diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2014-11-24 09:15:30 +0000 |
commit | 9f4dbff6669c8037f3b036bcf580d14f1a4f12a5 (patch) | |
tree | 47df2c12b57214af6c31e47404b005675b8b7ffc /lib | |
parent | f73d5f23a889b93d89ddef61ac0995df40286bb8 (diff) | |
download | src-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.tar.gz src-9f4dbff6669c8037f3b036bcf580d14f1a4f12a5.zip |
Vendor import of clang RELEASE_350/final tag r216957 (effectively, 3.5.0 release):vendor/clang/clang-release_350-r216957
Notes
Notes:
svn path=/vendor/clang/dist/; revision=274958
svn path=/vendor/clang/clang-release_350-r216957/; revision=274959; tag=vendor/clang/clang-release_350-r216957
Diffstat (limited to 'lib')
517 files changed, 80973 insertions, 50663 deletions
diff --git a/lib/ARCMigrate/ARCMT.cpp b/lib/ARCMigrate/ARCMT.cpp index 3e429beded5d..8a13b2ee4f1d 100644 --- a/lib/ARCMigrate/ARCMT.cpp +++ b/lib/ARCMigrate/ARCMT.cpp @@ -103,8 +103,8 @@ public: : Diags(diags), DiagClient(client), CapturedDiags(capturedDiags), HasBegunSourceFile(false) { } - virtual void BeginSourceFile(const LangOptions &Opts, - const Preprocessor *PP) { + void BeginSourceFile(const LangOptions &Opts, + const Preprocessor *PP) override { // Pass BeginSourceFile message onto DiagClient on first call. // The corresponding EndSourceFile call will be made from an // explicit call to FinishCapture. @@ -128,8 +128,8 @@ public: assert(!HasBegunSourceFile && "FinishCapture not called!"); } - virtual void HandleDiagnostic(DiagnosticsEngine::Level level, - const Diagnostic &Info) { + void HandleDiagnostic(DiagnosticsEngine::Level level, + const Diagnostic &Info) override { if (DiagnosticIDs::isARCDiagnostic(Info.getID()) || level >= DiagnosticsEngine::Error || level == DiagnosticsEngine::Note) { if (Info.getLocation().isValid()) @@ -167,7 +167,7 @@ static bool HasARCRuntime(CompilerInvocation &origCI) { static CompilerInvocation * createInvocationForMigration(CompilerInvocation &origCI) { - OwningPtr<CompilerInvocation> CInvok; + std::unique_ptr<CompilerInvocation> CInvok; CInvok.reset(new CompilerInvocation(origCI)); PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); if (!PPOpts.ImplicitPCHInclude.empty()) { @@ -204,11 +204,11 @@ createInvocationForMigration(CompilerInvocation &origCI) { WarnOpts.push_back(*I); } WarnOpts.push_back("error=arc-unsafe-retained-assign"); - CInvok->getDiagnosticOpts().Warnings = llvm_move(WarnOpts); + CInvok->getDiagnosticOpts().Warnings = std::move(WarnOpts); CInvok->getLangOpts()->ObjCARCWeak = HasARCRuntime(origCI); - return CInvok.take(); + return CInvok.release(); } static void emitPremigrationErrors(const CapturedDiagList &arcDiags, @@ -246,7 +246,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, NoFinalizeRemoval); assert(!transforms.empty()); - OwningPtr<CompilerInvocation> CInvok; + std::unique_ptr<CompilerInvocation> CInvok; CInvok.reset(createInvocationForMigration(origCI)); CInvok->getFrontendOpts().Inputs.clear(); CInvok->getFrontendOpts().Inputs.push_back(Input); @@ -263,8 +263,8 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); Diags->setClient(&errRec, /*ShouldOwnClient=*/false); - OwningPtr<ASTUnit> Unit( - ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags)); + std::unique_ptr<ASTUnit> Unit( + ASTUnit::LoadFromCompilerInvocationAction(CInvok.release(), Diags)); if (!Unit) { errRec.FinishCapture(); return true; @@ -310,8 +310,10 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, TransformActions testAct(*Diags, capturedDiags, Ctx, Unit->getPreprocessor()); MigrationPass pass(Ctx, OrigGCMode, Unit->getSema(), testAct, capturedDiags, ARCMTMacroLocs); - pass.setNSAllocReallocError(NoNSAllocReallocError); pass.setNoFinalizeRemoval(NoFinalizeRemoval); + if (!NoNSAllocReallocError) + Diags->setSeverity(diag::warn_arcmt_nsalloc_realloc, diag::Severity::Error, + SourceLocation()); for (unsigned i=0, e = transforms.size(); i != e; ++i) transforms[i](pass); @@ -416,44 +418,6 @@ bool arcmt::getFileRemappings(std::vector<std::pair<std::string,std::string> > & return false; } -bool arcmt::getFileRemappingsFromFileList( - std::vector<std::pair<std::string,std::string> > &remap, - ArrayRef<StringRef> remapFiles, - DiagnosticConsumer *DiagClient) { - bool hasErrorOccurred = false; - llvm::StringMap<bool> Uniquer; - - IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); - IntrusiveRefCntPtr<DiagnosticsEngine> Diags( - new DiagnosticsEngine(DiagID, new DiagnosticOptions, - DiagClient, /*ShouldOwnClient=*/false)); - - for (ArrayRef<StringRef>::iterator - I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) { - StringRef file = *I; - - FileRemapper remapper; - bool err = remapper.initFromFile(file, *Diags, - /*ignoreIfFilesChanged=*/true); - hasErrorOccurred = hasErrorOccurred || err; - if (err) - continue; - - PreprocessorOptions PPOpts; - remapper.applyMappings(PPOpts); - for (PreprocessorOptions::remapped_file_iterator - RI = PPOpts.remapped_file_begin(), RE = PPOpts.remapped_file_end(); - RI != RE; ++RI) { - bool &inserted = Uniquer[RI->first]; - if (inserted) - continue; - inserted = true; - remap.push_back(*RI); - } - } - - return hasErrorOccurred; -} //===----------------------------------------------------------------------===// // CollectTransformActions. @@ -468,8 +432,8 @@ public: ARCMTMacroTrackerPPCallbacks(std::vector<SourceLocation> &ARCMTMacroLocs) : ARCMTMacroLocs(ARCMTMacroLocs) { } - virtual void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, - SourceRange Range, const MacroArgs *Args) { + void MacroExpands(const Token &MacroNameTok, const MacroDirective *MD, + SourceRange Range, const MacroArgs *Args) override { if (MacroNameTok.getIdentifierInfo()->getName() == getARCMTMacroName()) ARCMTMacroLocs.push_back(MacroNameTok.getLocation()); } @@ -482,8 +446,8 @@ public: ARCMTMacroTrackerAction(std::vector<SourceLocation> &ARCMTMacroLocs) : ARCMTMacroLocs(ARCMTMacroLocs) { } - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) { + ASTConsumer *CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { CI.getPreprocessor().addPPCallbacks( new ARCMTMacroTrackerPPCallbacks(ARCMTMacroLocs)); return new ASTConsumer(); @@ -506,14 +470,14 @@ public: Listener->finish(); } - virtual void insert(SourceLocation loc, StringRef text) { + void insert(SourceLocation loc, StringRef text) override { bool err = rewriter.InsertText(loc, text, /*InsertAfter=*/true, /*indentNewLines=*/true); if (!err && Listener) Listener->insert(loc, text); } - virtual void remove(CharSourceRange range) { + void remove(CharSourceRange range) override { Rewriter::RewriteOptions removeOpts; removeOpts.IncludeInsertsAtBeginOfRange = false; removeOpts.IncludeInsertsAtEndOfRange = false; @@ -524,8 +488,8 @@ public: Listener->remove(range); } - virtual void increaseIndentation(CharSourceRange range, - SourceLocation parentIndent) { + void increaseIndentation(CharSourceRange range, + SourceLocation parentIndent) override { rewriter.IncreaseIndentation(range, parentIndent); } }; @@ -550,7 +514,7 @@ MigrationProcess::MigrationProcess(const CompilerInvocation &CI, bool MigrationProcess::applyTransform(TransformFn trans, RewriteListener *listener) { - OwningPtr<CompilerInvocation> CInvok; + std::unique_ptr<CompilerInvocation> CInvok; CInvok.reset(createInvocationForMigration(OrigCI)); CInvok->getDiagnosticOpts().IgnoreWarnings = true; @@ -569,12 +533,11 @@ bool MigrationProcess::applyTransform(TransformFn trans, CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); Diags->setClient(&errRec, /*ShouldOwnClient=*/false); - OwningPtr<ARCMTMacroTrackerAction> ASTAction; + std::unique_ptr<ARCMTMacroTrackerAction> ASTAction; ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs)); - OwningPtr<ASTUnit> Unit( - ASTUnit::LoadFromCompilerInvocationAction(CInvok.take(), Diags, - ASTAction.get())); + std::unique_ptr<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction( + CInvok.release(), Diags, ASTAction.get())); if (!Unit) { errRec.FinishCapture(); return true; diff --git a/lib/ARCMigrate/CMakeLists.txt b/lib/ARCMigrate/CMakeLists.txt index c55261277dd1..b716a20fe63f 100644 --- a/lib/ARCMigrate/CMakeLists.txt +++ b/lib/ARCMigrate/CMakeLists.txt @@ -1,3 +1,7 @@ +set(LLVM_LINK_COMPONENTS + Support + ) + add_clang_library(clangARCMigrate ARCMT.cpp ARCMTActions.cpp @@ -19,26 +23,16 @@ add_clang_library(clangARCMigrate TransZeroOutPropsInDealloc.cpp TransformActions.cpp Transforms.cpp - ) -add_dependencies(clangARCMigrate - ClangAttrClasses - ClangAttrList - ClangAttrParsedAttrList - ClangCommentNodes - ClangDeclNodes - ClangDiagnosticCommon - ClangDiagnosticGroups - ClangDiagnosticSema - ClangStmtNodes - ) - -target_link_libraries(clangARCMigrate - clangBasic + LINK_LIBS clangAST - clangParse + clangAnalysis + clangBasic + clangEdit clangFrontend - clangRewriteCore - clangRewriteFrontend + clangLex + clangRewrite + clangSema + clangSerialization clangStaticAnalyzerCheckers ) diff --git a/lib/ARCMigrate/FileRemapper.cpp b/lib/ARCMigrate/FileRemapper.cpp index a14226e43fe0..40e606090064 100644 --- a/lib/ARCMigrate/FileRemapper.cpp +++ b/lib/ARCMigrate/FileRemapper.cpp @@ -36,8 +36,7 @@ void FileRemapper::clear(StringRef outputDir) { assert(ToFromMappings.empty()); if (!outputDir.empty()) { std::string infoFile = getRemapInfoFile(outputDir); - bool existed; - llvm::sys::fs::remove(infoFile, existed); + llvm::sys::fs::remove(infoFile); } } @@ -65,13 +64,14 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag, return false; std::vector<std::pair<const FileEntry *, const FileEntry *> > pairs; - - OwningPtr<llvm::MemoryBuffer> fileBuf; - if (llvm::MemoryBuffer::getFile(infoFile.c_str(), fileBuf)) + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> fileBuf = + llvm::MemoryBuffer::getFile(infoFile.c_str()); + if (!fileBuf) return report("Error opening file: " + infoFile, Diag); SmallVector<StringRef, 64> lines; - fileBuf->getBuffer().split(lines, "\n"); + fileBuf.get()->getBuffer().split(lines, "\n"); for (unsigned idx = 0; idx+3 <= lines.size(); idx += 3) { StringRef fromFilename = lines[idx]; @@ -112,8 +112,7 @@ bool FileRemapper::initFromFile(StringRef filePath, DiagnosticsEngine &Diag, bool FileRemapper::flushToDisk(StringRef outputDir, DiagnosticsEngine &Diag) { using namespace llvm::sys; - bool existed; - if (fs::create_directory(outputDir, existed) != llvm::errc::success) + if (fs::create_directory(outputDir)) return report("Could not create directory: " + outputDir, Diag); std::string infoFile = getRemapInfoFile(outputDir); @@ -125,8 +124,7 @@ bool FileRemapper::flushToFile(StringRef outputPath, DiagnosticsEngine &Diag) { std::string errMsg; std::string infoFile = outputPath; - llvm::raw_fd_ostream infoOut(infoFile.c_str(), errMsg, - llvm::sys::fs::F_Binary); + llvm::raw_fd_ostream infoOut(infoFile.c_str(), errMsg, llvm::sys::fs::F_None); if (!errMsg.empty()) return report(errMsg, Diag); @@ -182,8 +180,7 @@ bool FileRemapper::overwriteOriginal(DiagnosticsEngine &Diag, Diag); std::string errMsg; - llvm::raw_fd_ostream Out(origFE->getName(), errMsg, - llvm::sys::fs::F_Binary); + llvm::raw_fd_ostream Out(origFE->getName(), errMsg, llvm::sys::fs::F_None); if (!errMsg.empty()) return report(errMsg, Diag); @@ -210,22 +207,6 @@ void FileRemapper::applyMappings(PreprocessorOptions &PPOpts) const { PPOpts.RetainRemappedFileBuffers = true; } -void FileRemapper::transferMappingsAndClear(PreprocessorOptions &PPOpts) { - for (MappingsTy::iterator - I = FromToMappings.begin(), E = FromToMappings.end(); I != E; ++I) { - if (const FileEntry *FE = I->second.dyn_cast<const FileEntry *>()) { - PPOpts.addRemappedFile(I->first->getName(), FE->getName()); - } else { - llvm::MemoryBuffer *mem = I->second.get<llvm::MemoryBuffer *>(); - PPOpts.addRemappedFile(I->first->getName(), mem); - } - I->second = Target(); - } - - PPOpts.RetainRemappedFileBuffers = false; - clear(); -} - void FileRemapper::remap(StringRef filePath, llvm::MemoryBuffer *memBuf) { remap(getOriginalFile(filePath), memBuf); } @@ -272,9 +253,7 @@ void FileRemapper::resetTarget(Target &targ) { } bool FileRemapper::report(const Twine &err, DiagnosticsEngine &Diag) { - SmallString<128> buf; - unsigned ID = Diag.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error, - err.toStringRef(buf)); - Diag.Report(ID); + Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")) + << err.str(); return true; } diff --git a/lib/ARCMigrate/Internals.h b/lib/ARCMigrate/Internals.h index 3690c83d8457..a65b329c5b03 100644 --- a/lib/ARCMigrate/Internals.h +++ b/lib/ARCMigrate/Internals.h @@ -48,7 +48,6 @@ void writeARCDiagsToPlist(const std::string &outPath, class TransformActions { DiagnosticsEngine &Diags; CapturedDiagList &CapturedDiags; - bool ReportedErrors; void *Impl; // TransformActionsImpl. public: @@ -95,6 +94,8 @@ public: return CapturedDiags.hasDiagnostic(IDs, range); } + DiagnosticBuilder report(SourceLocation loc, unsigned diagId, + SourceRange range = SourceRange()); void reportError(StringRef error, SourceLocation loc, SourceRange range = SourceRange()); void reportWarning(StringRef warning, SourceLocation loc, @@ -102,7 +103,9 @@ public: void reportNote(StringRef note, SourceLocation loc, SourceRange range = SourceRange()); - bool hasReportedErrors() const { return ReportedErrors; } + bool hasReportedErrors() const { + return Diags.hasUnrecoverableErrorOccurred(); + } class RewriteReceiver { public: @@ -161,8 +164,6 @@ public: const CapturedDiagList &getDiags() const { return CapturedDiags; } bool isGCMigration() const { return OrigGCMode != LangOptions::NonGC; } - bool noNSAllocReallocError() const { return MigOptions.NoNSAllocReallocError; } - void setNSAllocReallocError(bool val) { MigOptions.NoNSAllocReallocError = val; } bool noFinalizeRemoval() const { return MigOptions.NoFinalizeRemoval; } void setNoFinalizeRemoval(bool val) {MigOptions.NoFinalizeRemoval = val; } diff --git a/lib/ARCMigrate/ObjCMT.cpp b/lib/ARCMigrate/ObjCMT.cpp index cac0fb0aed1b..1a2055e9c452 100644 --- a/lib/ARCMigrate/ObjCMT.cpp +++ b/lib/ARCMigrate/ObjCMT.cpp @@ -8,12 +8,15 @@ //===----------------------------------------------------------------------===// #include "Transforms.h" +#include "clang/ARCMigrate/ARCMT.h" #include "clang/ARCMigrate/ARCMTActions.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/Attr.h" #include "clang/AST/NSAPI.h" #include "clang/AST/ParentMap.h" #include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/Basic/FileManager.h" #include "clang/Edit/Commit.h" #include "clang/Edit/EditedSource.h" @@ -24,11 +27,11 @@ #include "clang/Lex/PPConditionalDirectiveRecord.h" #include "clang/Lex/Preprocessor.h" #include "clang/Rewrite/Core/Rewriter.h" -#include "clang/Analysis/DomainSpecific/CocoaConventions.h" #include "clang/StaticAnalyzer/Checkers/ObjCRetainCount.h" -#include "clang/AST/Attr.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Path.h" +#include "llvm/Support/SourceMgr.h" +#include "llvm/Support/YAMLParser.h" using namespace clang; using namespace arcmt; @@ -45,7 +48,6 @@ class ObjCMigrateASTConsumer : public ASTConsumer { void migrateDecl(Decl *D); void migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D); - void migrateDeprecatedAnnotation(ASTContext &Ctx, ObjCCategoryDecl *CatDecl); void migrateProtocolConformance(ASTContext &Ctx, const ObjCImplementationDecl *ImpDecl); void CacheObjCNSIntegerTypedefed(const TypedefDecl *TypedefDcl); @@ -76,14 +78,18 @@ class ObjCMigrateASTConsumer : public ASTConsumer { void migrateAddMethodAnnotation(ASTContext &Ctx, const ObjCMethodDecl *MethodDecl); + + void inferDesignatedInitializers(ASTContext &Ctx, + const ObjCImplementationDecl *ImplD); + public: std::string MigrateDir; unsigned ASTMigrateActions; FileID FileId; const TypedefDecl *NSIntegerTypedefed; const TypedefDecl *NSUIntegerTypedefed; - OwningPtr<NSAPI> NSAPIObj; - OwningPtr<edit::EditedSource> Editor; + std::unique_ptr<NSAPI> NSAPIObj; + std::unique_ptr<edit::EditedSource> Editor; FileRemapper &Remapper; FileManager &FileMgr; const PPConditionalDirectiveRecord *PPRec; @@ -103,7 +109,7 @@ public: ArrayRef<std::string> WhiteList) : MigrateDir(migrateDir), ASTMigrateActions(astMigrateActions), - NSIntegerTypedefed(0), NSUIntegerTypedefed(0), + NSIntegerTypedefed(nullptr), NSUIntegerTypedefed(nullptr), Remapper(remapper), FileMgr(fileMgr), PPRec(PPRec), PP(PP), IsOutputFile(isOutputFile) { @@ -114,26 +120,26 @@ public: } protected: - virtual void Initialize(ASTContext &Context) { + void Initialize(ASTContext &Context) override { NSAPIObj.reset(new NSAPI(Context)); Editor.reset(new edit::EditedSource(Context.getSourceManager(), Context.getLangOpts(), - PPRec, false)); + PPRec)); } - virtual bool HandleTopLevelDecl(DeclGroupRef DG) { + bool HandleTopLevelDecl(DeclGroupRef DG) override { for (DeclGroupRef::iterator I = DG.begin(), E = DG.end(); I != E; ++I) migrateDecl(*I); return true; } - virtual void HandleInterestingDecl(DeclGroupRef DG) { + void HandleInterestingDecl(DeclGroupRef DG) override { // Ignore decls from the PCH. } - virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) { + void HandleTopLevelDeclInObjCContainer(DeclGroupRef DG) override { ObjCMigrateASTConsumer::HandleTopLevelDecl(DG); } - virtual void HandleTranslationUnit(ASTContext &Ctx); + void HandleTranslationUnit(ASTContext &Ctx) override; bool canModifyFile(StringRef Path) { if (WhiteListFilenames.empty()) @@ -141,6 +147,30 @@ protected: return WhiteListFilenames.find(llvm::sys::path::filename(Path)) != WhiteListFilenames.end(); } + bool canModifyFile(const FileEntry *FE) { + if (!FE) + return false; + return canModifyFile(FE->getName()); + } + bool canModifyFile(FileID FID) { + if (FID.isInvalid()) + return false; + return canModifyFile(PP.getSourceManager().getFileEntryForID(FID)); + } + + bool canModify(const Decl *D) { + if (!D) + return false; + if (const ObjCCategoryImplDecl *CatImpl = dyn_cast<ObjCCategoryImplDecl>(D)) + return canModify(CatImpl->getCategoryDecl()); + if (const ObjCImplementationDecl *Impl = dyn_cast<ObjCImplementationDecl>(D)) + return canModify(Impl->getClassInterface()); + if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) + return canModify(cast<Decl>(MD->getDeclContext())); + + FileID FID = PP.getSourceManager().getFileID(D->getLocation()); + return canModifyFile(FID); + } }; } @@ -150,7 +180,7 @@ ObjCMigrateAction::ObjCMigrateAction(FrontendAction *WrappedAction, unsigned migrateAction) : WrapperFrontendAction(WrappedAction), MigrateDir(migrateDir), ObjCMigAction(migrateAction), - CompInst(0) { + CompInst(nullptr) { if (MigrateDir.empty()) MigrateDir = "."; // user current directory if none is given. } @@ -223,7 +253,7 @@ public: class BodyMigrator : public RecursiveASTVisitor<BodyMigrator> { ObjCMigrateASTConsumer &Consumer; - OwningPtr<ParentMap> PMap; + std::unique_ptr<ParentMap> PMap; public: BodyMigrator(ObjCMigrateASTConsumer &consumer) : Consumer(consumer) { } @@ -294,7 +324,9 @@ void MigrateBlockOrFunctionPointerTypeVariable(std::string & PropertyString, static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType) { Qualifiers::ObjCLifetime propertyLifetime = ArgType.getObjCLifetime(); bool RetainableObject = ArgType->isObjCRetainableType(); - if (RetainableObject && propertyLifetime == Qualifiers::OCL_Strong) { + if (RetainableObject && + (propertyLifetime == Qualifiers::OCL_Strong + || propertyLifetime == Qualifiers::OCL_None)) { if (const ObjCObjectPointerType *ObjPtrTy = ArgType->getAs<ObjCObjectPointerType>()) { ObjCInterfaceDecl *IDecl = ObjPtrTy->getObjectType()->getInterface(); @@ -302,7 +334,7 @@ static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType IDecl->lookupNestedProtocol(&Context.Idents.get("NSCopying"))) return "copy"; else - return "retain"; + return "strong"; } else if (ArgType->isBlockPointerType()) return "copy"; @@ -311,8 +343,8 @@ static const char *PropertyMemoryAttribute(ASTContext &Context, QualType ArgType // looking into setter's implementation for backing weak ivar. return "weak"; else if (RetainableObject) - return ArgType->isBlockPointerType() ? "copy" : "retain"; - return 0; + return ArgType->isBlockPointerType() ? "copy" : "strong"; + return nullptr; } static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, @@ -344,23 +376,23 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, PropertyString += PropertyNameString; } // Property with no setter may be suggested as a 'readonly' property. - if (!Setter) { + if (!Setter) append_attr(PropertyString, "readonly", LParenAdded); - QualType ResType = Context.getCanonicalType(Getter->getResultType()); - if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType)) - append_attr(PropertyString, MemoryManagementAttr, LParenAdded); - } + // Short circuit 'delegate' properties that contain the name "delegate" or // "dataSource", or have exact name "target" to have 'assign' attribute. if (PropertyName.equals("target") || (PropertyName.find("delegate") != StringRef::npos) || (PropertyName.find("dataSource") != StringRef::npos)) { - QualType QT = Getter->getResultType(); + QualType QT = Getter->getReturnType(); if (!QT->isRealType()) append_attr(PropertyString, "assign", LParenAdded); - } - else if (Setter) { + } else if (!Setter) { + QualType ResType = Context.getCanonicalType(Getter->getReturnType()); + if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ResType)) + append_attr(PropertyString, MemoryManagementAttr, LParenAdded); + } else { const ParmVarDecl *argDecl = *Setter->param_begin(); QualType ArgType = Context.getCanonicalType(argDecl->getType()); if (const char *MemoryManagementAttr = PropertyMemoryAttribute(Context, ArgType)) @@ -368,7 +400,7 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, } if (LParenAdded) PropertyString += ')'; - QualType RT = Getter->getResultType(); + QualType RT = Getter->getReturnType(); if (!isa<TypedefType>(RT)) { // strip off any ARC lifetime qualifier. QualType CanResultTy = Context.getCanonicalType(RT); @@ -419,21 +451,27 @@ static void rewriteToObjCProperty(const ObjCMethodDecl *Getter, // Get location past ';' EndLoc = EndLoc.getLocWithOffset(1); SourceLocation BeginOfSetterDclLoc = Setter->getLocStart(); - // FIXME. This assumes that setter decl; is immediately preceeded by eoln. + // FIXME. This assumes that setter decl; is immediately preceded by eoln. // It is trying to remove the setter method decl. line entirely. BeginOfSetterDclLoc = BeginOfSetterDclLoc.getLocWithOffset(-1); commit.remove(SourceRange(BeginOfSetterDclLoc, EndLoc)); } } +static bool IsCategoryNameWithDeprecatedSuffix(ObjCContainerDecl *D) { + if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(D)) { + StringRef Name = CatDecl->getName(); + return Name.endswith("Deprecated"); + } + return false; +} + void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, ObjCContainerDecl *D) { - if (D->isDeprecated()) + if (D->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(D)) return; - - for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); - M != MEnd; ++M) { - ObjCMethodDecl *Method = (*M); + + for (auto *Method : D->methods()) { if (Method->isDeprecated()) continue; bool PropertyInferred = migrateProperty(Ctx, D, Method); @@ -448,48 +486,13 @@ void ObjCMigrateASTConsumer::migrateObjCInterfaceDecl(ASTContext &Ctx, if (!(ASTMigrateActions & FrontendOptions::ObjCMT_ReturnsInnerPointerProperty)) return; - for (ObjCContainerDecl::prop_iterator P = D->prop_begin(), - E = D->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; + for (auto *Prop : D->properties()) { if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && !Prop->isDeprecated()) migratePropertyNsReturnsInnerPointer(Ctx, Prop); } } -void ObjCMigrateASTConsumer::migrateDeprecatedAnnotation(ASTContext &Ctx, - ObjCCategoryDecl *CatDecl) { - StringRef Name = CatDecl->getName(); - if (!Name.endswith("Deprecated")) - return; - - if (!Ctx.Idents.get("DEPRECATED").hasMacroDefinition()) - return; - - ObjCContainerDecl *D = cast<ObjCContainerDecl>(CatDecl); - - for (ObjCContainerDecl::method_iterator M = D->meth_begin(), MEnd = D->meth_end(); - M != MEnd; ++M) { - ObjCMethodDecl *Method = (*M); - if (Method->isDeprecated() || Method->isImplicit()) - continue; - // Annotate with DEPRECATED - edit::Commit commit(*Editor); - commit.insertBefore(Method->getLocEnd(), " DEPRECATED"); - Editor->commit(commit); - } - for (ObjCContainerDecl::prop_iterator P = D->prop_begin(), - E = D->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Prop = *P; - if (Prop->isDeprecated()) - continue; - // Annotate with DEPRECATED - edit::Commit commit(*Editor); - commit.insertAfterToken(Prop->getLocEnd(), " DEPRECATED"); - Editor->commit(commit); - } -} - static bool ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, const ObjCImplementationDecl *ImpDecl, @@ -500,9 +503,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, // in class interface. bool HasAtleastOneRequiredProperty = false; if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) - for (ObjCProtocolDecl::prop_iterator P = PDecl->prop_begin(), - E = PDecl->prop_end(); P != E; ++P) { - ObjCPropertyDecl *Property = *P; + for (const auto *Property : PDecl->properties()) { if (Property->getPropertyImplementation() == ObjCPropertyDecl::Optional) continue; HasAtleastOneRequiredProperty = true; @@ -532,9 +533,7 @@ ClassImplementsAllMethodsAndProperties(ASTContext &Ctx, if (const ObjCProtocolDecl *PDecl = Protocol->getDefinition()) { if (PDecl->meth_begin() == PDecl->meth_end()) return HasAtleastOneRequiredProperty; - for (ObjCContainerDecl::method_iterator M = PDecl->meth_begin(), - MEnd = PDecl->meth_end(); M != MEnd; ++M) { - ObjCMethodDecl *MD = (*M); + for (const auto *MD : PDecl->methods()) { if (MD->isImplicit()) continue; if (MD->getImplementationControl() == ObjCMethodDecl::Optional) @@ -632,7 +631,7 @@ static bool rewriteToNSEnumDecl(const EnumDecl *EnumDcl, /*IsDecl*/true); if (!EndOfEnumDclLoc.isInvalid()) { SourceLocation BeginOfEnumDclLoc = EnumDcl->getLocStart(); - // FIXME. This assumes that enum decl; is immediately preceeded by eoln. + // FIXME. This assumes that enum decl; is immediately preceded by eoln. // It is trying to remove the enum decl. lines entirely. BeginOfEnumDclLoc = BeginOfEnumDclLoc.getLocWithOffset(-1); commit.remove(SourceRange(BeginOfEnumDclLoc, EndOfEnumDclLoc)); @@ -660,9 +659,7 @@ static bool UseNSOptionsMacro(Preprocessor &PP, ASTContext &Ctx, bool PowerOfTwo = true; bool AllHexdecimalEnumerator = true; uint64_t MaxPowerOfTwoVal = 0; - for (EnumDecl::enumerator_iterator EI = EnumDcl->enumerator_begin(), - EE = EnumDcl->enumerator_end(); EI != EE; ++EI) { - EnumConstantDecl *Enumerator = (*EI); + for (auto Enumerator : EnumDcl->enumerators()) { const Expr *InitExpr = Enumerator->getInitExpr(); if (!InitExpr) { PowerOfTwo = false; @@ -749,6 +746,8 @@ void ObjCMigrateASTConsumer::migrateProtocolConformance(ASTContext &Ctx, if (!DropIt) MinimalConformingProtocols.push_back(TargetPDecl); } + if (MinimalConformingProtocols.empty()) + return; edit::Commit commit(*Editor); rewriteToObjCInterfaceDecl(IDecl, MinimalConformingProtocols, *NSAPIObj, commit); @@ -774,11 +773,11 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, if (!TypedefDcl) { if (NSIntegerTypedefed) { TypedefDcl = NSIntegerTypedefed; - NSIntegerTypedefed = 0; + NSIntegerTypedefed = nullptr; } else if (NSUIntegerTypedefed) { TypedefDcl = NSUIntegerTypedefed; - NSUIntegerTypedefed = 0; + NSUIntegerTypedefed = nullptr; } else return false; @@ -831,11 +830,15 @@ bool ObjCMigrateASTConsumer::migrateNSEnumDecl(ASTContext &Ctx, return Res; } -static void ReplaceWithInstancetype(const ObjCMigrateASTConsumer &ASTC, +static void ReplaceWithInstancetype(ASTContext &Ctx, + const ObjCMigrateASTConsumer &ASTC, ObjCMethodDecl *OM) { + if (OM->getReturnType() == Ctx.getObjCInstanceType()) + return; // already has instancetype. + SourceRange R; std::string ClassString; - if (TypeSourceInfo *TSInfo = OM->getResultTypeSourceInfo()) { + if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc(); R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); ClassString = "instancetype"; @@ -855,7 +858,7 @@ static void ReplaceWithClasstype(const ObjCMigrateASTConsumer &ASTC, ObjCInterfaceDecl *IDecl = OM->getClassInterface(); SourceRange R; std::string ClassString; - if (TypeSourceInfo *TSInfo = OM->getResultTypeSourceInfo()) { + if (TypeSourceInfo *TSInfo = OM->getReturnTypeSourceInfo()) { TypeLoc TL = TSInfo->getTypeLoc(); R = SourceRange(TL.getBeginLoc(), TL.getEndLoc()); { ClassString = IDecl->getName(); @@ -893,14 +896,14 @@ void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, migrateFactoryMethod(Ctx, CDecl, OM, OIT_Singleton); return; case OIT_Init: - if (OM->getResultType()->isObjCIdType()) - ReplaceWithInstancetype(*this, OM); + if (OM->getReturnType()->isObjCIdType()) + ReplaceWithInstancetype(Ctx, *this, OM); return; case OIT_ReturnsSelf: migrateFactoryMethod(Ctx, CDecl, OM, OIT_ReturnsSelf); return; } - if (!OM->getResultType()->isObjCIdType()) + if (!OM->getReturnType()->isObjCIdType()) return; ObjCInterfaceDecl *IDecl = dyn_cast<ObjCInterfaceDecl>(CDecl); @@ -915,7 +918,7 @@ void ObjCMigrateASTConsumer::migrateMethodInstanceType(ASTContext &Ctx, migrateFactoryMethod(Ctx, CDecl, OM); return; } - ReplaceWithInstancetype(*this, OM); + ReplaceWithInstancetype(Ctx, *this, OM); } static bool TypeIsInnerPointer(QualType T) { @@ -1034,7 +1037,7 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, Method->param_size() != 0) return false; // Is this method candidate to be a getter? - QualType GRT = Method->getResultType(); + QualType GRT = Method->getReturnType(); if (GRT->isVoidType()) return false; @@ -1087,7 +1090,7 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, return false; // Is this a valid setter, matching the target getter? - QualType SRT = SetterMethod->getResultType(); + QualType SRT = SetterMethod->getReturnType(); if (!SRT->isVoidType()) return false; const ParmVarDecl *argDecl = *SetterMethod->param_begin(); @@ -1109,7 +1112,7 @@ bool ObjCMigrateASTConsumer::migrateProperty(ASTContext &Ctx, // Try a non-void method with no argument (and no setter or property of same name // as a 'readonly' property. edit::Commit commit(*Editor); - rewriteToObjCProperty(Method, 0 /*SetterMethod*/, *NSAPIObj, commit, + rewriteToObjCProperty(Method, nullptr /*SetterMethod*/, *NSAPIObj, commit, LengthOfPrefix, (ASTMigrateActions & FrontendOptions::ObjCMT_AtomicProperty) != 0, @@ -1128,8 +1131,8 @@ void ObjCMigrateASTConsumer::migrateNsReturnsInnerPointer(ASTContext &Ctx, !OM->isInstanceMethod() || OM->hasAttr<ObjCReturnsInnerPointerAttr>()) return; - - QualType RT = OM->getResultType(); + + QualType RT = OM->getReturnType(); if (!TypeIsInnerPointer(RT) || !Ctx.Idents.get("NS_RETURNS_INNER_POINTER").hasMacroDefinition()) return; @@ -1153,14 +1156,11 @@ void ObjCMigrateASTConsumer::migratePropertyNsReturnsInnerPointer(ASTContext &Ct void ObjCMigrateASTConsumer::migrateAllMethodInstaceType(ASTContext &Ctx, ObjCContainerDecl *CDecl) { - if (CDecl->isDeprecated()) + if (CDecl->isDeprecated() || IsCategoryNameWithDeprecatedSuffix(CDecl)) return; // migrate methods which can have instancetype as their result type. - for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(), - MEnd = CDecl->meth_end(); - M != MEnd; ++M) { - ObjCMethodDecl *Method = (*M); + for (auto *Method : CDecl->methods()) { if (Method->isDeprecated()) continue; migrateMethodInstanceType(Ctx, CDecl, Method); @@ -1172,8 +1172,8 @@ void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx, ObjCMethodDecl *OM, ObjCInstanceTypeFamily OIT_Family) { if (OM->isInstanceMethod() || - OM->getResultType() == Ctx.getObjCInstanceType() || - !OM->getResultType()->isObjCIdType()) + OM->getReturnType() == Ctx.getObjCInstanceType() || + !OM->getReturnType()->isObjCIdType()) return; // Candidate factory methods are + (id) NaMeXXX : ... which belong to a class @@ -1228,7 +1228,7 @@ void ObjCMigrateASTConsumer::migrateFactoryMethod(ASTContext &Ctx, if (OIT_Family == OIT_ReturnsSelf) ReplaceWithClasstype(*this, OM); else - ReplaceWithInstancetype(*this, OM); + ReplaceWithInstancetype(Ctx, *this, OM); } static bool IsVoidStarType(QualType Ty) { @@ -1338,7 +1338,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, // Annotate function. if (!ResultAnnotated) { RetEffect Ret = CE.getReturnValue(); - const char *AnnotationString = 0; + const char *AnnotationString = nullptr; if (Ret.getObjKind() == RetEffect::CF) { if (Ret.isOwned() && Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition()) @@ -1359,19 +1359,19 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, Editor->commit(commit); } } - llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); + ArrayRef<ArgEffect> AEArgs = CE.getArgs(); unsigned i = 0; for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), pe = FuncDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() && + if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() && Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); Editor->commit(commit); } - else if (AE == DecRefMsg && !pd->getAttr<NSConsumedAttr>() && + else if (AE == DecRefMsg && !pd->hasAttr<NSConsumedAttr>() && Ctx.Idents.get("NS_CONSUMED").hasMacroDefinition()) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "NS_CONSUMED "); @@ -1389,11 +1389,11 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND return CF_BRIDGING_NONE; CallEffects CE = CallEffects::getEffect(FuncDecl); - bool FuncIsReturnAnnotated = (FuncDecl->getAttr<CFReturnsRetainedAttr>() || - FuncDecl->getAttr<CFReturnsNotRetainedAttr>() || - FuncDecl->getAttr<NSReturnsRetainedAttr>() || - FuncDecl->getAttr<NSReturnsNotRetainedAttr>() || - FuncDecl->getAttr<NSReturnsAutoreleasedAttr>()); + bool FuncIsReturnAnnotated = (FuncDecl->hasAttr<CFReturnsRetainedAttr>() || + FuncDecl->hasAttr<CFReturnsNotRetainedAttr>() || + FuncDecl->hasAttr<NSReturnsRetainedAttr>() || + FuncDecl->hasAttr<NSReturnsNotRetainedAttr>() || + FuncDecl->hasAttr<NSReturnsAutoreleasedAttr>()); // Trivial case of when funciton is annotated and has no argument. if (FuncIsReturnAnnotated && FuncDecl->getNumParams() == 0) @@ -1405,13 +1405,13 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND if (Ret.getObjKind() == RetEffect::CF && (Ret.isOwned() || Ret.notOwned())) ReturnCFAudited = true; - else if (!AuditedType(FuncDecl->getResultType())) + else if (!AuditedType(FuncDecl->getReturnType())) return CF_BRIDGING_NONE; } // At this point result type is audited for potential inclusion. // Now, how about argument types. - llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); + ArrayRef<ArgEffect> AEArgs = CE.getArgs(); unsigned i = 0; bool ArgCFAudited = false; for (FunctionDecl::param_const_iterator pi = FuncDecl->param_begin(), @@ -1419,7 +1419,7 @@ ObjCMigrateASTConsumer::CF_BRIDGING_KIND const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; if (AE == DecRef /*CFConsumed annotated*/ || AE == IncRef) { - if (AE == DecRef && !pd->getAttr<CFConsumedAttr>()) + if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) ArgCFAudited = true; else if (AE == IncRef) ArgCFAudited = true; @@ -1444,12 +1444,8 @@ void ObjCMigrateASTConsumer::migrateARCSafeAnnotation(ASTContext &Ctx, return; // migrate methods which can have instancetype as their result type. - for (ObjCContainerDecl::method_iterator M = CDecl->meth_begin(), - MEnd = CDecl->meth_end(); - M != MEnd; ++M) { - ObjCMethodDecl *Method = (*M); + for (const auto *Method : CDecl->methods()) migrateCFAnnotation(Ctx, Method); - } } void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, @@ -1459,7 +1455,7 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, // Annotate function. if (!ResultAnnotated) { RetEffect Ret = CE.getReturnValue(); - const char *AnnotationString = 0; + const char *AnnotationString = nullptr; if (Ret.getObjKind() == RetEffect::CF) { if (Ret.isOwned() && Ctx.Idents.get("CF_RETURNS_RETAINED").hasMacroDefinition()) @@ -1492,13 +1488,13 @@ void ObjCMigrateASTConsumer::AddCFAnnotations(ASTContext &Ctx, Editor->commit(commit); } } - llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); + ArrayRef<ArgEffect> AEArgs = CE.getArgs(); unsigned i = 0; for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if (AE == DecRef && !pd->getAttr<CFConsumedAttr>() && + if (AE == DecRef && !pd->hasAttr<CFConsumedAttr>() && Ctx.Idents.get("CF_CONSUMED").hasMacroDefinition()) { edit::Commit commit(*Editor); commit.insertBefore(pd->getLocation(), "CF_CONSUMED "); @@ -1514,14 +1510,14 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation( return; CallEffects CE = CallEffects::getEffect(MethodDecl); - bool MethodIsReturnAnnotated = (MethodDecl->getAttr<CFReturnsRetainedAttr>() || - MethodDecl->getAttr<CFReturnsNotRetainedAttr>() || - MethodDecl->getAttr<NSReturnsRetainedAttr>() || - MethodDecl->getAttr<NSReturnsNotRetainedAttr>() || - MethodDecl->getAttr<NSReturnsAutoreleasedAttr>()); + bool MethodIsReturnAnnotated = (MethodDecl->hasAttr<CFReturnsRetainedAttr>() || + MethodDecl->hasAttr<CFReturnsNotRetainedAttr>() || + MethodDecl->hasAttr<NSReturnsRetainedAttr>() || + MethodDecl->hasAttr<NSReturnsNotRetainedAttr>() || + MethodDecl->hasAttr<NSReturnsAutoreleasedAttr>()); if (CE.getReceiver() == DecRefMsg && - !MethodDecl->getAttr<NSConsumesSelfAttr>() && + !MethodDecl->hasAttr<NSConsumesSelfAttr>() && MethodDecl->getMethodFamily() != OMF_init && MethodDecl->getMethodFamily() != OMF_release && Ctx.Idents.get("NS_CONSUMES_SELF").hasMacroDefinition()) { @@ -1542,20 +1538,19 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation( (Ret.isOwned() || Ret.notOwned())) { AddCFAnnotations(Ctx, CE, MethodDecl, false); return; - } - else if (!AuditedType(MethodDecl->getResultType())) + } else if (!AuditedType(MethodDecl->getReturnType())) return; } // At this point result type is either annotated or audited. // Now, how about argument types. - llvm::ArrayRef<ArgEffect> AEArgs = CE.getArgs(); + ArrayRef<ArgEffect> AEArgs = CE.getArgs(); unsigned i = 0; for (ObjCMethodDecl::param_const_iterator pi = MethodDecl->param_begin(), pe = MethodDecl->param_end(); pi != pe; ++pi, ++i) { const ParmVarDecl *pd = *pi; ArgEffect AE = AEArgs[i]; - if ((AE == DecRef && !pd->getAttr<CFConsumedAttr>()) || AE == IncRef || + if ((AE == DecRef && !pd->hasAttr<CFConsumedAttr>()) || AE == IncRef || !AuditedType(pd->getType())) { AddCFAnnotations(Ctx, CE, MethodDecl, MethodIsReturnAnnotated); return; @@ -1565,6 +1560,53 @@ void ObjCMigrateASTConsumer::migrateAddMethodAnnotation( } namespace { +class SuperInitChecker : public RecursiveASTVisitor<SuperInitChecker> { +public: + bool shouldVisitTemplateInstantiations() const { return false; } + bool shouldWalkTypesOfTypeLocs() const { return false; } + + bool VisitObjCMessageExpr(ObjCMessageExpr *E) { + if (E->getReceiverKind() == ObjCMessageExpr::SuperInstance) { + if (E->getMethodFamily() == OMF_init) + return false; + } + return true; + } +}; +} // anonymous namespace + +static bool hasSuperInitCall(const ObjCMethodDecl *MD) { + return !SuperInitChecker().TraverseStmt(MD->getBody()); +} + +void ObjCMigrateASTConsumer::inferDesignatedInitializers( + ASTContext &Ctx, + const ObjCImplementationDecl *ImplD) { + + const ObjCInterfaceDecl *IFace = ImplD->getClassInterface(); + if (!IFace || IFace->hasDesignatedInitializers()) + return; + if (!Ctx.Idents.get("NS_DESIGNATED_INITIALIZER").hasMacroDefinition()) + return; + + for (const auto *MD : ImplD->instance_methods()) { + if (MD->isDeprecated() || + MD->getMethodFamily() != OMF_init || + MD->isDesignatedInitializerForTheInterface()) + continue; + const ObjCMethodDecl *IFaceM = IFace->getMethod(MD->getSelector(), + /*isInstance=*/true); + if (!IFaceM) + continue; + if (hasSuperInitCall(MD)) { + edit::Commit commit(*Editor); + commit.insert(IFaceM->getLocEnd(), " NS_DESIGNATED_INITIALIZER"); + Editor->commit(commit); + } + } +} + +namespace { class RewritesReceiver : public edit::EditsReceiver { Rewriter &Rewrite; @@ -1572,42 +1614,92 @@ class RewritesReceiver : public edit::EditsReceiver { public: RewritesReceiver(Rewriter &Rewrite) : Rewrite(Rewrite) { } - virtual void insert(SourceLocation loc, StringRef text) { + void insert(SourceLocation loc, StringRef text) override { Rewrite.InsertText(loc, text); } - virtual void replace(CharSourceRange range, StringRef text) { + void replace(CharSourceRange range, StringRef text) override { Rewrite.ReplaceText(range.getBegin(), Rewrite.getRangeSize(range), text); } }; -} +class JSONEditWriter : public edit::EditsReceiver { + SourceManager &SourceMgr; + llvm::raw_ostream &OS; -static bool -IsReallyASystemHeader(ASTContext &Ctx, const FileEntry *file, FileID FID) { - bool Invalid = false; - const SrcMgr::SLocEntry &SEntry = - Ctx.getSourceManager().getSLocEntry(FID, &Invalid); - if (!Invalid && SEntry.isFile()) { - const SrcMgr::FileInfo &FI = SEntry.getFile(); - if (!FI.hasLineDirectives()) { - if (FI.getFileCharacteristic() == SrcMgr::C_ExternCSystem) - return true; - if (FI.getFileCharacteristic() == SrcMgr::C_System) { - // This file is in a system header directory. Continue with commiting change - // only if it is a user specified system directory because user put a - // .system_framework file in the framework directory. - StringRef Directory(file->getDir()->getName()); - size_t Ix = Directory.rfind(".framework"); - if (Ix == StringRef::npos) - return true; - std::string PatchToSystemFramework = Directory.slice(0, Ix+sizeof(".framework")); - PatchToSystemFramework += ".system_framework"; - if (!llvm::sys::fs::exists(PatchToSystemFramework.data())) - return true; - } +public: + JSONEditWriter(SourceManager &SM, llvm::raw_ostream &OS) + : SourceMgr(SM), OS(OS) { + OS << "[\n"; + } + ~JSONEditWriter() { + OS << "]\n"; + } + +private: + struct EntryWriter { + SourceManager &SourceMgr; + llvm::raw_ostream &OS; + + EntryWriter(SourceManager &SM, llvm::raw_ostream &OS) + : SourceMgr(SM), OS(OS) { + OS << " {\n"; + } + ~EntryWriter() { + OS << " },\n"; } + + void writeLoc(SourceLocation Loc) { + FileID FID; + unsigned Offset; + std::tie(FID, Offset) = SourceMgr.getDecomposedLoc(Loc); + assert(!FID.isInvalid()); + SmallString<200> Path = + StringRef(SourceMgr.getFileEntryForID(FID)->getName()); + llvm::sys::fs::make_absolute(Path); + OS << " \"file\": \""; + OS.write_escaped(Path.str()) << "\",\n"; + OS << " \"offset\": " << Offset << ",\n"; + } + + void writeRemove(CharSourceRange Range) { + assert(Range.isCharRange()); + std::pair<FileID, unsigned> Begin = + SourceMgr.getDecomposedLoc(Range.getBegin()); + std::pair<FileID, unsigned> End = + SourceMgr.getDecomposedLoc(Range.getEnd()); + assert(Begin.first == End.first); + assert(Begin.second <= End.second); + unsigned Length = End.second - Begin.second; + + OS << " \"remove\": " << Length << ",\n"; + } + + void writeText(StringRef Text) { + OS << " \"text\": \""; + OS.write_escaped(Text) << "\",\n"; + } + }; + + void insert(SourceLocation Loc, StringRef Text) override { + EntryWriter Writer(SourceMgr, OS); + Writer.writeLoc(Loc); + Writer.writeText(Text); } - return false; + + void replace(CharSourceRange Range, StringRef Text) override { + EntryWriter Writer(SourceMgr, OS); + Writer.writeLoc(Range.getBegin()); + Writer.writeRemove(Range); + Writer.writeText(Text); + } + + void remove(CharSourceRange Range) override { + EntryWriter Writer(SourceMgr, OS); + Writer.writeLoc(Range.getBegin()); + Writer.writeRemove(Range); + } +}; + } void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { @@ -1624,22 +1716,25 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { } if (ObjCInterfaceDecl *CDecl = dyn_cast<ObjCInterfaceDecl>(*D)) - migrateObjCInterfaceDecl(Ctx, CDecl); + if (canModify(CDecl)) + migrateObjCInterfaceDecl(Ctx, CDecl); if (ObjCCategoryDecl *CatDecl = dyn_cast<ObjCCategoryDecl>(*D)) { - migrateObjCInterfaceDecl(Ctx, CatDecl); - if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) - migrateDeprecatedAnnotation(Ctx, CatDecl); + if (canModify(CatDecl)) + migrateObjCInterfaceDecl(Ctx, CatDecl); } else if (ObjCProtocolDecl *PDecl = dyn_cast<ObjCProtocolDecl>(*D)) - ObjCProtocolDecls.insert(PDecl); + ObjCProtocolDecls.insert(PDecl->getCanonicalDecl()); else if (const ObjCImplementationDecl *ImpDecl = dyn_cast<ObjCImplementationDecl>(*D)) { - if (ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) + if ((ASTMigrateActions & FrontendOptions::ObjCMT_ProtocolConformance) && + canModify(ImpDecl)) migrateProtocolConformance(Ctx, ImpDecl); } else if (const EnumDecl *ED = dyn_cast<EnumDecl>(*D)) { if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros)) continue; + if (!canModify(ED)) + continue; DeclContext::decl_iterator N = D; if (++N != DEnd) { const TypedefDecl *TD = dyn_cast<TypedefDecl>(*N); @@ -1647,11 +1742,13 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { D++; } else - migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */0); + migrateNSEnumDecl(Ctx, ED, /*TypedefDecl */nullptr); } else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(*D)) { if (!(ASTMigrateActions & FrontendOptions::ObjCMT_NsMacros)) continue; + if (!canModify(TD)) + continue; DeclContext::decl_iterator N = D; if (++N == DEnd) continue; @@ -1673,23 +1770,49 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { CacheObjCNSIntegerTypedefed(TD); } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*D)) { - if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) + if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && + canModify(FD)) migrateCFAnnotation(Ctx, FD); } if (ObjCContainerDecl *CDecl = dyn_cast<ObjCContainerDecl>(*D)) { + bool CanModify = canModify(CDecl); // migrate methods which can have instancetype as their result type. - if (ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) + if ((ASTMigrateActions & FrontendOptions::ObjCMT_Instancetype) && + CanModify) migrateAllMethodInstaceType(Ctx, CDecl); // annotate methods with CF annotations. - if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) + if ((ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) && + CanModify) migrateARCSafeAnnotation(Ctx, CDecl); } + + if (const ObjCImplementationDecl * + ImplD = dyn_cast<ObjCImplementationDecl>(*D)) { + if ((ASTMigrateActions & FrontendOptions::ObjCMT_DesignatedInitializer) && + canModify(ImplD)) + inferDesignatedInitializers(Ctx, ImplD); + } } if (ASTMigrateActions & FrontendOptions::ObjCMT_Annotation) AnnotateImplicitBridging(Ctx); } + if (IsOutputFile) { + std::string Error; + llvm::raw_fd_ostream OS(MigrateDir.c_str(), Error, llvm::sys::fs::F_None); + if (!Error.empty()) { + DiagnosticsEngine &Diags = Ctx.getDiagnostics(); + Diags.Report(Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0")) + << Error; + return; + } + + JSONEditWriter Writer(Ctx.getSourceManager(), OS); + Editor->applyRewrites(Writer); + return; + } + Rewriter rewriter(Ctx.getSourceManager(), Ctx.getLangOpts()); RewritesReceiver Rec(rewriter); Editor->applyRewrites(Rec); @@ -1700,10 +1823,6 @@ void ObjCMigrateASTConsumer::HandleTranslationUnit(ASTContext &Ctx) { RewriteBuffer &buf = I->second; const FileEntry *file = Ctx.getSourceManager().getFileEntryForID(FID); assert(file); - if (IsReallyASystemHeader(Ctx, file, FID)) - continue; - if (!canModifyFile(file->getName())) - continue; SmallString<512> newText; llvm::raw_svector_ostream vecOS(newText); buf.write(vecOS); @@ -1734,8 +1853,8 @@ static std::vector<std::string> getWhiteListFilenames(StringRef DirPath) { std::vector<std::string> Filenames; if (DirPath.empty() || !is_directory(DirPath)) return Filenames; - - llvm::error_code EC; + + std::error_code EC; directory_iterator DI = directory_iterator(DirPath, EC); directory_iterator DE; for (; !EC && DI != DE; DI = DI.increment(EC)) { @@ -1773,3 +1892,246 @@ ASTConsumer *MigrateSourceAction::CreateASTConsumer(CompilerInstance &CI, /*isOutputFile=*/true, WhiteList); } + +namespace { +struct EditEntry { + const FileEntry *File; + unsigned Offset; + unsigned RemoveLen; + std::string Text; + + EditEntry() : File(), Offset(), RemoveLen() {} +}; +} + +namespace llvm { +template<> struct DenseMapInfo<EditEntry> { + static inline EditEntry getEmptyKey() { + EditEntry Entry; + Entry.Offset = unsigned(-1); + return Entry; + } + static inline EditEntry getTombstoneKey() { + EditEntry Entry; + Entry.Offset = unsigned(-2); + return Entry; + } + static unsigned getHashValue(const EditEntry& Val) { + llvm::FoldingSetNodeID ID; + ID.AddPointer(Val.File); + ID.AddInteger(Val.Offset); + ID.AddInteger(Val.RemoveLen); + ID.AddString(Val.Text); + return ID.ComputeHash(); + } + static bool isEqual(const EditEntry &LHS, const EditEntry &RHS) { + return LHS.File == RHS.File && + LHS.Offset == RHS.Offset && + LHS.RemoveLen == RHS.RemoveLen && + LHS.Text == RHS.Text; + } +}; +} + +namespace { +class RemapFileParser { + FileManager &FileMgr; + +public: + RemapFileParser(FileManager &FileMgr) : FileMgr(FileMgr) { } + + bool parse(StringRef File, SmallVectorImpl<EditEntry> &Entries) { + using namespace llvm::yaml; + + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> FileBufOrErr = + llvm::MemoryBuffer::getFile(File); + if (!FileBufOrErr) + return true; + + llvm::SourceMgr SM; + Stream YAMLStream(FileBufOrErr.get().release(), SM); + document_iterator I = YAMLStream.begin(); + if (I == YAMLStream.end()) + return true; + Node *Root = I->getRoot(); + if (!Root) + return true; + + SequenceNode *SeqNode = dyn_cast<SequenceNode>(Root); + if (!SeqNode) + return true; + + for (SequenceNode::iterator + AI = SeqNode->begin(), AE = SeqNode->end(); AI != AE; ++AI) { + MappingNode *MapNode = dyn_cast<MappingNode>(&*AI); + if (!MapNode) + continue; + parseEdit(MapNode, Entries); + } + + return false; + } + +private: + void parseEdit(llvm::yaml::MappingNode *Node, + SmallVectorImpl<EditEntry> &Entries) { + using namespace llvm::yaml; + EditEntry Entry; + bool Ignore = false; + + for (MappingNode::iterator + KVI = Node->begin(), KVE = Node->end(); KVI != KVE; ++KVI) { + ScalarNode *KeyString = dyn_cast<ScalarNode>((*KVI).getKey()); + if (!KeyString) + continue; + SmallString<10> KeyStorage; + StringRef Key = KeyString->getValue(KeyStorage); + + ScalarNode *ValueString = dyn_cast<ScalarNode>((*KVI).getValue()); + if (!ValueString) + continue; + SmallString<64> ValueStorage; + StringRef Val = ValueString->getValue(ValueStorage); + + if (Key == "file") { + const FileEntry *FE = FileMgr.getFile(Val); + if (!FE) + Ignore = true; + Entry.File = FE; + } else if (Key == "offset") { + if (Val.getAsInteger(10, Entry.Offset)) + Ignore = true; + } else if (Key == "remove") { + if (Val.getAsInteger(10, Entry.RemoveLen)) + Ignore = true; + } else if (Key == "text") { + Entry.Text = Val; + } + } + + if (!Ignore) + Entries.push_back(Entry); + } +}; +} + +static bool reportDiag(const Twine &Err, DiagnosticsEngine &Diag) { + Diag.Report(Diag.getCustomDiagID(DiagnosticsEngine::Error, "%0")) + << Err.str(); + return true; +} + +static std::string applyEditsToTemp(const FileEntry *FE, + ArrayRef<EditEntry> Edits, + FileManager &FileMgr, + DiagnosticsEngine &Diag) { + using namespace llvm::sys; + + SourceManager SM(Diag, FileMgr); + FileID FID = SM.createFileID(FE, SourceLocation(), SrcMgr::C_User); + LangOptions LangOpts; + edit::EditedSource Editor(SM, LangOpts); + for (ArrayRef<EditEntry>::iterator + I = Edits.begin(), E = Edits.end(); I != E; ++I) { + const EditEntry &Entry = *I; + assert(Entry.File == FE); + SourceLocation Loc = + SM.getLocForStartOfFile(FID).getLocWithOffset(Entry.Offset); + CharSourceRange Range; + if (Entry.RemoveLen != 0) { + Range = CharSourceRange::getCharRange(Loc, + Loc.getLocWithOffset(Entry.RemoveLen)); + } + + edit::Commit commit(Editor); + if (Range.isInvalid()) { + commit.insert(Loc, Entry.Text); + } else if (Entry.Text.empty()) { + commit.remove(Range); + } else { + commit.replace(Range, Entry.Text); + } + Editor.commit(commit); + } + + Rewriter rewriter(SM, LangOpts); + RewritesReceiver Rec(rewriter); + Editor.applyRewrites(Rec); + + const RewriteBuffer *Buf = rewriter.getRewriteBufferFor(FID); + SmallString<512> NewText; + llvm::raw_svector_ostream OS(NewText); + Buf->write(OS); + OS.flush(); + + SmallString<64> TempPath; + int FD; + if (fs::createTemporaryFile(path::filename(FE->getName()), + path::extension(FE->getName()), FD, + TempPath)) { + reportDiag("Could not create file: " + TempPath.str(), Diag); + return std::string(); + } + + llvm::raw_fd_ostream TmpOut(FD, /*shouldClose=*/true); + TmpOut.write(NewText.data(), NewText.size()); + TmpOut.close(); + + return TempPath.str(); +} + +bool arcmt::getFileRemappingsFromFileList( + std::vector<std::pair<std::string,std::string> > &remap, + ArrayRef<StringRef> remapFiles, + DiagnosticConsumer *DiagClient) { + bool hasErrorOccurred = false; + + FileSystemOptions FSOpts; + FileManager FileMgr(FSOpts); + RemapFileParser Parser(FileMgr); + + IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs()); + IntrusiveRefCntPtr<DiagnosticsEngine> Diags( + new DiagnosticsEngine(DiagID, new DiagnosticOptions, + DiagClient, /*ShouldOwnClient=*/false)); + + typedef llvm::DenseMap<const FileEntry *, std::vector<EditEntry> > + FileEditEntriesTy; + FileEditEntriesTy FileEditEntries; + + llvm::DenseSet<EditEntry> EntriesSet; + + for (ArrayRef<StringRef>::iterator + I = remapFiles.begin(), E = remapFiles.end(); I != E; ++I) { + SmallVector<EditEntry, 16> Entries; + if (Parser.parse(*I, Entries)) + continue; + + for (SmallVectorImpl<EditEntry>::iterator + EI = Entries.begin(), EE = Entries.end(); EI != EE; ++EI) { + EditEntry &Entry = *EI; + if (!Entry.File) + continue; + std::pair<llvm::DenseSet<EditEntry>::iterator, bool> + Insert = EntriesSet.insert(Entry); + if (!Insert.second) + continue; + + FileEditEntries[Entry.File].push_back(Entry); + } + } + + for (FileEditEntriesTy::iterator + I = FileEditEntries.begin(), E = FileEditEntries.end(); I != E; ++I) { + std::string TempFile = applyEditsToTemp(I->first, I->second, + FileMgr, *Diags); + if (TempFile.empty()) { + hasErrorOccurred = true; + continue; + } + + remap.push_back(std::make_pair(I->first->getName(), TempFile)); + } + + return hasErrorOccurred; +} diff --git a/lib/ARCMigrate/PlistReporter.cpp b/lib/ARCMigrate/PlistReporter.cpp index 144ba2e398ad..6b34ef0c2b9e 100644 --- a/lib/ARCMigrate/PlistReporter.cpp +++ b/lib/ARCMigrate/PlistReporter.cpp @@ -9,86 +9,27 @@ #include "Internals.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/PlistSupport.h" #include "clang/Basic/SourceManager.h" #include "clang/Lex/Lexer.h" using namespace clang; using namespace arcmt; - -// FIXME: This duplicates significant functionality from PlistDiagnostics.cpp, -// it would be jolly good if there was a reusable PlistWriter or something. - -typedef llvm::DenseMap<FileID, unsigned> FIDMap; - -static void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V, - const SourceManager &SM, SourceLocation L) { - - FileID FID = SM.getFileID(SM.getExpansionLoc(L)); - FIDMap::iterator I = FIDs.find(FID); - if (I != FIDs.end()) return; - FIDs[FID] = V.size(); - V.push_back(FID); -} - -static unsigned GetFID(const FIDMap& FIDs, const SourceManager &SM, - SourceLocation L) { - FileID FID = SM.getFileID(SM.getExpansionLoc(L)); - FIDMap::const_iterator I = FIDs.find(FID); - assert(I != FIDs.end()); - return I->second; -} - -static raw_ostream& Indent(raw_ostream& o, const unsigned indent) { - for (unsigned i = 0; i < indent; ++i) o << ' '; - return o; -} - -static void EmitLocation(raw_ostream& o, const SourceManager &SM, - const LangOptions &LangOpts, - SourceLocation L, const FIDMap &FM, - unsigned indent, bool extend = false) { - - FullSourceLoc Loc(SM.getExpansionLoc(L), const_cast<SourceManager&>(SM)); - - // Add in the length of the token, so that we cover multi-char tokens. - unsigned offset = - extend ? Lexer::MeasureTokenLength(Loc, SM, LangOpts) - 1 : 0; - - Indent(o, indent) << "<dict>\n"; - Indent(o, indent) << " <key>line</key><integer>" - << Loc.getExpansionLineNumber() << "</integer>\n"; - Indent(o, indent) << " <key>col</key><integer>" - << Loc.getExpansionColumnNumber() + offset << "</integer>\n"; - Indent(o, indent) << " <key>file</key><integer>" - << GetFID(FM, SM, Loc) << "</integer>\n"; - Indent(o, indent) << "</dict>\n"; -} - -static void EmitRange(raw_ostream& o, const SourceManager &SM, - const LangOptions &LangOpts, - CharSourceRange R, const FIDMap &FM, - unsigned indent) { - Indent(o, indent) << "<array>\n"; - EmitLocation(o, SM, LangOpts, R.getBegin(), FM, indent+1); - EmitLocation(o, SM, LangOpts, R.getEnd(), FM, indent+1, R.isTokenRange()); - Indent(o, indent) << "</array>\n"; -} - -static raw_ostream& EmitString(raw_ostream& o, - StringRef s) { - o << "<string>"; - for (StringRef::const_iterator I=s.begin(), E=s.end(); I!=E; ++I) { - char c = *I; - switch (c) { - default: o << c; break; - case '&': o << "&"; break; - case '<': o << "<"; break; - case '>': o << ">"; break; - case '\'': o << "'"; break; - case '\"': o << """; break; - } +using namespace markup; + +static StringRef getLevelName(DiagnosticsEngine::Level Level) { + switch (Level) { + case DiagnosticsEngine::Ignored: + llvm_unreachable("ignored"); + case DiagnosticsEngine::Note: + return "note"; + case DiagnosticsEngine::Remark: + case DiagnosticsEngine::Warning: + return "warning"; + case DiagnosticsEngine::Fatal: + case DiagnosticsEngine::Error: + return "error"; } - o << "</string>"; - return o; + llvm_unreachable("Invalid DiagnosticsEngine level!"); } void arcmt::writeARCDiagsToPlist(const std::string &outPath, @@ -116,17 +57,13 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath, } std::string errMsg; - llvm::raw_fd_ostream o(outPath.c_str(), errMsg); + llvm::raw_fd_ostream o(outPath.c_str(), errMsg, llvm::sys::fs::F_Text); if (!errMsg.empty()) { llvm::errs() << "error: could not create file: " << outPath << '\n'; return; } - // Write the plist header. - o << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" - "<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" " - "\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n" - "<plist version=\"1.0\">\n"; + EmitPlistHeader(o); // Write the root object: a <dict> containing... // - "files", an <array> mapping from FIDs to file names @@ -135,11 +72,8 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath, " <key>files</key>\n" " <array>\n"; - for (SmallVectorImpl<FileID>::iterator I=Fids.begin(), E=Fids.end(); - I!=E; ++I) { - o << " "; - EmitString(o, SM.getFileEntryForID(*I)->getName()) << '\n'; - } + for (FileID FID : Fids) + EmitString(o << " ", SM.getFileEntryForID(FID)->getName()) << '\n'; o << " </array>\n" " <key>diagnostics</key>\n" @@ -162,12 +96,7 @@ void arcmt::writeARCDiagsToPlist(const std::string &outPath, EmitString(o, DiagIDs.getCategoryNameFromID( DiagIDs.getCategoryNumberForDiag(D.getID()))) << '\n'; o << " <key>type</key>"; - if (D.getLevel() >= DiagnosticsEngine::Error) - EmitString(o, "error") << '\n'; - else if (D.getLevel() == DiagnosticsEngine::Warning) - EmitString(o, "warning") << '\n'; - else - EmitString(o, "note") << '\n'; + EmitString(o, getLevelName(D.getLevel())) << '\n'; // Output the location of the bug. o << " <key>location</key>\n"; diff --git a/lib/ARCMigrate/TransAPIUses.cpp b/lib/ARCMigrate/TransAPIUses.cpp index a0994a6b459a..544cb0addfcd 100644 --- a/lib/ARCMigrate/TransAPIUses.cpp +++ b/lib/ARCMigrate/TransAPIUses.cpp @@ -66,8 +66,7 @@ public: selName = "getArgument"; else if (E->getSelector() == setArgumentSel) selName = "setArgument"; - - if (selName.empty()) + else return true; Expr *parm = E->getArg(0)->IgnoreParenCasts(); @@ -75,13 +74,12 @@ public: if (pointee.isNull()) return true; - if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone) { - std::string err = "NSInvocation's "; - err += selName; - err += " is not safe to be used with an object with ownership other " - "than __unsafe_unretained"; - Pass.TA.reportError(err, parm->getLocStart(), parm->getSourceRange()); - } + if (pointee.getObjCLifetime() > Qualifiers::OCL_ExplicitNone) + Pass.TA.report(parm->getLocStart(), + diag::err_arcmt_nsinvocation_ownership, + parm->getSourceRange()) + << selName; + return true; } diff --git a/lib/ARCMigrate/TransAutoreleasePool.cpp b/lib/ARCMigrate/TransAutoreleasePool.cpp index a2990e7226ab..a8a99fa712a3 100644 --- a/lib/ARCMigrate/TransAutoreleasePool.cpp +++ b/lib/ARCMigrate/TransAutoreleasePool.cpp @@ -70,7 +70,7 @@ class AutoreleasePoolRewriter : public RecursiveASTVisitor<AutoreleasePoolRewriter> { public: AutoreleasePoolRewriter(MigrationPass &pass) - : Body(0), Pass(pass) { + : Body(nullptr), Pass(pass) { PoolII = &pass.Ctx.Idents.get("NSAutoreleasePool"); DrainSel = pass.Ctx.Selectors.getNullarySelector( &pass.Ctx.Idents.get("drain")); @@ -230,7 +230,7 @@ private: bool IsFollowedBySimpleReturnStmt; SmallVector<ObjCMessageExpr *, 4> Releases; - PoolScope() : PoolVar(0), CompoundParent(0), Begin(), End(), + PoolScope() : PoolVar(nullptr), CompoundParent(nullptr), Begin(), End(), IsFollowedBySimpleReturnStmt(false) { } SourceRange getIndentedRange() const { @@ -305,7 +305,7 @@ private: // statement, in which case we will include the return in the scope. if (SI != SE) if (ReturnStmt *retS = dyn_cast<ReturnStmt>(*SI)) - if ((retS->getRetValue() == 0 || + if ((retS->getRetValue() == nullptr || isa<DeclRefExpr>(retS->getRetValue()->IgnoreParenCasts())) && findLocationAfterSemi(retS->getLocEnd(), Pass.Ctx).isValid()) { scope.IsFollowedBySimpleReturnStmt = true; @@ -421,7 +421,7 @@ private: ExprSet Refs; SmallVector<PoolScope, 2> Scopes; - PoolVarInfo() : Dcl(0) { } + PoolVarInfo() : Dcl(nullptr) { } }; std::map<VarDecl *, PoolVarInfo> PoolVars; diff --git a/lib/ARCMigrate/TransBlockObjCVariable.cpp b/lib/ARCMigrate/TransBlockObjCVariable.cpp index 97c4e3480c15..fac6a84c45e5 100644 --- a/lib/ARCMigrate/TransBlockObjCVariable.cpp +++ b/lib/ARCMigrate/TransBlockObjCVariable.cpp @@ -78,10 +78,9 @@ public: bool VisitBlockDecl(BlockDecl *block) { SmallVector<VarDecl *, 4> BlockVars; - for (BlockDecl::capture_iterator - I = block->capture_begin(), E = block->capture_end(); I != E; ++I) { - VarDecl *var = I->getVariable(); - if (I->isByRef() && + for (const auto &I : block->captures()) { + VarDecl *var = I.getVariable(); + if (I.isByRef() && var->getType()->isObjCObjectPointerType() && isImplicitStrong(var->getType())) { BlockVars.push_back(var); diff --git a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp index ffb638f8a306..9689f40760cd 100644 --- a/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp +++ b/lib/ARCMigrate/TransEmptyStatementsAndDealloc.cpp @@ -89,9 +89,8 @@ public: bool VisitCompoundStmt(CompoundStmt *S) { if (S->body_empty()) return false; // was already empty, not because of transformations. - for (CompoundStmt::body_iterator - I = S->body_begin(), E = S->body_end(); I != E; ++I) - if (!Visit(*I)) + for (auto *I : S->body()) + if (!Visit(I)) return false; return true; } @@ -167,9 +166,8 @@ public: } bool VisitCompoundStmt(CompoundStmt *S) { - for (CompoundStmt::body_iterator - I = S->body_begin(), E = S->body_end(); I != E; ++I) - check(*I); + for (auto *I : S->body()) + check(I); return true; } @@ -189,9 +187,8 @@ private: static bool isBodyEmpty(CompoundStmt *body, ASTContext &Ctx, std::vector<SourceLocation> &MacroLocs) { - for (CompoundStmt::body_iterator - I = body->body_begin(), E = body->body_end(); I != E; ++I) - if (!EmptyChecker(Ctx, MacroLocs).Visit(*I)) + for (auto *I : body->body()) + if (!EmptyChecker(Ctx, MacroLocs).Visit(I)) return false; return true; @@ -208,12 +205,9 @@ static void cleanupDeallocOrFinalize(MigrationPass &pass) { impl_iterator; for (impl_iterator I = impl_iterator(DC->decls_begin()), E = impl_iterator(DC->decls_end()); I != E; ++I) { - ObjCMethodDecl *DeallocM = 0; - ObjCMethodDecl *FinalizeM = 0; - for (ObjCImplementationDecl::instmeth_iterator - MI = I->instmeth_begin(), - ME = I->instmeth_end(); MI != ME; ++MI) { - ObjCMethodDecl *MD = *MI; + ObjCMethodDecl *DeallocM = nullptr; + ObjCMethodDecl *FinalizeM = nullptr; + for (auto *MD : I->instance_methods()) { if (!MD->hasBody()) continue; diff --git a/lib/ARCMigrate/TransGCAttrs.cpp b/lib/ARCMigrate/TransGCAttrs.cpp index d8be1ae746ab..10fce19b6f19 100644 --- a/lib/ARCMigrate/TransGCAttrs.cpp +++ b/lib/ARCMigrate/TransGCAttrs.cpp @@ -80,7 +80,7 @@ public: } } - bool handleAttr(AttributedTypeLoc TL, Decl *D = 0) { + bool handleAttr(AttributedTypeLoc TL, Decl *D = nullptr) { if (TL.getAttrKind() != AttributedType::attr_objc_ownership) return false; @@ -134,8 +134,7 @@ public: return hasObjCImpl(ContD); if (CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { - for (CXXRecordDecl::method_iterator - MI = RD->method_begin(), ME = RD->method_end(); MI != ME; ++MI) { + for (const auto *MI : RD->methods()) { if (MI->isOutOfLine()) return true; } @@ -150,9 +149,9 @@ public: return false; if (ObjCContainerDecl *ContD = dyn_cast<ObjCContainerDecl>(D)) { if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ContD)) - return ID->getImplementation() != 0; + return ID->getImplementation() != nullptr; if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ContD)) - return CD->getImplementation() != 0; + return CD->getImplementation() != nullptr; if (isa<ObjCImplDecl>(ContD)) return true; return false; @@ -164,8 +163,7 @@ public: if (!D) return false; - for (Decl::redecl_iterator - I = D->redecls_begin(), E = D->redecls_end(); I != E; ++I) + for (auto I : D->redecls()) if (!isInMainFile(I->getLocation())) return false; diff --git a/lib/ARCMigrate/TransGCCalls.cpp b/lib/ARCMigrate/TransGCCalls.cpp index 249f20f01b22..3a236d34cd4b 100644 --- a/lib/ARCMigrate/TransGCCalls.cpp +++ b/lib/ARCMigrate/TransGCCalls.cpp @@ -38,14 +38,8 @@ public: TransformActions &TA = MigrateCtx.Pass.TA; if (MigrateCtx.isGCOwnedNonObjC(E->getType())) { - if (MigrateCtx.Pass.noNSAllocReallocError()) - TA.reportWarning("call returns pointer to GC managed memory; " - "it will become unmanaged in ARC", - E->getLocStart(), E->getSourceRange()); - else - TA.reportError("call returns pointer to GC managed memory; " - "it will become unmanaged in ARC", - E->getLocStart(), E->getSourceRange()); + TA.report(E->getLocStart(), diag::warn_arcmt_nsalloc_realloc, + E->getSourceRange()); return true; } diff --git a/lib/ARCMigrate/TransProperties.cpp b/lib/ARCMigrate/TransProperties.cpp index b6ddc43dd69f..ab128844b45f 100644 --- a/lib/ARCMigrate/TransProperties.cpp +++ b/lib/ARCMigrate/TransProperties.cpp @@ -61,7 +61,8 @@ class PropertiesRewriter { ObjCIvarDecl *IvarD; ObjCPropertyImplDecl *ImplD; - PropData(ObjCPropertyDecl *propD) : PropD(propD), IvarD(0), ImplD(0) { } + PropData(ObjCPropertyDecl *propD) + : PropD(propD), IvarD(nullptr), ImplD(nullptr) {} }; typedef SmallVector<PropData, 2> PropsTy; @@ -74,18 +75,16 @@ public: : MigrateCtx(MigrateCtx), Pass(MigrateCtx.Pass) { } static void collectProperties(ObjCContainerDecl *D, AtPropDeclsTy &AtProps, - AtPropDeclsTy *PrevAtProps = 0) { - for (ObjCInterfaceDecl::prop_iterator - propI = D->prop_begin(), - propE = D->prop_end(); propI != propE; ++propI) { - if (propI->getAtLoc().isInvalid()) + AtPropDeclsTy *PrevAtProps = nullptr) { + for (auto *Prop : D->properties()) { + if (Prop->getAtLoc().isInvalid()) continue; - unsigned RawLoc = propI->getAtLoc().getRawEncoding(); + unsigned RawLoc = Prop->getAtLoc().getRawEncoding(); if (PrevAtProps) if (PrevAtProps->find(RawLoc) != PrevAtProps->end()) continue; PropsTy &props = AtProps[RawLoc]; - props.push_back(*propI); + props.push_back(Prop); } } @@ -141,12 +140,8 @@ public: AtPropDeclsTy AtExtProps; // Look through extensions. - for (ObjCInterfaceDecl::visible_extensions_iterator - ext = iface->visible_extensions_begin(), - extEnd = iface->visible_extensions_end(); - ext != extEnd; ++ext) { - collectProperties(*ext, AtExtProps, &AtProps); - } + for (auto *Ext : iface->visible_extensions()) + collectProperties(Ext, AtExtProps, &AtProps); for (AtPropDeclsTy::iterator I = AtExtProps.begin(), E = AtExtProps.end(); I != E; ++I) { @@ -353,14 +348,6 @@ private: return false; } - bool hasAllIvarsBacked(PropsTy &props) const { - for (PropsTy::iterator I = props.begin(), E = props.end(); I != E; ++I) - if (!isUserDeclared(I->IvarD)) - return false; - - return true; - } - // \brief Returns true if all declarations in the @property have GC __weak. bool hasGCWeak(PropsTy &props, SourceLocation atLoc) const { if (!Pass.isGCMigration()) diff --git a/lib/ARCMigrate/TransProtectedScope.cpp b/lib/ARCMigrate/TransProtectedScope.cpp index 237aa42877e6..0fcbcbedfe04 100644 --- a/lib/ARCMigrate/TransProtectedScope.cpp +++ b/lib/ARCMigrate/TransProtectedScope.cpp @@ -47,7 +47,7 @@ struct CaseInfo { St_Fixed } State; - CaseInfo() : SC(0), State(St_Unchecked) {} + CaseInfo() : SC(nullptr), State(St_Unchecked) {} CaseInfo(SwitchCase *S, SourceRange Range) : SC(S), Range(Range), State(St_Unchecked) {} }; diff --git a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp index 446a284a286f..bcbc9e9612ba 100644 --- a/lib/ARCMigrate/TransRetainReleaseDealloc.cpp +++ b/lib/ARCMigrate/TransRetainReleaseDealloc.cpp @@ -38,13 +38,13 @@ class RetainReleaseDeallocRemover : MigrationPass &Pass; ExprSet Removables; - OwningPtr<ParentMap> StmtMap; + std::unique_ptr<ParentMap> StmtMap; Selector DelegateSel, FinalizeSel; public: RetainReleaseDeallocRemover(MigrationPass &pass) - : Body(0), Pass(pass) { + : Body(nullptr), Pass(pass) { DelegateSel = Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("delegate")); FinalizeSel = @@ -70,7 +70,7 @@ public: // An unused autorelease is badness. If we remove it the receiver // will likely die immediately while previously it was kept alive // by the autorelease pool. This is bad practice in general, leave it - // and emit an error to force the user to restructure his code. + // and emit an error to force the user to restructure their code. Pass.TA.reportError("it is not safe to remove an unused 'autorelease' " "message; its receiver may be destroyed immediately", E->getLocStart(), E->getSourceRange()); @@ -212,7 +212,7 @@ private: return false; Stmt *prevStmt, *nextStmt; - llvm::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(E); + std::tie(prevStmt, nextStmt) = getPreviousAndNextStmt(E); return isPlusOneAssignToVar(prevStmt, RefD) || isPlusOneAssignToVar(nextStmt, RefD); @@ -248,7 +248,7 @@ private: } std::pair<Stmt *, Stmt *> getPreviousAndNextStmt(Expr *E) { - Stmt *prevStmt = 0, *nextStmt = 0; + Stmt *prevStmt = nullptr, *nextStmt = nullptr; if (!E) return std::make_pair(prevStmt, nextStmt); @@ -294,7 +294,7 @@ private: Decl *getReferencedDecl(Expr *E) { if (!E) - return 0; + return nullptr; E = E->IgnoreParenCasts(); if (ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(E)) { @@ -305,7 +305,7 @@ private: case OMF_retain: return getReferencedDecl(ME->getInstanceReceiver()); default: - return 0; + return nullptr; } } if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E)) @@ -315,7 +315,7 @@ private: if (ObjCIvarRefExpr *IRE = dyn_cast<ObjCIvarRefExpr>(E)) return IRE->getDecl(); - return 0; + return nullptr; } /// \brief Check if the retain/release is due to a GCD/XPC macro that are @@ -345,7 +345,7 @@ private: if (!isGCDOrXPC) return; - StmtExpr *StmtE = 0; + StmtExpr *StmtE = nullptr; Stmt *S = Msg; while (S) { if (StmtExpr *SE = dyn_cast<StmtExpr>(S)) { diff --git a/lib/ARCMigrate/TransUnbridgedCasts.cpp b/lib/ARCMigrate/TransUnbridgedCasts.cpp index 7b360c640cfd..7ca49558a7f0 100644 --- a/lib/ARCMigrate/TransUnbridgedCasts.cpp +++ b/lib/ARCMigrate/TransUnbridgedCasts.cpp @@ -60,13 +60,14 @@ namespace { class UnbridgedCastRewriter : public RecursiveASTVisitor<UnbridgedCastRewriter>{ MigrationPass &Pass; IdentifierInfo *SelfII; - OwningPtr<ParentMap> StmtMap; + std::unique_ptr<ParentMap> StmtMap; Decl *ParentD; Stmt *Body; - mutable OwningPtr<ExprSet> Removables; + mutable std::unique_ptr<ExprSet> Removables; public: - UnbridgedCastRewriter(MigrationPass &pass) : Pass(pass), ParentD(0), Body(0) { + UnbridgedCastRewriter(MigrationPass &pass) + : Pass(pass), ParentD(nullptr), Body(nullptr) { SelfII = &Pass.Ctx.Idents.get("self"); } @@ -133,11 +134,11 @@ private: Expr *inner = E->IgnoreParenCasts(); if (CallExpr *callE = dyn_cast<CallExpr>(inner)) { if (FunctionDecl *FD = callE->getDirectCallee()) { - if (FD->getAttr<CFReturnsRetainedAttr>()) { + if (FD->hasAttr<CFReturnsRetainedAttr>()) { castToObjCObject(E, /*retained=*/true); return; } - if (FD->getAttr<CFReturnsNotRetainedAttr>()) { + if (FD->hasAttr<CFReturnsNotRetainedAttr>()) { castToObjCObject(E, /*retained=*/false); return; } @@ -283,7 +284,7 @@ private: SourceLocation Loc = E->getExprLoc(); assert(Loc.isMacroID()); SourceLocation MacroBegin, MacroEnd; - llvm::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc); + std::tie(MacroBegin, MacroEnd) = SM.getImmediateExpansionRange(Loc); SourceRange SubRange = E->getSubExpr()->IgnoreParenImpCasts()->getSourceRange(); SourceLocation InnerBegin = SM.getImmediateMacroCallerLoc(SubRange.getBegin()); SourceLocation InnerEnd = SM.getImmediateMacroCallerLoc(SubRange.getEnd()); @@ -439,7 +440,7 @@ private: } if (i < callE->getNumArgs() && i < FD->getNumParams()) { ParmVarDecl *PD = FD->getParamDecl(i); - if (PD->getAttr<CFConsumedAttr>()) { + if (PD->hasAttr<CFConsumedAttr>()) { isConsumed = true; return true; } diff --git a/lib/ARCMigrate/TransUnusedInitDelegate.cpp b/lib/ARCMigrate/TransUnusedInitDelegate.cpp index e316c73fc3cd..98571c035dd5 100644 --- a/lib/ARCMigrate/TransUnusedInitDelegate.cpp +++ b/lib/ARCMigrate/TransUnusedInitDelegate.cpp @@ -39,7 +39,7 @@ class UnusedInitRewriter : public RecursiveASTVisitor<UnusedInitRewriter> { public: UnusedInitRewriter(MigrationPass &pass) - : Body(0), Pass(pass) { } + : Body(nullptr), Pass(pass) { } void transformBody(Stmt *body, Decl *ParentD) { Body = body; diff --git a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp index 4d088e05bfab..76ce0ec90db3 100644 --- a/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp +++ b/lib/ARCMigrate/TransZeroOutPropsInDealloc.cpp @@ -35,7 +35,7 @@ class ZeroOutInDeallocRemover : Selector FinalizeSel; public: - ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(0) { + ZeroOutInDeallocRemover(MigrationPass &pass) : Pass(pass), SelfD(nullptr) { FinalizeSel = Pass.Ctx.Selectors.getNullarySelector(&Pass.Ctx.Idents.get("finalize")); } @@ -113,23 +113,21 @@ public: // For a 'dealloc' method use, find all property implementations in // this class implementation. - for (ObjCImplDecl::propimpl_iterator - I = IMD->propimpl_begin(), EI = IMD->propimpl_end(); I != EI; ++I) { - ObjCPropertyImplDecl *PID = *I; - if (PID->getPropertyImplementation() == - ObjCPropertyImplDecl::Synthesize) { - ObjCPropertyDecl *PD = PID->getPropertyDecl(); - ObjCMethodDecl *setterM = PD->getSetterMethodDecl(); - if (!(setterM && setterM->isDefined())) { - ObjCPropertyDecl::PropertyAttributeKind AttrKind = - PD->getPropertyAttributes(); - if (AttrKind & - (ObjCPropertyDecl::OBJC_PR_retain | - ObjCPropertyDecl::OBJC_PR_copy | - ObjCPropertyDecl::OBJC_PR_strong)) - SynthesizedProperties[PD] = PID; - } + for (auto *PID : IMD->property_impls()) { + if (PID->getPropertyImplementation() == + ObjCPropertyImplDecl::Synthesize) { + ObjCPropertyDecl *PD = PID->getPropertyDecl(); + ObjCMethodDecl *setterM = PD->getSetterMethodDecl(); + if (!(setterM && setterM->isDefined())) { + ObjCPropertyDecl::PropertyAttributeKind AttrKind = + PD->getPropertyAttributes(); + if (AttrKind & + (ObjCPropertyDecl::OBJC_PR_retain | + ObjCPropertyDecl::OBJC_PR_copy | + ObjCPropertyDecl::OBJC_PR_strong)) + SynthesizedProperties[PD] = PID; } + } } // Now, remove all zeroing of ivars etc. @@ -137,7 +135,7 @@ public: // clear out for next method. SynthesizedProperties.clear(); - SelfD = 0; + SelfD = nullptr; Removables.clear(); return true; } diff --git a/lib/ARCMigrate/TransformActions.cpp b/lib/ARCMigrate/TransformActions.cpp index 2fd0619df9f8..6d178bea0907 100644 --- a/lib/ARCMigrate/TransformActions.cpp +++ b/lib/ARCMigrate/TransformActions.cpp @@ -601,7 +601,7 @@ TransformActions::RewriteReceiver::~RewriteReceiver() { } TransformActions::TransformActions(DiagnosticsEngine &diag, CapturedDiagList &capturedDiags, ASTContext &ctx, Preprocessor &PP) - : Diags(diag), CapturedDiags(capturedDiags), ReportedErrors(false) { + : Diags(diag), CapturedDiags(capturedDiags) { Impl = new TransformActionsImpl(capturedDiags, ctx, PP); } @@ -673,60 +673,24 @@ void TransformActions::applyRewrites(RewriteReceiver &receiver) { static_cast<TransformActionsImpl*>(Impl)->applyRewrites(receiver); } -void TransformActions::reportError(StringRef error, SourceLocation loc, - SourceRange range) { - assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() && +DiagnosticBuilder TransformActions::report(SourceLocation loc, unsigned diagId, + SourceRange range) { + assert(!static_cast<TransformActionsImpl *>(Impl)->isInTransaction() && "Errors should be emitted out of a transaction"); - - SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)-> - getASTContext().getSourceManager(); - if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) - return; - - // FIXME: Use a custom category name to distinguish rewriter errors. - std::string rewriteErr = "[rewriter] "; - rewriteErr += error; - unsigned diagID - = Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Error, - rewriteErr); - Diags.Report(loc, diagID) << range; - ReportedErrors = true; + return Diags.Report(loc, diagId) << range; } -void TransformActions::reportWarning(StringRef warning, SourceLocation loc, +void TransformActions::reportError(StringRef message, SourceLocation loc, SourceRange range) { - assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() && - "Warning should be emitted out of a transaction"); - - SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)-> - getASTContext().getSourceManager(); - if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) - return; - - // FIXME: Use a custom category name to distinguish rewriter errors. - std::string rewriterWarn = "[rewriter] "; - rewriterWarn += warning; - unsigned diagID - = Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Warning, - rewriterWarn); - Diags.Report(loc, diagID) << range; + report(loc, diag::err_mt_message, range) << message; } -void TransformActions::reportNote(StringRef note, SourceLocation loc, - SourceRange range) { - assert(!static_cast<TransformActionsImpl*>(Impl)->isInTransaction() && - "Errors should be emitted out of a transaction"); - - SourceManager &SM = static_cast<TransformActionsImpl*>(Impl)-> - getASTContext().getSourceManager(); - if (SM.isInSystemHeader(SM.getExpansionLoc(loc))) - return; +void TransformActions::reportWarning(StringRef message, SourceLocation loc, + SourceRange range) { + report(loc, diag::warn_mt_message, range) << message; +} - // FIXME: Use a custom category name to distinguish rewriter errors. - std::string rewriteNote = "[rewriter] "; - rewriteNote += note; - unsigned diagID - = Diags.getDiagnosticIDs()->getCustomDiagID(DiagnosticIDs::Note, - rewriteNote); - Diags.Report(loc, diagID) << range; +void TransformActions::reportNote(StringRef message, SourceLocation loc, + SourceRange range) { + report(loc, diag::note_mt_message, range) << message; } diff --git a/lib/ARCMigrate/Transforms.cpp b/lib/ARCMigrate/Transforms.cpp index 679b924ba009..6ff7b6b9db87 100644 --- a/lib/ARCMigrate/Transforms.cpp +++ b/lib/ARCMigrate/Transforms.cpp @@ -88,7 +88,7 @@ bool trans::isPlusOne(const Expr *E) { if (const CallExpr * callE = dyn_cast<CallExpr>(E->IgnoreParenCasts())) { if (const FunctionDecl *FD = callE->getDirectCallee()) { - if (FD->getAttr<CFReturnsRetainedAttr>()) + if (FD->hasAttr<CFReturnsRetainedAttr>()) return true; if (FD->isGlobal() && @@ -264,9 +264,8 @@ public: } bool VisitCompoundStmt(CompoundStmt *S) { - for (CompoundStmt::body_iterator - I = S->body_begin(), E = S->body_end(); I != E; ++I) - mark(*I); + for (auto *I : S->body()) + mark(I); return true; } @@ -414,8 +413,7 @@ bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr, if (tok.isNot(tok::at)) return false; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::raw_identifier)) return false; - if (StringRef(tok.getRawIdentifierData(), tok.getLength()) - != "property") + if (tok.getRawIdentifier() != "property") return false; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::l_paren)) return false; @@ -431,8 +429,7 @@ bool MigrationContext::rewritePropertyAttribute(StringRef fromAttr, while (1) { if (tok.isNot(tok::raw_identifier)) return false; - StringRef ident(tok.getRawIdentifierData(), tok.getLength()); - if (ident == fromAttr) { + if (tok.getRawIdentifier() == fromAttr) { if (!toAttr.empty()) { Pass.TA.replaceText(tok.getLocation(), fromAttr, toAttr); return true; @@ -497,8 +494,7 @@ bool MigrationContext::addPropertyAttribute(StringRef attr, if (tok.isNot(tok::at)) return false; lexer.LexFromRawLexer(tok); if (tok.isNot(tok::raw_identifier)) return false; - if (StringRef(tok.getRawIdentifierData(), tok.getLength()) - != "property") + if (tok.getRawIdentifier() != "property") return false; lexer.LexFromRawLexer(tok); @@ -538,15 +534,12 @@ static void GCRewriteFinalize(MigrationPass &pass) { impl_iterator; for (impl_iterator I = impl_iterator(DC->decls_begin()), E = impl_iterator(DC->decls_end()); I != E; ++I) { - for (ObjCImplementationDecl::instmeth_iterator - MI = I->instmeth_begin(), - ME = I->instmeth_end(); MI != ME; ++MI) { - ObjCMethodDecl *MD = *MI; + for (const auto *MD : I->instance_methods()) { if (!MD->hasBody()) continue; if (MD->isInstanceMethod() && MD->getSelector() == FinalizeSel) { - ObjCMethodDecl *FinalizeM = MD; + const ObjCMethodDecl *FinalizeM = MD; Transaction Trans(TA); TA.insert(FinalizeM->getSourceRange().getBegin(), "#if !__has_feature(objc_arc)\n"); diff --git a/lib/ARCMigrate/Transforms.h b/lib/ARCMigrate/Transforms.h index eab5e85d56b7..12551d261d36 100644 --- a/lib/ARCMigrate/Transforms.h +++ b/lib/ARCMigrate/Transforms.h @@ -127,29 +127,29 @@ public: class PropertyRewriteTraverser : public ASTTraverser { public: - virtual void traverseObjCImplementation(ObjCImplementationContext &ImplCtx); + void traverseObjCImplementation(ObjCImplementationContext &ImplCtx) override; }; class BlockObjCVariableTraverser : public ASTTraverser { public: - virtual void traverseBody(BodyContext &BodyCtx); + void traverseBody(BodyContext &BodyCtx) override; }; class ProtectedScopeTraverser : public ASTTraverser { public: - virtual void traverseBody(BodyContext &BodyCtx); + void traverseBody(BodyContext &BodyCtx) override; }; // GC transformations class GCAttrsTraverser : public ASTTraverser { public: - virtual void traverseTU(MigrationContext &MigrateCtx); + void traverseTU(MigrationContext &MigrateCtx) override; }; class GCCollectableCallsTraverser : public ASTTraverser { public: - virtual void traverseBody(BodyContext &BodyCtx); + void traverseBody(BodyContext &BodyCtx) override; }; //===----------------------------------------------------------------------===// @@ -189,7 +189,7 @@ class BodyTransform : public RecursiveASTVisitor<BodyTransform<BODY_TRANS> > { typedef RecursiveASTVisitor<BodyTransform<BODY_TRANS> > base; public: - BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(0) { } + BodyTransform(MigrationPass &pass) : Pass(pass), ParentD(nullptr) { } bool TraverseStmt(Stmt *rootS) { if (rootS) diff --git a/lib/AST/APValue.cpp b/lib/AST/APValue.cpp index 541836b21b70..0fa0216d9dac 100644 --- a/lib/AST/APValue.cpp +++ b/lib/AST/APValue.cpp @@ -34,7 +34,7 @@ namespace { struct APValue::LV : LVBase { static const unsigned InlinePathSpace = - (MaxSize - sizeof(LVBase)) / sizeof(LValuePathEntry); + (DataSize - sizeof(LVBase)) / sizeof(LValuePathEntry); /// Path - The sequence of base classes, fields and array indices to follow to /// walk from Base to the subobject. When performing GCC-style folding, there @@ -75,7 +75,7 @@ namespace { struct APValue::MemberPointerData : MemberPointerBase { static const unsigned InlinePathSpace = - (MaxSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); + (DataSize - sizeof(MemberPointerBase)) / sizeof(const CXXRecordDecl*); typedef const CXXRecordDecl *PathElem; union { PathElem Path[InlinePathSpace]; @@ -117,7 +117,7 @@ APValue::StructData::~StructData() { delete [] Elts; } -APValue::UnionData::UnionData() : Field(0), Value(new APValue) {} +APValue::UnionData::UnionData() : Field(nullptr), Value(new APValue) {} APValue::UnionData::~UnionData () { delete Value; } @@ -136,7 +136,7 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { break; case Vector: MakeVector(); - setVector(((const Vec *)(const char *)RHS.Data)->Elts, + setVector(((const Vec *)(const char *)RHS.Data.buffer)->Elts, RHS.getVectorLength()); break; case ComplexInt: @@ -188,27 +188,27 @@ APValue::APValue(const APValue &RHS) : Kind(Uninitialized) { void APValue::DestroyDataAndMakeUninit() { if (Kind == Int) - ((APSInt*)(char*)Data)->~APSInt(); + ((APSInt*)(char*)Data.buffer)->~APSInt(); else if (Kind == Float) - ((APFloat*)(char*)Data)->~APFloat(); + ((APFloat*)(char*)Data.buffer)->~APFloat(); else if (Kind == Vector) - ((Vec*)(char*)Data)->~Vec(); + ((Vec*)(char*)Data.buffer)->~Vec(); else if (Kind == ComplexInt) - ((ComplexAPSInt*)(char*)Data)->~ComplexAPSInt(); + ((ComplexAPSInt*)(char*)Data.buffer)->~ComplexAPSInt(); else if (Kind == ComplexFloat) - ((ComplexAPFloat*)(char*)Data)->~ComplexAPFloat(); + ((ComplexAPFloat*)(char*)Data.buffer)->~ComplexAPFloat(); else if (Kind == LValue) - ((LV*)(char*)Data)->~LV(); + ((LV*)(char*)Data.buffer)->~LV(); else if (Kind == Array) - ((Arr*)(char*)Data)->~Arr(); + ((Arr*)(char*)Data.buffer)->~Arr(); else if (Kind == Struct) - ((StructData*)(char*)Data)->~StructData(); + ((StructData*)(char*)Data.buffer)->~StructData(); else if (Kind == Union) - ((UnionData*)(char*)Data)->~UnionData(); + ((UnionData*)(char*)Data.buffer)->~UnionData(); else if (Kind == MemberPointer) - ((MemberPointerData*)(char*)Data)->~MemberPointerData(); + ((MemberPointerData*)(char*)Data.buffer)->~MemberPointerData(); else if (Kind == AddrLabelDiff) - ((AddrLabelDiffData*)(char*)Data)->~AddrLabelDiffData(); + ((AddrLabelDiffData*)(char*)Data.buffer)->~AddrLabelDiffData(); Kind = Uninitialized; } @@ -239,19 +239,20 @@ bool APValue::needsCleanup() const { "same size."); return getComplexIntReal().needsCleanup(); case LValue: - return reinterpret_cast<const LV *>(Data)->hasPathPtr(); + return reinterpret_cast<const LV *>(Data.buffer)->hasPathPtr(); case MemberPointer: - return reinterpret_cast<const MemberPointerData *>(Data)->hasPathPtr(); + return reinterpret_cast<const MemberPointerData *>(Data.buffer) + ->hasPathPtr(); } llvm_unreachable("Unknown APValue kind!"); } void APValue::swap(APValue &RHS) { std::swap(Kind, RHS.Kind); - char TmpData[MaxSize]; - memcpy(TmpData, Data, MaxSize); - memcpy(Data, RHS.Data, MaxSize); - memcpy(RHS.Data, TmpData, MaxSize); + char TmpData[DataSize]; + memcpy(TmpData, Data.buffer, DataSize); + memcpy(Data.buffer, RHS.Data.buffer, DataSize); + memcpy(RHS.Data.buffer, TmpData, DataSize); } void APValue::dump() const { @@ -402,8 +403,13 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ if (const ValueDecl *VD = Base.dyn_cast<const ValueDecl*>()) Out << *VD; - else - Base.get<const Expr*>()->printPretty(Out, 0, Ctx.getPrintingPolicy()); + else { + assert(Base.get<const Expr *>() != nullptr && + "Expecting non-null Expr"); + Base.get<const Expr*>()->printPretty(Out, nullptr, + Ctx.getPrintingPolicy()); + } + if (!O.isZero()) { Out << " + " << (O / S); if (IsReference) @@ -424,12 +430,13 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ ElemTy = VD->getType(); } else { const Expr *E = Base.get<const Expr*>(); - E->printPretty(Out, 0, Ctx.getPrintingPolicy()); + assert(E != nullptr && "Expecting non-null Expr"); + E->printPretty(Out, nullptr, Ctx.getPrintingPolicy()); ElemTy = E->getType(); } ArrayRef<LValuePathEntry> Path = getLValuePath(); - const CXXRecordDecl *CastToBase = 0; + const CXXRecordDecl *CastToBase = nullptr; for (unsigned I = 0, N = Path.size(); I != N; ++I) { if (ElemTy->getAs<RecordType>()) { // The lvalue refers to a class type, so the next path entry is a base @@ -498,8 +505,7 @@ void APValue::printPretty(raw_ostream &Out, ASTContext &Ctx, QualType Ty) const{ First = false; } } - for (RecordDecl::field_iterator FI = RD->field_begin(); - FI != RD->field_end(); ++FI) { + for (const auto *FI : RD->fields()) { if (!First) Out << ", "; if (FI->isUnnamedBitfield()) continue; @@ -546,39 +552,39 @@ std::string APValue::getAsString(ASTContext &Ctx, QualType Ty) const { const APValue::LValueBase APValue::getLValueBase() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getPointer(); + return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getPointer(); } bool APValue::isLValueOnePastTheEnd() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const void*)Data)->BaseAndIsOnePastTheEnd.getInt(); + return ((const LV*)(const void*)Data.buffer)->BaseAndIsOnePastTheEnd.getInt(); } CharUnits &APValue::getLValueOffset() { assert(isLValue() && "Invalid accessor"); - return ((LV*)(void*)Data)->Offset; + return ((LV*)(void*)Data.buffer)->Offset; } bool APValue::hasLValuePath() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data)->hasPath(); + return ((const LV*)(const char*)Data.buffer)->hasPath(); } ArrayRef<APValue::LValuePathEntry> APValue::getLValuePath() const { assert(isLValue() && hasLValuePath() && "Invalid accessor"); - const LV &LVal = *((const LV*)(const char*)Data); + const LV &LVal = *((const LV*)(const char*)Data.buffer); return ArrayRef<LValuePathEntry>(LVal.getPath(), LVal.PathLength); } unsigned APValue::getLValueCallIndex() const { assert(isLValue() && "Invalid accessor"); - return ((const LV*)(const char*)Data)->CallIndex; + return ((const LV*)(const char*)Data.buffer)->CallIndex; } void APValue::setLValue(LValueBase B, const CharUnits &O, NoLValuePath, unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data); + LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); LVal.BaseAndIsOnePastTheEnd.setInt(false); LVal.Offset = O; @@ -590,7 +596,7 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool IsOnePastTheEnd, unsigned CallIndex) { assert(isLValue() && "Invalid accessor"); - LV &LVal = *((LV*)(char*)Data); + LV &LVal = *((LV*)(char*)Data.buffer); LVal.BaseAndIsOnePastTheEnd.setPointer(B); LVal.BaseAndIsOnePastTheEnd.setInt(IsOnePastTheEnd); LVal.Offset = O; @@ -601,39 +607,42 @@ void APValue::setLValue(LValueBase B, const CharUnits &O, const ValueDecl *APValue::getMemberPointerDecl() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return MPD.MemberAndIsDerivedMember.getPointer(); } bool APValue::isMemberPointerToDerivedMember() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return MPD.MemberAndIsDerivedMember.getInt(); } ArrayRef<const CXXRecordDecl*> APValue::getMemberPointerPath() const { assert(isMemberPointer() && "Invalid accessor"); - const MemberPointerData &MPD = *((const MemberPointerData*)(const char*)Data); + const MemberPointerData &MPD = + *((const MemberPointerData *)(const char *)Data.buffer); return ArrayRef<const CXXRecordDecl*>(MPD.getPath(), MPD.PathLength); } void APValue::MakeLValue() { assert(isUninit() && "Bad state change"); - assert(sizeof(LV) <= MaxSize && "LV too big"); - new ((void*)(char*)Data) LV(); + static_assert(sizeof(LV) <= DataSize, "LV too big"); + new ((void*)(char*)Data.buffer) LV(); Kind = LValue; } void APValue::MakeArray(unsigned InitElts, unsigned Size) { assert(isUninit() && "Bad state change"); - new ((void*)(char*)Data) Arr(InitElts, Size); + new ((void*)(char*)Data.buffer) Arr(InitElts, Size); Kind = Array; } void APValue::MakeMemberPointer(const ValueDecl *Member, bool IsDerivedMember, ArrayRef<const CXXRecordDecl*> Path) { assert(isUninit() && "Bad state change"); - MemberPointerData *MPD = new ((void*)(char*)Data) MemberPointerData; + MemberPointerData *MPD = new ((void*)(char*)Data.buffer) MemberPointerData; Kind = MemberPointer; MPD->MemberAndIsDerivedMember.setPointer(Member); MPD->MemberAndIsDerivedMember.setInt(IsDerivedMember); diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index a03cf9e7d47b..bccdae91d2eb 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -29,6 +29,7 @@ #include "clang/AST/RecordLayout.h" #include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TypeLoc.h" +#include "clang/AST/VTableBuilder.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" @@ -62,6 +63,13 @@ enum FloatingRank { RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { if (!CommentsLoaded && ExternalSource) { ExternalSource->ReadComments(); + +#ifndef NDEBUG + ArrayRef<RawComment *> RawComments = Comments.getComments(); + assert(std::is_sorted(RawComments.begin(), RawComments.end(), + BeforeThanCompare<RawComment>(SourceMgr))); +#endif + CommentsLoaded = true; } @@ -69,23 +77,23 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // User can not attach documentation to implicit declarations. if (D->isImplicit()) - return NULL; + return nullptr; // User can not attach documentation to implicit instantiations. if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const ClassTemplateSpecializationDecl *CTSD = @@ -93,35 +101,35 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { TemplateSpecializationKind TSK = CTSD->getSpecializationKind(); if (TSK == TSK_ImplicitInstantiation || TSK == TSK_Undeclared) - return NULL; + return nullptr; } if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) - return NULL; + return nullptr; } if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { // When tag declaration (but not definition!) is part of the // decl-specifier-seq of some other declaration, it doesn't get comment if (TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition()) - return NULL; + return nullptr; } // TODO: handle comments for function parameters properly. if (isa<ParmVarDecl>(D)) - return NULL; + return nullptr; // TODO: we could look up template parameter documentation in the template // documentation. if (isa<TemplateTypeParmDecl>(D) || isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTemplateParmDecl>(D)) - return NULL; + return nullptr; ArrayRef<RawComment *> RawComments = Comments.getComments(); // If there are no comments anywhere, we won't find anything. if (RawComments.empty()) - return NULL; + return nullptr; // Find declaration location. // For Objective-C declarations we generally don't expect to have multiple @@ -137,17 +145,29 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { DeclLoc = D->getLocStart(); else { DeclLoc = D->getLocation(); - // If location of the typedef name is in a macro, it is because being - // declared via a macro. Try using declaration's starting location - // as the "declaration location". - if (DeclLoc.isMacroID() && isa<TypedefDecl>(D)) - DeclLoc = D->getLocStart(); + if (DeclLoc.isMacroID()) { + if (isa<TypedefDecl>(D)) { + // If location of the typedef name is in a macro, it is because being + // declared via a macro. Try using declaration's starting location as + // the "declaration location". + DeclLoc = D->getLocStart(); + } else if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { + // If location of the tag decl is inside a macro, but the spelling of + // the tag name comes from a macro argument, it looks like a special + // macro like NS_ENUM is being used to define the tag decl. In that + // case, adjust the source location to the expansion loc so that we can + // attach the comment to the tag decl. + if (SourceMgr.isMacroArgExpansion(DeclLoc) && + TD->isCompleteDefinition()) + DeclLoc = SourceMgr.getExpansionLoc(DeclLoc); + } + } } // If the declaration doesn't map directly to a location in a file, we // can't find the comment. if (DeclLoc.isInvalid() || !DeclLoc.isFileID()) - return NULL; + return nullptr; // Find the comment that occurs just after this declaration. ArrayRef<RawComment *>::iterator Comment; @@ -201,12 +221,12 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // The comment just after the declaration was not a trailing comment. // Let's look at the previous comment. if (Comment == RawComments.begin()) - return NULL; + return nullptr; --Comment; // Check that we actually have a non-member Doxygen comment. if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment()) - return NULL; + return nullptr; // Decompose the end of the comment. std::pair<FileID, unsigned> CommentEndDecomp @@ -215,14 +235,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // If the comment and the declaration aren't in the same file, then they // aren't related. if (DeclLocDecomp.first != CommentEndDecomp.first) - return NULL; + return nullptr; // Get the corresponding buffer. bool Invalid = false; const char *Buffer = SourceMgr.getBufferData(DeclLocDecomp.first, &Invalid).data(); if (Invalid) - return NULL; + return nullptr; // Extract text between the comment and declaration. StringRef Text(Buffer + CommentEndDecomp.second, @@ -231,7 +251,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // There should be no other declarations or preprocessor directives between // comment and declaration. if (Text.find_first_of(";{}#@") != StringRef::npos) - return NULL; + return nullptr; return *Comment; } @@ -329,13 +349,11 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( } // Search for comments attached to declarations in the redeclaration chain. - const RawComment *RC = NULL; - const Decl *OriginalDeclForRC = NULL; - for (Decl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { + const RawComment *RC = nullptr; + const Decl *OriginalDeclForRC = nullptr; + for (auto I : D->redecls()) { llvm::DenseMap<const Decl *, RawCommentAndCacheFlags>::iterator Pos = - RedeclComments.find(*I); + RedeclComments.find(I); if (Pos != RedeclComments.end()) { const RawCommentAndCacheFlags &Raw = Pos->second; if (Raw.getKind() != RawCommentAndCacheFlags::NoCommentInDecl) { @@ -344,16 +362,16 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( break; } } else { - RC = getRawCommentForDeclNoCache(*I); - OriginalDeclForRC = *I; + RC = getRawCommentForDeclNoCache(I); + OriginalDeclForRC = I; RawCommentAndCacheFlags Raw; if (RC) { Raw.setRaw(RC); Raw.setKind(RawCommentAndCacheFlags::FromDecl); } else Raw.setKind(RawCommentAndCacheFlags::NoCommentInDecl); - Raw.setOriginalDecl(*I); - RedeclComments[*I] = Raw; + Raw.setOriginalDecl(I); + RedeclComments[I] = Raw; if (RC) break; } @@ -371,10 +389,8 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( Raw.setKind(RawCommentAndCacheFlags::FromRedecl); Raw.setOriginalDecl(OriginalDeclForRC); - for (Decl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { - RawCommentAndCacheFlags &R = RedeclComments[*I]; + for (auto I : D->redecls()) { + RawCommentAndCacheFlags &R = RedeclComments[I]; if (R.getKind() == RawCommentAndCacheFlags::NoCommentInDecl) R = Raw; } @@ -390,10 +406,7 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, if (!ID) return; // Add redeclared method here. - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = ID->known_extensions_begin(), - ExtEnd = ID->known_extensions_end(); - Ext != ExtEnd; ++Ext) { + for (const auto *Ext : ID->known_extensions()) { if (ObjCMethodDecl *RedeclaredMethod = Ext->getMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) @@ -409,6 +422,8 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, ThisDeclInfo->IsFilled = false; ThisDeclInfo->fill(); ThisDeclInfo->CommentDecl = FC->getDecl(); + if (!ThisDeclInfo->TemplateParameters) + ThisDeclInfo->TemplateParameters = FC->getDeclInfo()->TemplateParameters; comments::FullComment *CFC = new (*this) comments::FullComment(FC->getBlocks(), ThisDeclInfo); @@ -418,14 +433,14 @@ comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, comments::FullComment *ASTContext::getLocalCommentForDeclUncached(const Decl *D) const { const RawComment *RC = getRawCommentForDeclNoCache(D); - return RC ? RC->parse(*this, 0, D) : 0; + return RC ? RC->parse(*this, nullptr, D) : nullptr; } comments::FullComment *ASTContext::getCommentForDecl( const Decl *D, const Preprocessor *PP) const { if (D->isInvalidDecl()) - return NULL; + return nullptr; D = adjustDeclToTemplate(D); const Decl *Canonical = D->getCanonicalDecl(); @@ -482,13 +497,12 @@ comments::FullComment *ASTContext::getCommentForDecl( } else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { if (!(RD = RD->getDefinition())) - return NULL; + return nullptr; // Check non-virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = - RD->bases_begin(), E = RD->bases_end(); I != E; ++I) { - if (I->isVirtual() || (I->getAccessSpecifier() != AS_public)) + for (const auto &I : RD->bases()) { + if (I.isVirtual() || (I.getAccessSpecifier() != AS_public)) continue; - QualType Ty = I->getType(); + QualType Ty = I.getType(); if (Ty.isNull()) continue; if (const CXXRecordDecl *NonVirtualBase = Ty->getAsCXXRecordDecl()) { @@ -500,11 +514,10 @@ comments::FullComment *ASTContext::getCommentForDecl( } } // Check virtual bases. - for (CXXRecordDecl::base_class_const_iterator I = - RD->vbases_begin(), E = RD->vbases_end(); I != E; ++I) { - if (I->getAccessSpecifier() != AS_public) + for (const auto &I : RD->vbases()) { + if (I.getAccessSpecifier() != AS_public) continue; - QualType Ty = I->getType(); + QualType Ty = I.getType(); if (Ty.isNull()) continue; if (const CXXRecordDecl *VirtualBase = Ty->getAsCXXRecordDecl()) { @@ -515,7 +528,7 @@ comments::FullComment *ASTContext::getCommentForDecl( } } } - return NULL; + return nullptr; } // If the RawComment was attached to other redeclaration of this Decl, we @@ -576,7 +589,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( // Check if we already have a canonical template template parameter. llvm::FoldingSetNodeID ID; CanonicalTemplateTemplateParm::Profile(ID, TTP); - void *InsertPos = 0; + void *InsertPos = nullptr; CanonicalTemplateTemplateParm *Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); if (Canonical) @@ -595,7 +608,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), SourceLocation(), TTP->getDepth(), - TTP->getIndex(), 0, false, + TTP->getIndex(), nullptr, false, TTP->isParameterPack())); else if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { @@ -615,7 +628,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), SourceLocation(), NTTP->getDepth(), - NTTP->getPosition(), 0, + NTTP->getPosition(), nullptr, T, TInfo, ExpandedTypes.data(), @@ -626,7 +639,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), SourceLocation(), NTTP->getDepth(), - NTTP->getPosition(), 0, + NTTP->getPosition(), nullptr, T, NTTP->isParameterPack(), TInfo); @@ -643,7 +656,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( SourceLocation(), TTP->getDepth(), TTP->getPosition(), TTP->isParameterPack(), - 0, + nullptr, TemplateParameterList::Create(*this, SourceLocation(), SourceLocation(), CanonParams.data(), @@ -652,7 +665,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( // Get the new insert position for the node we care about. Canonical = CanonTemplateTemplateParms.FindNodeOrInsertPos(ID, InsertPos); - assert(Canonical == 0 && "Shouldn't be in the map!"); + assert(!Canonical && "Shouldn't be in the map!"); (void)Canonical; // Create the canonical template template parameter entry. @@ -662,13 +675,13 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( } CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { - if (!LangOpts.CPlusPlus) return 0; + if (!LangOpts.CPlusPlus) return nullptr; switch (T.getCXXABI().getKind()) { - case TargetCXXABI::GenericARM: + case TargetCXXABI::GenericARM: // Same as Itanium at this level case TargetCXXABI::iOS: - return CreateARMCXXABI(*this); - case TargetCXXABI::GenericAArch64: // Same as Itanium at this level + case TargetCXXABI::iOS64: + case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: return CreateItaniumCXXABI(*this); case TargetCXXABI::Microsoft: @@ -710,47 +723,40 @@ static bool isAddrSpaceMapManglingEnabled(const TargetInfo &TI, } ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, - const TargetInfo *t, IdentifierTable &idents, SelectorTable &sels, - Builtin::Context &builtins, - unsigned size_reserve, - bool DelayInitialization) + Builtin::Context &builtins) : FunctionProtoTypes(this_()), TemplateSpecializationTypes(this_()), DependentTemplateSpecializationTypes(this_()), SubstTemplateTemplateParmPacks(this_()), - GlobalNestedNameSpecifier(0), - Int128Decl(0), UInt128Decl(0), Float128StubDecl(0), - BuiltinVaListDecl(0), - ObjCIdDecl(0), ObjCSelDecl(0), ObjCClassDecl(0), ObjCProtocolClassDecl(0), - BOOLDecl(0), - CFConstantStringTypeDecl(0), ObjCInstanceTypeDecl(0), - FILEDecl(0), - jmp_bufDecl(0), sigjmp_bufDecl(0), ucontext_tDecl(0), - BlockDescriptorType(0), BlockDescriptorExtendedType(0), - cudaConfigureCallDecl(0), + GlobalNestedNameSpecifier(nullptr), + Int128Decl(nullptr), UInt128Decl(nullptr), Float128StubDecl(nullptr), + BuiltinVaListDecl(nullptr), + ObjCIdDecl(nullptr), ObjCSelDecl(nullptr), ObjCClassDecl(nullptr), + ObjCProtocolClassDecl(nullptr), BOOLDecl(nullptr), + CFConstantStringTypeDecl(nullptr), ObjCInstanceTypeDecl(nullptr), + FILEDecl(nullptr), + jmp_bufDecl(nullptr), sigjmp_bufDecl(nullptr), ucontext_tDecl(nullptr), + BlockDescriptorType(nullptr), BlockDescriptorExtendedType(nullptr), + cudaConfigureCallDecl(nullptr), NullTypeSourceInfo(QualType()), FirstLocalImport(), LastLocalImport(), SourceMgr(SM), LangOpts(LOpts), - AddrSpaceMap(0), Target(t), PrintingPolicy(LOpts), + AddrSpaceMap(nullptr), Target(nullptr), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), - ExternalSource(0), Listener(0), + ExternalSource(nullptr), Listener(nullptr), Comments(SM), CommentsLoaded(false), CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), - LastSDM(0, 0) + LastSDM(nullptr, 0) { - if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); - - if (!DelayInitialization) { - assert(t && "No target supplied for ASTContext initialization"); - InitBuiltinTypes(*t); - } } ASTContext::~ASTContext() { + ReleaseParentMapEntries(); + // Release the DenseMaps associated with DeclContext objects. // FIXME: Is this the ideal solution? ReleaseDeclContextMaps(); @@ -782,11 +788,19 @@ ASTContext::~ASTContext() { A != AEnd; ++A) A->second->~AttrVec(); - for (llvm::DenseMap<const DeclContext *, MangleNumberingContext *>::iterator - I = MangleNumberingContexts.begin(), - E = MangleNumberingContexts.end(); - I != E; ++I) - delete I->second; + llvm::DeleteContainerSeconds(MangleNumberingContexts); +} + +void ASTContext::ReleaseParentMapEntries() { + if (!AllParents) return; + for (const auto &Entry : *AllParents) { + if (Entry.second.is<ast_type_traits::DynTypedNode *>()) { + delete Entry.second.get<ast_type_traits::DynTypedNode *>(); + } else { + assert(Entry.second.is<ParentVector *>()); + delete Entry.second.get<ParentVector *>(); + } + } } void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { @@ -794,8 +808,8 @@ void ASTContext::AddDeallocation(void (*Callback)(void*), void *Data) { } void -ASTContext::setExternalSource(OwningPtr<ExternalASTSource> &Source) { - ExternalSource.reset(Source.take()); +ASTContext::setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source) { + ExternalSource = Source; } void ASTContext::PrintStats() const { @@ -849,7 +863,7 @@ void ASTContext::PrintStats() const { << NumImplicitDestructors << " implicit destructors created\n"; - if (ExternalSource.get()) { + if (ExternalSource) { llvm::errs() << "\n"; ExternalSource->PrintStats(); } @@ -857,45 +871,47 @@ void ASTContext::PrintStats() const { BumpAlloc.PrintStats(); } +RecordDecl *ASTContext::buildImplicitRecord(StringRef Name, + RecordDecl::TagKind TK) const { + SourceLocation Loc; + RecordDecl *NewDecl; + if (getLangOpts().CPlusPlus) + NewDecl = CXXRecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, + Loc, &Idents.get(Name)); + else + NewDecl = RecordDecl::Create(*this, TK, getTranslationUnitDecl(), Loc, Loc, + &Idents.get(Name)); + NewDecl->setImplicit(); + return NewDecl; +} + +TypedefDecl *ASTContext::buildImplicitTypedef(QualType T, + StringRef Name) const { + TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); + TypedefDecl *NewDecl = TypedefDecl::Create( + const_cast<ASTContext &>(*this), getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), &Idents.get(Name), TInfo); + NewDecl->setImplicit(); + return NewDecl; +} + TypedefDecl *ASTContext::getInt128Decl() const { - if (!Int128Decl) { - TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(Int128Ty); - Int128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("__int128_t"), - TInfo); - } - + if (!Int128Decl) + Int128Decl = buildImplicitTypedef(Int128Ty, "__int128_t"); return Int128Decl; } TypedefDecl *ASTContext::getUInt128Decl() const { - if (!UInt128Decl) { - TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(UnsignedInt128Ty); - UInt128Decl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("__uint128_t"), - TInfo); - } - + if (!UInt128Decl) + UInt128Decl = buildImplicitTypedef(UnsignedInt128Ty, "__uint128_t"); return UInt128Decl; } TypeDecl *ASTContext::getFloat128StubType() const { assert(LangOpts.CPlusPlus && "should only be called for c++"); - if (!Float128StubDecl) { - Float128StubDecl = CXXRecordDecl::Create(const_cast<ASTContext &>(*this), - TTK_Struct, - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("__float128")); - } - + if (!Float128StubDecl) + Float128StubDecl = buildImplicitRecord("__float128"); + return Float128StubDecl; } @@ -1106,7 +1122,7 @@ FunctionDecl *ASTContext::getClassScopeSpecializationPattern( llvm::DenseMap<const FunctionDecl*, FunctionDecl *>::const_iterator Pos = ClassScopeSpecializationPattern.find(FD); if (Pos == ClassScopeSpecializationPattern.end()) - return 0; + return nullptr; return Pos->second; } @@ -1123,7 +1139,7 @@ ASTContext::getInstantiatedFromUsingDecl(UsingDecl *UUD) { llvm::DenseMap<UsingDecl *, NamedDecl *>::const_iterator Pos = InstantiatedFromUsingDecl.find(UUD); if (Pos == InstantiatedFromUsingDecl.end()) - return 0; + return nullptr; return Pos->second; } @@ -1143,7 +1159,7 @@ ASTContext::getInstantiatedFromUsingShadowDecl(UsingShadowDecl *Inst) { llvm::DenseMap<UsingShadowDecl*, UsingShadowDecl*>::const_iterator Pos = InstantiatedFromUsingShadowDecl.find(Inst); if (Pos == InstantiatedFromUsingShadowDecl.end()) - return 0; + return nullptr; return Pos->second; } @@ -1159,7 +1175,7 @@ FieldDecl *ASTContext::getInstantiatedFromUnnamedFieldDecl(FieldDecl *Field) { llvm::DenseMap<FieldDecl *, FieldDecl *>::iterator Pos = InstantiatedFromUnnamedFieldDecl.find(Field); if (Pos == InstantiatedFromUnnamedFieldDecl.end()) - return 0; + return nullptr; return Pos->second; } @@ -1179,7 +1195,7 @@ ASTContext::overridden_methods_begin(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) - return 0; + return nullptr; return Pos->second.begin(); } @@ -1189,7 +1205,7 @@ ASTContext::overridden_methods_end(const CXXMethodDecl *Method) const { llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector>::const_iterator Pos = OverriddenMethods.find(Method->getCanonicalDecl()); if (Pos == OverriddenMethods.end()) - return 0; + return nullptr; return Pos->second.end(); } @@ -1293,13 +1309,14 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); - if (const ReferenceType* RT = T->getAs<ReferenceType>()) { + if (const ReferenceType *RT = T->getAs<ReferenceType>()) { if (ForAlignof) T = RT->getPointeeType(); else T = getPointerType(RT->getPointeeType()); } - if (!T->isIncompleteType() && !T->isFunctionType()) { + QualType BaseT = getBaseElementType(T); + if (!BaseT->isIncompleteType() && !T->isFunctionType()) { // Adjust alignments of declarations with array type by the // large-array alignment on the target. if (const ArrayType *arrayType = getAsArrayType(T)) { @@ -1311,9 +1328,6 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { MinWidth <= getTypeSize(cast<ConstantArrayType>(arrayType))) Align = std::max(Align, Target->getLargeArrayAlign()); } - - // Walk through any array types while we're at it. - T = getBaseElementType(arrayType); } Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { @@ -1618,7 +1632,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - llvm::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); + std::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); break; } case Type::Complex: { @@ -1632,8 +1646,9 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::ObjCObject: return getTypeInfo(cast<ObjCObjectType>(T)->getBaseType().getTypePtr()); + case Type::Adjusted: case Type::Decayed: - return getTypeInfo(cast<DecayedType>(T)->getDecayedType().getTypePtr()); + return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr()); case Type::ObjCInterface: { const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); @@ -1761,13 +1776,19 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { if (Target->getTriple().getArch() == llvm::Triple::xcore) return ABIAlign; // Never overalign on XCore. + const TypedefType *TT = T->getAs<TypedefType>(); + // Double and long long should be naturally aligned if possible. - if (const ComplexType* CT = T->getAs<ComplexType>()) + T = T->getBaseElementTypeUnsafe(); + if (const ComplexType *CT = T->getAs<ComplexType>()) T = CT->getElementType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || T->isSpecificBuiltinType(BuiltinType::LongLong) || T->isSpecificBuiltinType(BuiltinType::ULongLong)) - return std::max(ABIAlign, (unsigned)getTypeSize(T)); + // Don't increase the alignment if an alignment attribute was specified on a + // typedef declaration. + if (!TT || !TT->getDecl()->getMaxAlignment()) + return std::max(ABIAlign, (unsigned)getTypeSize(T)); return ABIAlign; } @@ -1796,9 +1817,8 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, if (const ObjCInterfaceDecl *SuperClass = OI->getSuperClass()) DeepCollectObjCIvars(SuperClass, false, Ivars); if (!leafClass) { - for (ObjCInterfaceDecl::ivar_iterator I = OI->ivar_begin(), - E = OI->ivar_end(); I != E; ++I) - Ivars.push_back(*I); + for (const auto *I : OI->ivars()) + Ivars.push_back(I); } else { ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI); for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; @@ -1814,24 +1834,17 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) { // We can use protocol_iterator here instead of // all_referenced_protocol_iterator since we are walking all categories. - for (ObjCInterfaceDecl::all_protocol_iterator P = OI->all_referenced_protocol_begin(), - PE = OI->all_referenced_protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (auto *Proto : OI->all_referenced_protocols()) { Protocols.insert(Proto->getCanonicalDecl()); - for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), - PE = Proto->protocol_end(); P != PE; ++P) { - Protocols.insert((*P)->getCanonicalDecl()); - CollectInheritedProtocols(*P, Protocols); + for (auto *P : Proto->protocols()) { + Protocols.insert(P->getCanonicalDecl()); + CollectInheritedProtocols(P, Protocols); } } // Categories of this Interface. - for (ObjCInterfaceDecl::visible_categories_iterator - Cat = OI->visible_categories_begin(), - CatEnd = OI->visible_categories_end(); - Cat != CatEnd; ++Cat) { - CollectInheritedProtocols(*Cat, Protocols); - } + for (const auto *Cat : OI->visible_categories()) + CollectInheritedProtocols(Cat, Protocols); if (ObjCInterfaceDecl *SD = OI->getSuperClass()) while (SD) { @@ -1839,22 +1852,16 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, SD = SD->getSuperClass(); } } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) { - for (ObjCCategoryDecl::protocol_iterator P = OC->protocol_begin(), - PE = OC->protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (auto *Proto : OC->protocols()) { Protocols.insert(Proto->getCanonicalDecl()); - for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), - PE = Proto->protocol_end(); P != PE; ++P) - CollectInheritedProtocols(*P, Protocols); + for (const auto *P : Proto->protocols()) + CollectInheritedProtocols(P, Protocols); } } else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) { - for (ObjCProtocolDecl::protocol_iterator P = OP->protocol_begin(), - PE = OP->protocol_end(); P != PE; ++P) { - ObjCProtocolDecl *Proto = (*P); + for (auto *Proto : OP->protocols()) { Protocols.insert(Proto->getCanonicalDecl()); - for (ObjCProtocolDecl::protocol_iterator P = Proto->protocol_begin(), - PE = Proto->protocol_end(); P != PE; ++P) - CollectInheritedProtocols(*P, Protocols); + for (const auto *P : Proto->protocols()) + CollectInheritedProtocols(P, Protocols); } } } @@ -1862,12 +1869,8 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. - for (ObjCInterfaceDecl::known_extensions_iterator - Ext = OI->known_extensions_begin(), - ExtEnd = OI->known_extensions_end(); - Ext != ExtEnd; ++Ext) { + for (const auto *Ext : OI->known_extensions()) count += Ext->ivar_size(); - } // Count ivar defined in this class's implementation. This // includes synthesized ivars. @@ -1901,7 +1904,7 @@ ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) I = ObjCImpls.find(D); if (I != ObjCImpls.end()) return cast<ObjCImplementationDecl>(I->second); - return 0; + return nullptr; } /// \brief Get the implementation of ObjCCategoryDecl, or NULL if none exists. ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { @@ -1909,7 +1912,7 @@ ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { I = ObjCImpls.find(D); if (I != ObjCImpls.end()) return cast<ObjCCategoryImplDecl>(I->second); - return 0; + return nullptr; } /// \brief Set the implementation of ObjCInterfaceDecl. @@ -1937,7 +1940,7 @@ const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( dyn_cast<ObjCImplDecl>(ND->getDeclContext())) return IMD->getClassInterface(); - return 0; + return nullptr; } /// \brief Get the copy initialization expression of VarDecl,or NULL if @@ -1948,7 +1951,7 @@ Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { "getBlockVarCopyInits - not __block var"); llvm::DenseMap<const VarDecl*, Expr*>::iterator I = BlockVarCopyInits.find(VD); - return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : 0; + return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : nullptr; } /// \brief Set the copy inialization expression of a block var decl. @@ -1982,7 +1985,7 @@ TypeSourceInfo *ASTContext::getTrivialTypeSourceInfo(QualType T, const ASTRecordLayout & ASTContext::getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const { - return getObjCLayout(D, 0); + return getObjCLayout(D, nullptr); } const ASTRecordLayout & @@ -2003,7 +2006,7 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const { // Check if we've already instantiated this type. llvm::FoldingSetNodeID ID; ExtQuals::Profile(ID, baseType, quals); - void *insertPos = 0; + void *insertPos = nullptr; if (ExtQuals *eq = ExtQualNodes.FindNodeOrInsertPos(ID, insertPos)) { assert(eq->getQualifiers() == quals); return QualType(eq, fastQuals); @@ -2080,12 +2083,12 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, QualType Result; if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) { - Result = getFunctionNoProtoType(FNPT->getResultType(), Info); + Result = getFunctionNoProtoType(FNPT->getReturnType(), Info); } else { const FunctionProtoType *FPT = cast<FunctionProtoType>(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; - Result = getFunctionType(FPT->getResultType(), FPT->getArgTypes(), EPI); + Result = getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI); } return cast<FunctionType>(Result.getTypePtr()); @@ -2097,7 +2100,7 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, while (true) { const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); - FD->setType(getFunctionType(ResultType, FPT->getArgTypes(), EPI)); + FD->setType(getFunctionType(ResultType, FPT->getParamTypes(), EPI)); if (FunctionDecl *Next = FD->getPreviousDecl()) FD = Next; else @@ -2115,7 +2118,7 @@ QualType ASTContext::getComplexType(QualType T) const { llvm::FoldingSetNodeID ID; ComplexType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ComplexType *CT = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(CT, 0); @@ -2127,7 +2130,7 @@ QualType ASTContext::getComplexType(QualType T) const { // Get the new insert position for the node we care about. ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical); Types.push_back(New); @@ -2143,7 +2146,7 @@ QualType ASTContext::getPointerType(QualType T) const { llvm::FoldingSetNodeID ID; PointerType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (PointerType *PT = PointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -2155,7 +2158,7 @@ QualType ASTContext::getPointerType(QualType T) const { // Get the new insert position for the node we care about. PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical); Types.push_back(New); @@ -2163,15 +2166,30 @@ QualType ASTContext::getPointerType(QualType T) const { return QualType(New, 0); } +QualType ASTContext::getAdjustedType(QualType Orig, QualType New) const { + llvm::FoldingSetNodeID ID; + AdjustedType::Profile(ID, Orig, New); + void *InsertPos = nullptr; + AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + + QualType Canonical = getCanonicalType(New); + + // Get the new insert position for the node we care about. + AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); + + AT = new (*this, TypeAlignment) + AdjustedType(Type::Adjusted, Orig, New, Canonical); + Types.push_back(AT); + AdjustedTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); +} + QualType ASTContext::getDecayedType(QualType T) const { assert((T->isArrayType() || T->isFunctionType()) && "T does not decay"); - llvm::FoldingSetNodeID ID; - DecayedType::Profile(ID, T); - void *InsertPos = 0; - if (DecayedType *DT = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos)) - return QualType(DT, 0); - QualType Decayed; // C99 6.7.5.3p7: @@ -2189,17 +2207,23 @@ QualType ASTContext::getDecayedType(QualType T) const { if (T->isFunctionType()) Decayed = getPointerType(T); + llvm::FoldingSetNodeID ID; + AdjustedType::Profile(ID, T, Decayed); + void *InsertPos = nullptr; + AdjustedType *AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + if (AT) + return QualType(AT, 0); + QualType Canonical = getCanonicalType(Decayed); // Get the new insert position for the node we care about. - DecayedType *NewIP = DecayedTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + AT = AdjustedTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!AT && "Shouldn't be in the map!"); - DecayedType *New = - new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); - Types.push_back(New); - DecayedTypes.InsertNode(New, InsertPos); - return QualType(New, 0); + AT = new (*this, TypeAlignment) DecayedType(T, Decayed, Canonical); + Types.push_back(AT); + AdjustedTypes.InsertNode(AT, InsertPos); + return QualType(AT, 0); } /// getBlockPointerType - Return the uniqued reference to the type for @@ -2211,7 +2235,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const { llvm::FoldingSetNodeID ID; BlockPointerType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (BlockPointerType *PT = BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -2225,7 +2249,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const { // Get the new insert position for the node we care about. BlockPointerType *NewIP = BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } BlockPointerType *New = new (*this, TypeAlignment) BlockPointerType(T, Canonical); @@ -2246,7 +2270,7 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { llvm::FoldingSetNodeID ID; ReferenceType::Profile(ID, T, SpelledAsLValue); - void *InsertPos = 0; + void *InsertPos = nullptr; if (LValueReferenceType *RT = LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); @@ -2263,7 +2287,7 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { // Get the new insert position for the node we care about. LValueReferenceType *NewIP = LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } LValueReferenceType *New @@ -2283,7 +2307,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { llvm::FoldingSetNodeID ID; ReferenceType::Profile(ID, T, false); - void *InsertPos = 0; + void *InsertPos = nullptr; if (RValueReferenceType *RT = RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); @@ -2300,7 +2324,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { // Get the new insert position for the node we care about. RValueReferenceType *NewIP = RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } RValueReferenceType *New @@ -2318,7 +2342,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { llvm::FoldingSetNodeID ID; MemberPointerType::Profile(ID, T, Cls); - void *InsertPos = 0; + void *InsertPos = nullptr; if (MemberPointerType *PT = MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(PT, 0); @@ -2332,7 +2356,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { // Get the new insert position for the node we care about. MemberPointerType *NewIP = MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } MemberPointerType *New = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical); @@ -2360,7 +2384,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, llvm::FoldingSetNodeID ID; ConstantArrayType::Profile(ID, EltTy, ArySize, ASM, IndexTypeQuals); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ConstantArrayType *ATP = ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(ATP, 0); @@ -2377,7 +2401,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, // Get the new insert position for the node we care about. ConstantArrayType *NewIP = ConstantArrayTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } ConstantArrayType *New = new(*this,TypeAlignment) @@ -2495,7 +2519,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { const IncompleteArrayType *iat = cast<IncompleteArrayType>(ty); result = getVariableArrayType( getVariableArrayDecayedType(iat->getElementType()), - /*size*/ 0, + /*size*/ nullptr, ArrayType::Normal, iat->getIndexTypeCVRQualifiers(), SourceRange()); @@ -2507,7 +2531,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { const VariableArrayType *vat = cast<VariableArrayType>(ty); result = getVariableArrayType( getVariableArrayDecayedType(vat->getElementType()), - /*size*/ 0, + /*size*/ nullptr, ArrayType::Star, vat->getIndexTypeCVRQualifiers(), vat->getBracketsRange()); @@ -2577,7 +2601,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, SplitQualType canonElementType = getCanonicalType(elementType).split(); - void *insertPos = 0; + void *insertPos = nullptr; llvm::FoldingSetNodeID ID; DependentSizedArrayType::Profile(ID, *this, QualType(canonElementType.Ty, 0), @@ -2622,7 +2646,7 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType, llvm::FoldingSetNodeID ID; IncompleteArrayType::Profile(ID, elementType, ASM, elementTypeQuals); - void *insertPos = 0; + void *insertPos = nullptr; if (IncompleteArrayType *iat = IncompleteArrayTypes.FindNodeOrInsertPos(ID, insertPos)) return QualType(iat, 0); @@ -2662,7 +2686,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, llvm::FoldingSetNodeID ID; VectorType::Profile(ID, vecType, NumElts, Type::Vector, VecKind); - void *InsertPos = 0; + void *InsertPos = nullptr; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -2674,7 +2698,7 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } VectorType *New = new (*this, TypeAlignment) VectorType(vecType, NumElts, Canonical, VecKind); @@ -2693,7 +2717,7 @@ ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const { llvm::FoldingSetNodeID ID; VectorType::Profile(ID, vecType, NumElts, Type::ExtVector, VectorType::GenericVector); - void *InsertPos = 0; + void *InsertPos = nullptr; if (VectorType *VTP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(VTP, 0); @@ -2705,7 +2729,7 @@ ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const { // Get the new insert position for the node we care about. VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } ExtVectorType *New = new (*this, TypeAlignment) ExtVectorType(vecType, NumElts, Canonical); @@ -2722,7 +2746,7 @@ ASTContext::getDependentSizedExtVectorType(QualType vecType, DependentSizedExtVectorType::Profile(ID, *this, getCanonicalType(vecType), SizeExpr); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentSizedExtVectorType *Canon = DependentSizedExtVectorTypes.FindNodeOrInsertPos(ID, InsertPos); DependentSizedExtVectorType *New; @@ -2768,7 +2792,7 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, llvm::FoldingSetNodeID ID; FunctionNoProtoType::Profile(ID, ResultTy, Info); - void *InsertPos = 0; + void *InsertPos = nullptr; if (FunctionNoProtoType *FT = FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(FT, 0); @@ -2780,7 +2804,7 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, // Get the new insert position for the node we care about. FunctionNoProtoType *NewIP = FunctionNoProtoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } FunctionProtoType::ExtInfo newInfo = Info.withCallingConv(CallConv); @@ -2798,8 +2822,6 @@ static bool isCanonicalResultType(QualType T) { T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); } -/// getFunctionType - Return a normal function type with a typed argument -/// list. isVariadic indicates whether the argument list includes '...'. QualType ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, const FunctionProtoType::ExtProtoInfo &EPI) const { @@ -2811,7 +2833,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, *this); - void *InsertPos = 0; + void *InsertPos = nullptr; if (FunctionProtoType *FTP = FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(FTP, 0); @@ -2851,7 +2873,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, // Get the new insert position for the node we care about. FunctionProtoType *NewIP = FunctionProtoTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } // FunctionProtoType objects are allocated with extra bytes after @@ -2873,7 +2895,7 @@ ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, } else if (EPI.ExceptionSpecType == EST_Unevaluated) { Size += sizeof(FunctionDecl*); } - if (EPI.ConsumedArguments) + if (EPI.ConsumedParameters) Size += NumArgs * sizeof(bool); FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); @@ -2995,7 +3017,7 @@ QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, llvm::FoldingSetNodeID id; AttributedType::Profile(id, attrKind, modifiedType, equivalentType); - void *insertPos = 0; + void *insertPos = nullptr; AttributedType *type = AttributedTypes.FindNodeOrInsertPos(id, insertPos); if (type) return QualType(type, 0); @@ -3019,7 +3041,7 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, llvm::FoldingSetNodeID ID; SubstTemplateTypeParmType::Profile(ID, Parm, Replacement); - void *InsertPos = 0; + void *InsertPos = nullptr; SubstTemplateTypeParmType *SubstParm = SubstTemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3038,17 +3060,15 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( const TemplateTypeParmType *Parm, const TemplateArgument &ArgPack) { #ifndef NDEBUG - for (TemplateArgument::pack_iterator P = ArgPack.pack_begin(), - PEnd = ArgPack.pack_end(); - P != PEnd; ++P) { - assert(P->getKind() == TemplateArgument::Type &&"Pack contains a non-type"); - assert(P->getAsType().isCanonical() && "Pack contains non-canonical type"); + for (const auto &P : ArgPack.pack_elements()) { + assert(P.getKind() == TemplateArgument::Type &&"Pack contains a non-type"); + assert(P.getAsType().isCanonical() && "Pack contains non-canonical type"); } #endif llvm::FoldingSetNodeID ID; SubstTemplateTypeParmPackType::Profile(ID, Parm, ArgPack); - void *InsertPos = 0; + void *InsertPos = nullptr; if (SubstTemplateTypeParmPackType *SubstParm = SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(SubstParm, 0); @@ -3077,7 +3097,7 @@ QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, TemplateTypeParmDecl *TTPDecl) const { llvm::FoldingSetNodeID ID; TemplateTypeParmType::Profile(ID, Depth, Index, ParameterPack, TTPDecl); - void *InsertPos = 0; + void *InsertPos = nullptr; TemplateTypeParmType *TypeParm = TemplateTypeParmTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3218,7 +3238,7 @@ ASTContext::getCanonicalTemplateSpecializationType(TemplateName Template, TemplateSpecializationType::Profile(ID, CanonTemplate, CanonArgs.data(), NumArgs, *this); - void *InsertPos = 0; + void *InsertPos = nullptr; TemplateSpecializationType *Spec = TemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -3246,7 +3266,7 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, llvm::FoldingSetNodeID ID; ElaboratedType::Profile(ID, Keyword, NNS, NamedType); - void *InsertPos = 0; + void *InsertPos = nullptr; ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); @@ -3270,7 +3290,7 @@ ASTContext::getParenType(QualType InnerType) const { llvm::FoldingSetNodeID ID; ParenType::Profile(ID, InnerType); - void *InsertPos = 0; + void *InsertPos = nullptr; ParenType *T = ParenTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) return QualType(T, 0); @@ -3293,8 +3313,6 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, QualType Canon) const { - assert(NNS->isDependent() && "nested-name-specifier must be dependent"); - if (Canon.isNull()) { NestedNameSpecifier *CanonNNS = getCanonicalNestedNameSpecifier(NNS); ElaboratedTypeKeyword CanonKeyword = Keyword; @@ -3308,7 +3326,7 @@ QualType ASTContext::getDependentNameType(ElaboratedTypeKeyword Keyword, llvm::FoldingSetNodeID ID; DependentNameType::Profile(ID, Keyword, NNS, Name); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentNameType *T = DependentNameTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) @@ -3349,7 +3367,7 @@ ASTContext::getDependentTemplateSpecializationType( DependentTemplateSpecializationType::Profile(ID, *this, Keyword, NNS, Name, NumArgs, Args); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentTemplateSpecializationType *T = DependentTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) @@ -3395,7 +3413,7 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, assert(Pattern->containsUnexpandedParameterPack() && "Pack expansions must expand one or more parameter packs"); - void *InsertPos = 0; + void *InsertPos = nullptr; PackExpansionType *T = PackExpansionTypes.FindNodeOrInsertPos(ID, InsertPos); if (T) @@ -3408,7 +3426,7 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, // contains an alias template specialization which ignores one of its // parameters. if (Canon->containsUnexpandedParameterPack()) { - Canon = getPackExpansionType(getCanonicalType(Pattern), NumExpansions); + Canon = getPackExpansionType(Canon, NumExpansions); // Find the insert position again, in case we inserted an element into // PackExpansionTypes and invalidated our insert position. @@ -3419,7 +3437,7 @@ QualType ASTContext::getPackExpansionType(QualType Pattern, T = new (*this) PackExpansionType(Pattern, Canon, NumExpansions); Types.push_back(T); PackExpansionTypes.InsertNode(T, InsertPos); - return QualType(T, 0); + return QualType(T, 0); } /// CmpProtocolNames - Comparison predicate for sorting protocols @@ -3470,7 +3488,7 @@ QualType ASTContext::getObjCObjectType(QualType BaseType, // Look in the folding set for an existing type. llvm::FoldingSetNodeID ID; ObjCObjectTypeImpl::Profile(ID, BaseType, Protocols, NumProtocols); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ObjCObjectType *QT = ObjCObjectTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); @@ -3507,13 +3525,79 @@ QualType ASTContext::getObjCObjectType(QualType BaseType, return QualType(T, 0); } +/// ObjCObjectAdoptsQTypeProtocols - Checks that protocols in IC's +/// protocol list adopt all protocols in QT's qualified-id protocol +/// list. +bool ASTContext::ObjCObjectAdoptsQTypeProtocols(QualType QT, + ObjCInterfaceDecl *IC) { + if (!QT->isObjCQualifiedIdType()) + return false; + + if (const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>()) { + // If both the right and left sides have qualifiers. + for (auto *Proto : OPT->quals()) { + if (!IC->ClassImplementsProtocol(Proto, false)) + return false; + } + return true; + } + return false; +} + +/// QIdProtocolsAdoptObjCObjectProtocols - Checks that protocols in +/// QT's qualified-id protocol list adopt all protocols in IDecl's list +/// of protocols. +bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT, + ObjCInterfaceDecl *IDecl) { + if (!QT->isObjCQualifiedIdType()) + return false; + const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>(); + if (!OPT) + return false; + if (!IDecl->hasDefinition()) + return false; + llvm::SmallPtrSet<ObjCProtocolDecl *, 8> InheritedProtocols; + CollectInheritedProtocols(IDecl, InheritedProtocols); + if (InheritedProtocols.empty()) + return false; + // Check that if every protocol in list of id<plist> conforms to a protcol + // of IDecl's, then bridge casting is ok. + bool Conforms = false; + for (auto *Proto : OPT->quals()) { + Conforms = false; + for (auto *PI : InheritedProtocols) { + if (ProtocolCompatibleWithProtocol(Proto, PI)) { + Conforms = true; + break; + } + } + if (!Conforms) + break; + } + if (Conforms) + return true; + + for (auto *PI : InheritedProtocols) { + // If both the right and left sides have qualifiers. + bool Adopts = false; + for (auto *Proto : OPT->quals()) { + // return 'true' if 'PI' is in the inheritance hierarchy of Proto + if ((Adopts = ProtocolCompatibleWithProtocol(PI, Proto))) + break; + } + if (!Adopts) + return false; + } + return true; +} + /// getObjCObjectPointerType - Return a ObjCObjectPointerType type for /// the given object type. QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const { llvm::FoldingSetNodeID ID; ObjCObjectPointerType::Profile(ID, ObjectT); - void *InsertPos = 0; + void *InsertPos = nullptr; if (ObjCObjectPointerType *QT = ObjCObjectPointerTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(QT, 0); @@ -3572,7 +3656,7 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { llvm::FoldingSetNodeID ID; DependentTypeOfExprType::Profile(ID, *this, tofExpr); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentTypeOfExprType *Canon = DependentTypeOfExprTypes.FindNodeOrInsertPos(ID, InsertPos); if (Canon) { @@ -3596,10 +3680,10 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { } /// getTypeOfType - Unlike many "get<Type>" functions, we don't unique -/// TypeOfType AST's. The only motivation to unique these nodes would be +/// TypeOfType nodes. The only motivation to unique these nodes would be /// memory savings. Since typeof(t) is fairly uncommon, space shouldn't be -/// an issue. This doesn't effect the type checker, since it operates -/// on canonical type's (which are always unique). +/// an issue. This doesn't affect the type checker, since it operates +/// on canonical types (which are always unique). QualType ASTContext::getTypeOfType(QualType tofType) const { QualType Canonical = getCanonicalType(tofType); TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical); @@ -3608,39 +3692,34 @@ QualType ASTContext::getTypeOfType(QualType tofType) const { } -/// getDecltypeType - Unlike many "get<Type>" functions, we don't unique -/// DecltypeType AST's. The only motivation to unique these nodes would be -/// memory savings. Since decltype(t) is fairly uncommon, space shouldn't be -/// an issue. This doesn't effect the type checker, since it operates -/// on canonical types (which are always unique). +/// \brief Unlike many "get<Type>" functions, we don't unique DecltypeType +/// nodes. This would never be helpful, since each such type has its own +/// expression, and would not give a significant memory saving, since there +/// is an Expr tree under each such type. QualType ASTContext::getDecltypeType(Expr *e, QualType UnderlyingType) const { DecltypeType *dt; - - // C++0x [temp.type]p2: + + // C++11 [temp.type]p2: // If an expression e involves a template parameter, decltype(e) denotes a - // unique dependent type. Two such decltype-specifiers refer to the same - // type only if their expressions are equivalent (14.5.6.1). + // unique dependent type. Two such decltype-specifiers refer to the same + // type only if their expressions are equivalent (14.5.6.1). if (e->isInstantiationDependent()) { llvm::FoldingSetNodeID ID; DependentDecltypeType::Profile(ID, *this, e); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentDecltypeType *Canon = DependentDecltypeTypes.FindNodeOrInsertPos(ID, InsertPos); - if (Canon) { - // We already have a "canonical" version of an equivalent, dependent - // decltype type. Use that as our canonical type. - dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType, - QualType((DecltypeType*)Canon, 0)); - } else { + if (!Canon) { // Build a new, canonical typeof(expr) type. Canon = new (*this, TypeAlignment) DependentDecltypeType(*this, e); DependentDecltypeTypes.InsertNode(Canon, InsertPos); - dt = Canon; } + dt = new (*this, TypeAlignment) + DecltypeType(e, UnderlyingType, QualType((DecltypeType *)Canon, 0)); } else { - dt = new (*this, TypeAlignment) DecltypeType(e, UnderlyingType, - getCanonicalType(UnderlyingType)); + dt = new (*this, TypeAlignment) + DecltypeType(e, UnderlyingType, getCanonicalType(UnderlyingType)); } Types.push_back(dt); return QualType(dt, 0); @@ -3670,7 +3749,7 @@ QualType ASTContext::getAutoType(QualType DeducedType, bool IsDecltypeAuto, return getAutoDeductType(); // Look in the folding set for an existing type. - void *InsertPos = 0; + void *InsertPos = nullptr; llvm::FoldingSetNodeID ID; AutoType::Profile(ID, DeducedType, IsDecltypeAuto, IsDependent); if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) @@ -3693,7 +3772,7 @@ QualType ASTContext::getAtomicType(QualType T) const { llvm::FoldingSetNodeID ID; AtomicType::Profile(ID, T); - void *InsertPos = 0; + void *InsertPos = nullptr; if (AtomicType *AT = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(AT, 0); @@ -3705,7 +3784,7 @@ QualType ASTContext::getAtomicType(QualType T) const { // Get the new insert position for the node we care about. AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos); - assert(NewIP == 0 && "Shouldn't be in the map!"); (void)NewIP; + assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical); Types.push_back(New); @@ -4064,7 +4143,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { NestedNameSpecifier * ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { if (!NNS) - return 0; + return nullptr; switch (NNS->getKind()) { case NestedNameSpecifier::Identifier: @@ -4076,13 +4155,13 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { case NestedNameSpecifier::Namespace: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, 0, + return NestedNameSpecifier::Create(*this, nullptr, NNS->getAsNamespace()->getOriginalNamespace()); case NestedNameSpecifier::NamespaceAlias: // A namespace is canonical; build a nested-name-specifier with // this namespace and no prefix. - return NestedNameSpecifier::Create(*this, 0, + return NestedNameSpecifier::Create(*this, nullptr, NNS->getAsNamespaceAlias()->getNamespace() ->getOriginalNamespace()); @@ -4104,8 +4183,8 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { // Otherwise, just canonicalize the type, and force it to be a TypeSpec. // FIXME: Why are TypeSpec and TypeSpecWithTemplate distinct in the // first place? - return NestedNameSpecifier::Create(*this, 0, false, - const_cast<Type*>(T.getTypePtr())); + return NestedNameSpecifier::Create(*this, nullptr, false, + const_cast<Type *>(T.getTypePtr())); } case NestedNameSpecifier::Global: @@ -4127,7 +4206,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // Handle the common negative case fast. if (!isa<ArrayType>(T.getCanonicalType())) - return 0; + return nullptr; // Apply any qualifiers from the array type to the element type. This // implements C99 6.7.3p8: "If the specification of an array type includes @@ -4142,7 +4221,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // If we have a simple case, just return now. const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty); - if (ATy == 0 || qs.empty()) + if (!ATy || qs.empty()) return ATy; // Otherwise, we have an array and we have qualifiers on it. Push the @@ -4428,7 +4507,7 @@ static const Type *getIntegerTypeForEnum(const EnumType *ET) { // FIXME: In C++, enum types are never integer types. if (ET->getDecl()->isComplete() && !ET->getDecl()->isScoped()) return ET->getDecl()->getIntegerType().getTypePtr(); - return NULL; + return nullptr; } /// getIntegerTypeOrder - Returns the highest ranked integer type: @@ -4479,22 +4558,10 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { return 1; } -static RecordDecl * -CreateRecordDecl(const ASTContext &Ctx, RecordDecl::TagKind TK, - DeclContext *DC, IdentifierInfo *Id) { - SourceLocation Loc; - if (Ctx.getLangOpts().CPlusPlus) - return CXXRecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); - else - return RecordDecl::Create(Ctx, TK, DC, Loc, Loc, Id); -} - // getCFConstantStringType - Return the type used for constant CFStrings. QualType ASTContext::getCFConstantStringType() const { if (!CFConstantStringTypeDecl) { - CFConstantStringTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("NSConstantString")); + CFConstantStringTypeDecl = buildImplicitRecord("NSConstantString"); CFConstantStringTypeDecl->startDefinition(); QualType FieldTypes[4]; @@ -4512,9 +4579,9 @@ QualType ASTContext::getCFConstantStringType() const { for (unsigned i = 0; i < 4; ++i) { FieldDecl *Field = FieldDecl::Create(*this, CFConstantStringTypeDecl, SourceLocation(), - SourceLocation(), 0, - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + SourceLocation(), nullptr, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -4529,8 +4596,7 @@ QualType ASTContext::getCFConstantStringType() const { QualType ASTContext::getObjCSuperType() const { if (ObjCSuperType.isNull()) { - RecordDecl *ObjCSuperTypeDecl = - CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("objc_super")); + RecordDecl *ObjCSuperTypeDecl = buildImplicitRecord("objc_super"); TUDecl->addDecl(ObjCSuperTypeDecl); ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl); } @@ -4547,12 +4613,11 @@ QualType ASTContext::getBlockDescriptorType() const { if (BlockDescriptorType) return getTagDeclType(BlockDescriptorType); - RecordDecl *T; + RecordDecl *RD; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("__block_descriptor")); - T->startDefinition(); - + RD = buildImplicitRecord("__block_descriptor"); + RD->startDefinition(); + QualType FieldTypes[] = { UnsignedLongTy, UnsignedLongTy, @@ -4564,20 +4629,17 @@ QualType ASTContext::getBlockDescriptorType() const { }; for (size_t i = 0; i < 2; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false, - ICIS_NoInit); + FieldDecl *Field = FieldDecl::Create( + *this, RD, SourceLocation(), SourceLocation(), + &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); - T->addDecl(Field); + RD->addDecl(Field); } - T->completeDefinition(); + RD->completeDefinition(); - BlockDescriptorType = T; + BlockDescriptorType = RD; return getTagDeclType(BlockDescriptorType); } @@ -4586,12 +4648,11 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { if (BlockDescriptorExtendedType) return getTagDeclType(BlockDescriptorExtendedType); - RecordDecl *T; + RecordDecl *RD; // FIXME: Needs the FlagAppleBlock bit. - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, - &Idents.get("__block_descriptor_withcopydispose")); - T->startDefinition(); - + RD = buildImplicitRecord("__block_descriptor_withcopydispose"); + RD->startDefinition(); + QualType FieldTypes[] = { UnsignedLongTy, UnsignedLongTy, @@ -4607,21 +4668,18 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { }; for (size_t i = 0; i < 4; ++i) { - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, - /*Mutable=*/false, - ICIS_NoInit); + FieldDecl *Field = FieldDecl::Create( + *this, RD, SourceLocation(), SourceLocation(), + &Idents.get(FieldNames[i]), FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, + /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); - T->addDecl(Field); + RD->addDecl(Field); } - T->completeDefinition(); - - BlockDescriptorExtendedType = T; + RD->completeDefinition(); + BlockDescriptorExtendedType = RD; return getTagDeclType(BlockDescriptorExtendedType); } @@ -4691,12 +4749,8 @@ bool ASTContext::getByrefLifetime(QualType Ty, TypedefDecl *ASTContext::getObjCInstanceTypeDecl() { if (!ObjCInstanceTypeDecl) - ObjCInstanceTypeDecl = TypedefDecl::Create(*this, - getTranslationUnitDecl(), - SourceLocation(), - SourceLocation(), - &Idents.get("instancetype"), - getTrivialTypeSourceInfo(getObjCIdType())); + ObjCInstanceTypeDecl = + buildImplicitTypedef(getObjCIdType(), "instancetype"); return ObjCInstanceTypeDecl; } @@ -4727,6 +4781,12 @@ CharUnits ASTContext::getObjCEncodingTypeSize(QualType type) const { return sz; } +bool ASTContext::isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const { + return getLangOpts().MSVCCompat && VD->isStaticDataMember() && + VD->getType()->isIntegralOrEnumerationType() && + !VD->getFirstDecl()->isOutOfLine() && VD->getFirstDecl()->hasInit(); +} + static inline std::string charUnitsToString(const CharUnits &CU) { return llvm::itostr(CU.getQuantity()); @@ -4742,21 +4802,19 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { Expr->getType()->getAs<BlockPointerType>()->getPointeeType(); // Encode result type. if (getLangOpts().EncodeExtendedBlockSig) - getObjCEncodingForMethodParameter(Decl::OBJC_TQ_None, - BlockTy->getAs<FunctionType>()->getResultType(), - S, true /*Extended*/); + getObjCEncodingForMethodParameter( + Decl::OBJC_TQ_None, BlockTy->getAs<FunctionType>()->getReturnType(), S, + true /*Extended*/); else - getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getResultType(), - S); + getObjCEncodingForType(BlockTy->getAs<FunctionType>()->getReturnType(), S); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! SourceLocation Loc; CharUnits PtrSize = getTypeSizeInChars(VoidPtrTy); CharUnits ParmOffset = PtrSize; - for (BlockDecl::param_const_iterator PI = Decl->param_begin(), - E = Decl->param_end(); PI != E; ++PI) { - QualType PType = (*PI)->getType(); + for (auto PI : Decl->params()) { + QualType PType = PI->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) continue; @@ -4770,9 +4828,7 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { // Argument types. ParmOffset = PtrSize; - for (BlockDecl::param_const_iterator PI = Decl->param_begin(), E = - Decl->param_end(); PI != E; ++PI) { - ParmVarDecl *PVDecl = *PI; + for (auto PVDecl : Decl->params()) { QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -4797,12 +4853,11 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, std::string& S) { // Encode result type. - getObjCEncodingForType(Decl->getResultType(), S); + getObjCEncodingForType(Decl->getReturnType(), S); CharUnits ParmOffset; // Compute size of all parameters. - for (FunctionDecl::param_const_iterator PI = Decl->param_begin(), - E = Decl->param_end(); PI != E; ++PI) { - QualType PType = (*PI)->getType(); + for (auto PI : Decl->params()) { + QualType PType = PI->getType(); CharUnits sz = getObjCEncodingTypeSize(PType); if (sz.isZero()) continue; @@ -4815,9 +4870,7 @@ bool ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl, ParmOffset = CharUnits::Zero(); // Argument types. - for (FunctionDecl::param_const_iterator PI = Decl->param_begin(), - E = Decl->param_end(); PI != E; ++PI) { - ParmVarDecl *PVDecl = *PI; + for (auto PVDecl : Decl->params()) { QualType PType = PVDecl->getOriginalType(); if (const ArrayType *AT = dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { @@ -4844,7 +4897,7 @@ void ASTContext::getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, // Encode type qualifer, 'in', 'inout', etc. for the parameter. getObjCEncodingForTypeQualifier(QT, S); // Encode parameter type. - getObjCEncodingForTypeImpl(T, S, true, true, 0, + getObjCEncodingForTypeImpl(T, S, true, true, nullptr, true /*OutermostType*/, false /*EncodingProperty*/, false /*StructField*/, @@ -4859,8 +4912,8 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended) const { // FIXME: This is not very efficient. // Encode return type. - getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), - Decl->getResultType(), S, Extended); + getObjCEncodingForMethodParameter(Decl->getObjCDeclQualifier(), + Decl->getReturnType(), S, Extended); // Compute size of all parameters. // Start with computing size of a pointer in number of bytes. // FIXME: There might(should) be a better way of doing this computation! @@ -4907,6 +4960,26 @@ bool ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, return false; } +ObjCPropertyImplDecl * +ASTContext::getObjCPropertyImplDeclForPropertyDecl( + const ObjCPropertyDecl *PD, + const Decl *Container) const { + if (!Container) + return nullptr; + if (const ObjCCategoryImplDecl *CID = + dyn_cast<ObjCCategoryImplDecl>(Container)) { + for (auto *PID : CID->property_impls()) + if (PID->getPropertyDecl() == PD) + return PID; + } else { + const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container); + for (auto *PID : OID->property_impls()) + if (PID->getPropertyDecl() == PD) + return PID; + } + return nullptr; +} + /// getObjCEncodingForPropertyDecl - Return the encoded type for this /// property declaration. If non-NULL, Container must be either an /// ObjCCategoryImplDecl or ObjCImplementationDecl; it should only be @@ -4937,39 +5010,14 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, std::string& S) const { // Collect information from the property implementation decl(s). bool Dynamic = false; - ObjCPropertyImplDecl *SynthesizePID = 0; - - // FIXME: Duplicated code due to poor abstraction. - if (Container) { - if (const ObjCCategoryImplDecl *CID = - dyn_cast<ObjCCategoryImplDecl>(Container)) { - for (ObjCCategoryImplDecl::propimpl_iterator - i = CID->propimpl_begin(), e = CID->propimpl_end(); - i != e; ++i) { - ObjCPropertyImplDecl *PID = *i; - if (PID->getPropertyDecl() == PD) { - if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) { - Dynamic = true; - } else { - SynthesizePID = PID; - } - } - } - } else { - const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container); - for (ObjCCategoryImplDecl::propimpl_iterator - i = OID->propimpl_begin(), e = OID->propimpl_end(); - i != e; ++i) { - ObjCPropertyImplDecl *PID = *i; - if (PID->getPropertyDecl() == PD) { - if (PID->getPropertyImplementation()==ObjCPropertyImplDecl::Dynamic) { - Dynamic = true; - } else { - SynthesizePID = PID; - } - } - } - } + ObjCPropertyImplDecl *SynthesizePID = nullptr; + + if (ObjCPropertyImplDecl *PropertyImpDecl = + getObjCPropertyImplDeclForPropertyDecl(PD, Container)) { + if (PropertyImpDecl->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic) + Dynamic = true; + else + SynthesizePID = PropertyImpDecl; } // FIXME: This is not very efficient. @@ -4978,9 +5026,7 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, // Encode result type. // GCC has some special rules regarding encoding of properties which // closely resembles encoding of ivars. - getObjCEncodingForTypeImpl(PD->getType(), S, true, true, 0, - true /* outermost type */, - true /* encoding for property */); + getObjCEncodingForPropertyType(PD->getType(), S); if (PD->isReadOnly()) { S += ",R"; @@ -4988,6 +5034,8 @@ void ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, S += ",C"; if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_retain) S += ",&"; + if (PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_weak) + S += ",W"; } else { switch (PD->getSetterKind()) { case ObjCPropertyDecl::Assign: break; @@ -5051,6 +5099,16 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, true /* outermost type */); } +void ASTContext::getObjCEncodingForPropertyType(QualType T, + std::string& S) const { + // Encode result type. + // GCC has some special rules regarding encoding of properties which + // closely resembles encoding of ivars. + getObjCEncodingForTypeImpl(T, S, true, true, nullptr, + true /* outermost type */, + true /* encoding property */); +} + static char getObjCEncodingForPrimitiveKind(const ASTContext *C, BuiltinType::Kind kind) { switch (kind) { @@ -5180,15 +5238,15 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Complex: { const ComplexType *CT = T->castAs<ComplexType>(); S += 'j'; - getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false, - false); + getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr, + false, false); return; } case Type::Atomic: { const AtomicType *AT = T->castAs<AtomicType>(); S += 'A'; - getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0, + getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr, false, false); return; } @@ -5260,7 +5318,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, getLegacyIntegralTypeEncoding(PointeeTy); getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - NULL); + nullptr); return; } @@ -5322,9 +5380,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (!RDecl->isUnion()) { getObjCEncodingForStructureImpl(RDecl, S, FD); } else { - for (RecordDecl::field_iterator Field = RDecl->field_begin(), - FieldEnd = RDecl->field_end(); - Field != FieldEnd; ++Field) { + for (const auto *Field : RDecl->fields()) { if (FD) { S += '"'; S += Field->getNameAsString(); @@ -5334,7 +5390,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Special case bit-fields. if (Field->isBitField()) { getObjCEncodingForTypeImpl(Field->getType(), S, false, true, - *Field); + Field); } else { QualType qt = Field->getType(); getLegacyIntegralTypeEncoding(qt); @@ -5358,37 +5414,38 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += '<'; // Block return type - getObjCEncodingForTypeImpl(FT->getResultType(), S, - ExpandPointedToStructures, ExpandStructures, - FD, - false /* OutermostType */, - EncodingProperty, - false /* StructField */, - EncodeBlockParameters, - EncodeClassNames); + getObjCEncodingForTypeImpl( + FT->getReturnType(), S, ExpandPointedToStructures, ExpandStructures, + FD, false /* OutermostType */, EncodingProperty, + false /* StructField */, EncodeBlockParameters, EncodeClassNames); // Block self S += "@?"; // Block parameters if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { - for (FunctionProtoType::arg_type_iterator I = FPT->arg_type_begin(), - E = FPT->arg_type_end(); I && (I != E); ++I) { - getObjCEncodingForTypeImpl(*I, S, - ExpandPointedToStructures, - ExpandStructures, - FD, - false /* OutermostType */, - EncodingProperty, - false /* StructField */, - EncodeBlockParameters, - EncodeClassNames); - } + for (const auto &I : FPT->param_types()) + getObjCEncodingForTypeImpl( + I, S, ExpandPointedToStructures, ExpandStructures, FD, + false /* OutermostType */, EncodingProperty, + false /* StructField */, EncodeBlockParameters, EncodeClassNames); } S += '>'; } return; } - case Type::ObjCObject: + case Type::ObjCObject: { + // hack to match legacy encoding of *id and *Class + QualType Ty = getObjCObjectPointerType(CT); + if (Ty->isObjCIdType()) { + S += "{objc_object=}"; + return; + } + else if (Ty->isObjCClassType()) { + S += "{objc_class=}"; + return; + } + } + case Type::ObjCInterface: { // Ignore protocol qualifiers when mangling at this level. T = T->castAs<ObjCObjectType>()->getBaseType(); @@ -5440,10 +5497,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Note that we do extended encoding of protocol qualifer list // Only when doing ivar or property encoding. S += '"'; - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) { + for (const auto *I : OPT->quals()) { S += '<'; - S += (*I)->getNameAsString(); + S += I->getNameAsString(); S += '>'; } S += '"'; @@ -5475,7 +5531,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - NULL, + nullptr, false, false, false, false, false, /*EncodePointerToObjCTypedef*/true); return; @@ -5486,10 +5542,9 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, (FD || EncodingProperty || EncodeClassNames)) { S += '"'; S += OPT->getInterfaceDecl()->getIdentifier()->getName(); - for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), - E = OPT->qual_end(); I != E; ++I) { + for (const auto *I : OPT->quals()) { S += '<'; - S += (*I)->getNameAsString(); + S += I->getNameAsString(); S += '>'; } S += '"'; @@ -5542,11 +5597,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, const ASTRecordLayout &layout = getASTRecordLayout(RDecl); if (CXXRec) { - for (CXXRecordDecl::base_class_iterator - BI = CXXRec->bases_begin(), - BE = CXXRec->bases_end(); BI != BE; ++BI) { - if (!BI->isVirtual()) { - CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl(); + for (const auto &BI : CXXRec->bases()) { + if (!BI.isVirtual()) { + CXXRecordDecl *base = BI.getType()->getAsCXXRecordDecl(); if (base->isEmpty()) continue; uint64_t offs = toBits(layout.getBaseClassOffset(base)); @@ -5566,10 +5619,8 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, } if (CXXRec && includeVBases) { - for (CXXRecordDecl::base_class_iterator - BI = CXXRec->vbases_begin(), - BE = CXXRec->vbases_end(); BI != BE; ++BI) { - CXXRecordDecl *base = BI->getType()->getAsCXXRecordDecl(); + for (const auto &BI : CXXRec->vbases()) { + CXXRecordDecl *base = BI.getType()->getAsCXXRecordDecl(); if (base->isEmpty()) continue; uint64_t offs = toBits(layout.getVBaseClassOffset(base)); @@ -5587,7 +5638,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, size = layout.getSize(); } +#ifndef NDEBUG uint64_t CurOffs = 0; +#endif std::multimap<uint64_t, NamedDecl *>::iterator CurLayObj = FieldOrBaseOffsets.begin(); @@ -5601,19 +5654,21 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, S += '"'; } S += "^^?"; +#ifndef NDEBUG CurOffs += getTypeSize(VoidPtrTy); +#endif } if (!RDecl->hasFlexibleArrayMember()) { // Mark the end of the structure. uint64_t offs = toBits(size); FieldOrBaseOffsets.insert(FieldOrBaseOffsets.upper_bound(offs), - std::make_pair(offs, (NamedDecl*)0)); + std::make_pair(offs, nullptr)); } for (; CurLayObj != FieldOrBaseOffsets.end(); ++CurLayObj) { +#ifndef NDEBUG assert(CurOffs <= CurLayObj->first); - if (CurOffs < CurLayObj->first) { uint64_t padding = CurLayObj->first - CurOffs; // FIXME: There doesn't seem to be a way to indicate in the encoding that @@ -5625,9 +5680,10 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, // longer then though. CurOffs += padding; } +#endif NamedDecl *dcl = CurLayObj->second; - if (dcl == 0) + if (!dcl) break; // reached end of structure. if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) { @@ -5637,7 +5693,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, // making the encoding type bigger than it really is. getObjCEncodingForStructureImpl(base, S, FD, /*includeVBases*/false); assert(!base->isEmpty()); +#ifndef NDEBUG CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize()); +#endif } else { FieldDecl *field = cast<FieldDecl>(dcl); if (FD) { @@ -5648,7 +5706,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (field->isBitField()) { EncodeBitField(this, S, field->getType(), field); +#ifndef NDEBUG CurOffs += field->getBitWidthValue(*this); +#endif } else { QualType qt = field->getType(); getLegacyIntegralTypeEncoding(qt); @@ -5656,7 +5716,9 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, /*OutermostType*/false, /*EncodingProperty*/false, /*StructField*/true); +#ifndef NDEBUG CurOffs += getTypeSize(field->getType()); +#endif } } } @@ -5680,41 +5742,27 @@ void ASTContext::getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, TypedefDecl *ASTContext::getObjCIdDecl() const { if (!ObjCIdDecl) { - QualType T = getObjCObjectType(ObjCBuiltinIdTy, 0, 0); + QualType T = getObjCObjectType(ObjCBuiltinIdTy, nullptr, 0); T = getObjCObjectPointerType(T); - TypeSourceInfo *IdInfo = getTrivialTypeSourceInfo(T); - ObjCIdDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Idents.get("id"), IdInfo); + ObjCIdDecl = buildImplicitTypedef(T, "id"); } - return ObjCIdDecl; } TypedefDecl *ASTContext::getObjCSelDecl() const { if (!ObjCSelDecl) { - QualType SelT = getPointerType(ObjCBuiltinSelTy); - TypeSourceInfo *SelInfo = getTrivialTypeSourceInfo(SelT); - ObjCSelDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Idents.get("SEL"), SelInfo); + QualType T = getPointerType(ObjCBuiltinSelTy); + ObjCSelDecl = buildImplicitTypedef(T, "SEL"); } return ObjCSelDecl; } TypedefDecl *ASTContext::getObjCClassDecl() const { if (!ObjCClassDecl) { - QualType T = getObjCObjectType(ObjCBuiltinClassTy, 0, 0); + QualType T = getObjCObjectType(ObjCBuiltinClassTy, nullptr, 0); T = getObjCObjectPointerType(T); - TypeSourceInfo *ClassInfo = getTrivialTypeSourceInfo(T); - ObjCClassDecl = TypedefDecl::Create(const_cast<ASTContext &>(*this), - getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Idents.get("Class"), ClassInfo); + ObjCClassDecl = buildImplicitTypedef(T, "Class"); } - return ObjCClassDecl; } @@ -5724,7 +5772,7 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const { = ObjCInterfaceDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), &Idents.get("Protocol"), - /*PrevDecl=*/0, + /*PrevDecl=*/nullptr, SourceLocation(), true); } @@ -5737,56 +5785,30 @@ ObjCInterfaceDecl *ASTContext::getObjCProtocolDecl() const { static TypedefDecl *CreateCharPtrBuiltinVaListDecl(const ASTContext *Context) { // typedef char* __builtin_va_list; - QualType CharPtrType = Context->getPointerType(Context->CharTy); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(CharPtrType); - - TypedefDecl *VaListTypeDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - return VaListTypeDecl; + QualType T = Context->getPointerType(Context->CharTy); + return Context->buildImplicitTypedef(T, "__builtin_va_list"); } static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { // typedef void* __builtin_va_list; - QualType VoidPtrType = Context->getPointerType(Context->VoidTy); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VoidPtrType); - - TypedefDecl *VaListTypeDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - return VaListTypeDecl; + QualType T = Context->getPointerType(Context->VoidTy); + return Context->buildImplicitTypedef(T, "__builtin_va_list"); } static TypedefDecl * CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { - RecordDecl *VaListTagDecl; + // struct __va_list + RecordDecl *VaListTagDecl = Context->buildImplicitRecord("__va_list"); if (Context->getLangOpts().CPlusPlus) { // namespace std { struct __va_list { NamespaceDecl *NS; NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context), Context->getTranslationUnitDecl(), - /*Inline*/false, SourceLocation(), + /*Inline*/ false, SourceLocation(), SourceLocation(), &Context->Idents.get("std"), - /*PrevDecl*/0); - - VaListTagDecl = CXXRecordDecl::Create(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list")); + /*PrevDecl*/ nullptr); + NS->setImplicit(); VaListTagDecl->setDeclContext(NS); - } else { - // struct __va_list - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list")); } VaListTagDecl->startDefinition(); @@ -5822,8 +5844,8 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -5834,23 +5856,14 @@ CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __builtin_va_list; - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - Context->getTrivialTypeSourceInfo(VaListTagType)); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagType, "__builtin_va_list"); } static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list_tag")); + VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); const size_t NumFields = 5; @@ -5883,8 +5896,8 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -5895,12 +5908,9 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list_tag"), - Context->getTrivialTypeSourceInfo(VaListTagType)); + TypedefDecl *VaListTagTypedefDecl = + Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); + QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl); @@ -5909,25 +5919,14 @@ static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { QualType VaListTagArrayType = Context->getConstantArrayType(VaListTagTypedefType, Size, ArrayType::Normal, 0); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VaListTagArrayType); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } static TypedefDecl * CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list_tag")); + VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); const size_t NumFields = 4; @@ -5957,8 +5956,8 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -5969,12 +5968,9 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list_tag"), - Context->getTrivialTypeSourceInfo(VaListTagType)); + TypedefDecl *VaListTagTypedefDecl = + Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); + QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl); @@ -5983,16 +5979,7 @@ CreateX86_64ABIBuiltinVaListDecl(const ASTContext *Context) { QualType VaListTagArrayType = Context->getConstantArrayType(VaListTagTypedefType, Size, ArrayType::Normal,0); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VaListTagArrayType); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { @@ -6001,19 +5988,13 @@ static TypedefDecl *CreatePNaClABIBuiltinVaListDecl(const ASTContext *Context) { QualType IntArrayType = Context->getConstantArrayType(Context->IntTy, Size, ArrayType::Normal, 0); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - Context->getTrivialTypeSourceInfo(IntArrayType)); - - return VaListTypedefDecl; + return Context->buildImplicitTypedef(IntArrayType, "__builtin_va_list"); } static TypedefDecl * CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { - RecordDecl *VaListDecl; + // struct __va_list + RecordDecl *VaListDecl = Context->buildImplicitRecord("__va_list"); if (Context->getLangOpts().CPlusPlus) { // namespace std { struct __va_list { NamespaceDecl *NS; @@ -6021,20 +6002,9 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { Context->getTranslationUnitDecl(), /*Inline*/false, SourceLocation(), SourceLocation(), &Context->Idents.get("std"), - /*PrevDecl*/0); - - VaListDecl = CXXRecordDecl::Create(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list")); - + /*PrevDecl*/ nullptr); + NS->setImplicit(); VaListDecl->setDeclContext(NS); - - } else { - // struct __va_list { - VaListDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list")); } VaListDecl->startDefinition(); @@ -6046,8 +6016,8 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), &Context->Idents.get("__ap"), Context->getPointerType(Context->VoidTy), - /*TInfo=*/0, - /*BitWidth=*/0, + /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -6057,26 +6027,15 @@ CreateAAPCSABIBuiltinVaListDecl(const ASTContext *Context) { VaListDecl->completeDefinition(); // typedef struct __va_list __builtin_va_list; - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(Context->getRecordType(VaListDecl)); - - TypedefDecl *VaListTypeDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - - return VaListTypeDecl; + QualType T = Context->getRecordType(VaListDecl); + return Context->buildImplicitTypedef(T, "__builtin_va_list"); } static TypedefDecl * CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; - VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, - Context->getTranslationUnitDecl(), - &Context->Idents.get("__va_list_tag")); + VaListTagDecl = Context->buildImplicitRecord("__va_list_tag"); VaListTagDecl->startDefinition(); const size_t NumFields = 4; @@ -6106,8 +6065,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { SourceLocation(), SourceLocation(), &Context->Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, + FieldTypes[i], /*TInfo=*/nullptr, + /*BitWidth=*/nullptr, /*Mutable=*/false, ICIS_NoInit); Field->setAccess(AS_public); @@ -6118,12 +6077,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { Context->VaListTagTy = VaListTagType; // } __va_list_tag; - TypedefDecl *VaListTagTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__va_list_tag"), - Context->getTrivialTypeSourceInfo(VaListTagType)); + TypedefDecl *VaListTagTypedefDecl = + Context->buildImplicitTypedef(VaListTagType, "__va_list_tag"); QualType VaListTagTypedefType = Context->getTypedefType(VaListTagTypedefDecl); @@ -6132,16 +6087,8 @@ CreateSystemZBuiltinVaListDecl(const ASTContext *Context) { QualType VaListTagArrayType = Context->getConstantArrayType(VaListTagTypedefType, Size, ArrayType::Normal,0); - TypeSourceInfo *TInfo - = Context->getTrivialTypeSourceInfo(VaListTagArrayType); - TypedefDecl *VaListTypedefDecl - = TypedefDecl::Create(const_cast<ASTContext &>(*Context), - Context->getTranslationUnitDecl(), - SourceLocation(), SourceLocation(), - &Context->Idents.get("__builtin_va_list"), - TInfo); - return VaListTypedefDecl; + return Context->buildImplicitTypedef(VaListTagArrayType, "__builtin_va_list"); } static TypedefDecl *CreateVaListDecl(const ASTContext *Context, @@ -6169,8 +6116,10 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context, } TypedefDecl *ASTContext::getBuiltinVaListDecl() const { - if (!BuiltinVaListDecl) + if (!BuiltinVaListDecl) { BuiltinVaListDecl = CreateVaListDecl(this, Target->getBuiltinVaListKind()); + assert(BuiltinVaListDecl->isImplicit()); + } return BuiltinVaListDecl; } @@ -6227,7 +6176,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, llvm::FoldingSetNodeID ID; QualifiedTemplateName::Profile(ID, NNS, TemplateKeyword, Template); - void *InsertPos = 0; + void *InsertPos = nullptr; QualifiedTemplateName *QTN = QualifiedTemplateNames.FindNodeOrInsertPos(ID, InsertPos); if (!QTN) { @@ -6250,7 +6199,7 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, llvm::FoldingSetNodeID ID; DependentTemplateName::Profile(ID, NNS, Name); - void *InsertPos = 0; + void *InsertPos = nullptr; DependentTemplateName *QTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6285,8 +6234,8 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, llvm::FoldingSetNodeID ID; DependentTemplateName::Profile(ID, NNS, Operator); - - void *InsertPos = 0; + + void *InsertPos = nullptr; DependentTemplateName *QTN = DependentTemplateNames.FindNodeOrInsertPos(ID, InsertPos); @@ -6317,8 +6266,8 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, TemplateName replacement) const { llvm::FoldingSetNodeID ID; SubstTemplateTemplateParmStorage::Profile(ID, param, replacement); - - void *insertPos = 0; + + void *insertPos = nullptr; SubstTemplateTemplateParmStorage *subst = SubstTemplateTemplateParms.FindNodeOrInsertPos(ID, insertPos); @@ -6336,8 +6285,8 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, ASTContext &Self = const_cast<ASTContext &>(*this); llvm::FoldingSetNodeID ID; SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack); - - void *InsertPos = 0; + + void *InsertPos = nullptr; SubstTemplateTemplateParmPackStorage *Subst = SubstTemplateTemplateParmPacks.FindNodeOrInsertPos(ID, InsertPos); @@ -6454,9 +6403,8 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, ObjCProtocolDecl *rProto) const { if (declaresSameEntity(lProto, rProto)) return true; - for (ObjCProtocolDecl::protocol_iterator PI = rProto->protocol_begin(), - E = rProto->protocol_end(); PI != E; ++PI) - if (ProtocolCompatibleWithProtocol(lProto, *PI)) + for (auto *PI : rProto->protocols()) + if (ProtocolCompatibleWithProtocol(lProto, PI)) return true; return false; } @@ -6469,13 +6417,9 @@ bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); assert ((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible"); - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { + for (auto *lhsProto : lhsQID->quals()) { bool match = false; - ObjCProtocolDecl *lhsProto = *I; - for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(), - E = rhsOPT->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsOPT->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto)) { match = true; break; @@ -6508,12 +6452,11 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // If the RHS is a unqualified interface pointer "NSString*", // make sure we check the class hierarchy. if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { + for (auto *I : lhsQID->quals()) { // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. - if (!rhsID->ClassImplementsProtocol(*I, true)) + if (!rhsID->ClassImplementsProtocol(I, true)) return false; } } @@ -6521,17 +6464,13 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, return true; } // Both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { - ObjCProtocolDecl *lhsProto = *I; + for (auto *lhsProto : lhsQID->quals()) { bool match = false; // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. - for (ObjCObjectPointerType::qual_iterator J = rhsOPT->qual_begin(), - E = rhsOPT->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsOPT->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { match = true; @@ -6541,12 +6480,11 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // If the RHS is a qualified interface pointer "NSString<P>*", // make sure we check the class hierarchy. if (ObjCInterfaceDecl *rhsID = rhsOPT->getInterfaceDecl()) { - for (ObjCObjectPointerType::qual_iterator I = lhsQID->qual_begin(), - E = lhsQID->qual_end(); I != E; ++I) { + for (auto *I : lhsQID->quals()) { // when comparing an id<P> on lhs with a static type on rhs, // see if static class implements all of id's protocols, directly or // through its super class and categories. - if (rhsID->ClassImplementsProtocol(*I, true)) { + if (rhsID->ClassImplementsProtocol(I, true)) { match = true; break; } @@ -6565,9 +6503,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, if (const ObjCObjectPointerType *lhsOPT = lhs->getAsObjCInterfacePointerType()) { // If both the right and left sides have qualifiers. - for (ObjCObjectPointerType::qual_iterator I = lhsOPT->qual_begin(), - E = lhsOPT->qual_end(); I != E; ++I) { - ObjCProtocolDecl *lhsProto = *I; + for (auto *lhsProto : lhsOPT->quals()) { bool match = false; // when comparing an id<P> on rhs with a static type on lhs, @@ -6575,9 +6511,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // through its super class and categories. // First, lhs protocols in the qualifier list must be found, direct // or indirect in rhs's qualifier list or it is a mismatch. - for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), - E = rhsQID->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsQID->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { match = true; @@ -6598,14 +6532,9 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, // assume that it is mismatch. if (LHSInheritedProtocols.empty() && lhsOPT->qual_empty()) return false; - for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I = - LHSInheritedProtocols.begin(), - E = LHSInheritedProtocols.end(); I != E; ++I) { + for (auto *lhsProto : LHSInheritedProtocols) { bool match = false; - ObjCProtocolDecl *lhsProto = (*I); - for (ObjCObjectPointerType::qual_iterator J = rhsQID->qual_begin(), - E = rhsQID->qual_end(); J != E; ++J) { - ObjCProtocolDecl *rhsProto = *J; + for (auto *rhsProto : rhsQID->quals()) { if (ProtocolCompatibleWithProtocol(lhsProto, rhsProto) || (compare && ProtocolCompatibleWithProtocol(rhsProto, lhsProto))) { match = true; @@ -6798,16 +6727,9 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, if (SuperClassInheritedProtocols.empty()) return false; - for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), - LHSPE = LHS->qual_end(); - LHSPI != LHSPE; LHSPI++) { - bool SuperImplementsProtocol = false; - ObjCProtocolDecl *LHSProto = (*LHSPI); - - for (llvm::SmallPtrSet<ObjCProtocolDecl*,8>::iterator I = - SuperClassInheritedProtocols.begin(), - E = SuperClassInheritedProtocols.end(); I != E; ++I) { - ObjCProtocolDecl *SuperClassProto = (*I); + for (const auto *LHSProto : LHS->quals()) { + bool SuperImplementsProtocol = false; + for (auto *SuperClassProto : SuperClassInheritedProtocols) { if (SuperClassProto->lookupProtocolNamed(LHSProto->getIdentifier())) { SuperImplementsProtocol = true; break; @@ -6821,17 +6743,13 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, return false; } - for (ObjCObjectType::qual_iterator LHSPI = LHS->qual_begin(), - LHSPE = LHS->qual_end(); - LHSPI != LHSPE; LHSPI++) { + for (const auto *LHSPI : LHS->quals()) { bool RHSImplementsProtocol = false; // If the RHS doesn't implement the protocol on the left, the types // are incompatible. - for (ObjCObjectType::qual_iterator RHSPI = RHS->qual_begin(), - RHSPE = RHS->qual_end(); - RHSPI != RHSPE; RHSPI++) { - if ((*RHSPI)->lookupProtocolNamed((*LHSPI)->getIdentifier())) { + for (auto *RHSPI : RHS->quals()) { + if (RHSPI->lookupProtocolNamed(LHSPI->getIdentifier())) { RHSImplementsProtocol = true; break; } @@ -6891,9 +6809,8 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, if (const RecordType *UT = T->getAsUnionType()) { RecordDecl *UD = UT->getDecl(); if (UD->hasAttr<TransparentUnionAttr>()) { - for (RecordDecl::field_iterator it = UD->field_begin(), - itend = UD->field_end(); it != itend; ++it) { - QualType ET = it->getType().getUnqualifiedType(); + for (const auto *I : UD->fields()) { + QualType ET = I->getType().getUnqualifiedType(); QualType MT = mergeTypes(ET, SubType, OfBlockPointer, Unqualified); if (!MT.isNull()) return MT; @@ -6904,11 +6821,11 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, return QualType(); } -/// mergeFunctionArgumentTypes - merge two types which appear as function -/// argument types -QualType ASTContext::mergeFunctionArgumentTypes(QualType lhs, QualType rhs, - bool OfBlockPointer, - bool Unqualified) { +/// mergeFunctionParameterTypes - merge two types which appear as function +/// parameter types +QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs, + bool OfBlockPointer, + bool Unqualified) { // GNU extension: two types are compatible if they appear as a function // argument, one of the types is a transparent union type and the other // type is compatible with a union member @@ -6938,23 +6855,23 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // Check return type QualType retType; if (OfBlockPointer) { - QualType RHS = rbase->getResultType(); - QualType LHS = lbase->getResultType(); + QualType RHS = rbase->getReturnType(); + QualType LHS = lbase->getReturnType(); bool UnqualifiedResult = Unqualified; if (!UnqualifiedResult) UnqualifiedResult = (!RHS.hasQualifiers() && LHS.hasQualifiers()); retType = mergeTypes(LHS, RHS, true, UnqualifiedResult, true); } else - retType = mergeTypes(lbase->getResultType(), rbase->getResultType(), false, + retType = mergeTypes(lbase->getReturnType(), rbase->getReturnType(), false, Unqualified); if (retType.isNull()) return QualType(); if (Unqualified) retType = retType.getUnqualifiedType(); - CanQualType LRetType = getCanonicalType(lbase->getResultType()); - CanQualType RRetType = getCanonicalType(rbase->getResultType()); + CanQualType LRetType = getCanonicalType(lbase->getReturnType()); + CanQualType RRetType = getCanonicalType(rbase->getReturnType()); if (Unqualified) { LRetType = LRetType.getUnqualifiedType(); RRetType = RRetType.getUnqualifiedType(); @@ -6998,11 +6915,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lproto && rproto) { // two C99 style function prototypes assert(!lproto->hasExceptionSpec() && !rproto->hasExceptionSpec() && "C++ shouldn't be here"); - unsigned lproto_nargs = lproto->getNumArgs(); - unsigned rproto_nargs = rproto->getNumArgs(); - - // Compatible functions must have the same number of arguments - if (lproto_nargs != rproto_nargs) + // Compatible functions must have the same number of parameters + if (lproto->getNumParams() != rproto->getNumParams()) return QualType(); // Variadic and non-variadic functions aren't compatible @@ -7015,29 +6929,29 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (LangOpts.ObjCAutoRefCount && !FunctionTypesMatchOnNSConsumedAttrs(rproto, lproto)) return QualType(); - - // Check argument compatibility + + // Check parameter type compatibility SmallVector<QualType, 10> types; - for (unsigned i = 0; i < lproto_nargs; i++) { - QualType largtype = lproto->getArgType(i).getUnqualifiedType(); - QualType rargtype = rproto->getArgType(i).getUnqualifiedType(); - QualType argtype = mergeFunctionArgumentTypes(largtype, rargtype, - OfBlockPointer, - Unqualified); - if (argtype.isNull()) return QualType(); - + for (unsigned i = 0, n = lproto->getNumParams(); i < n; i++) { + QualType lParamType = lproto->getParamType(i).getUnqualifiedType(); + QualType rParamType = rproto->getParamType(i).getUnqualifiedType(); + QualType paramType = mergeFunctionParameterTypes( + lParamType, rParamType, OfBlockPointer, Unqualified); + if (paramType.isNull()) + return QualType(); + if (Unqualified) - argtype = argtype.getUnqualifiedType(); - - types.push_back(argtype); + paramType = paramType.getUnqualifiedType(); + + types.push_back(paramType); if (Unqualified) { - largtype = largtype.getUnqualifiedType(); - rargtype = rargtype.getUnqualifiedType(); + lParamType = lParamType.getUnqualifiedType(); + rParamType = rParamType.getUnqualifiedType(); } - - if (getCanonicalType(argtype) != getCanonicalType(largtype)) + + if (getCanonicalType(paramType) != getCanonicalType(lParamType)) allLTypes = false; - if (getCanonicalType(argtype) != getCanonicalType(rargtype)) + if (getCanonicalType(paramType) != getCanonicalType(rParamType)) allRTypes = false; } @@ -7061,20 +6975,19 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // The only types actually affected are promotable integer // types and floats, which would be passed as a different // type depending on whether the prototype is visible. - unsigned proto_nargs = proto->getNumArgs(); - for (unsigned i = 0; i < proto_nargs; ++i) { - QualType argTy = proto->getArgType(i); - + for (unsigned i = 0, n = proto->getNumParams(); i < n; ++i) { + QualType paramTy = proto->getParamType(i); + // Look at the converted type of enum types, since that is the type used // to pass enum values. - if (const EnumType *Enum = argTy->getAs<EnumType>()) { - argTy = Enum->getDecl()->getIntegerType(); - if (argTy.isNull()) + if (const EnumType *Enum = paramTy->getAs<EnumType>()) { + paramTy = Enum->getDecl()->getIntegerType(); + if (paramTy.isNull()) return QualType(); } - - if (argTy->isPromotableIntegerType() || - getCanonicalType(argTy).getUnqualifiedType() == FloatTy) + + if (paramTy->isPromotableIntegerType() || + getCanonicalType(paramTy).getUnqualifiedType() == FloatTy) return QualType(); } @@ -7083,7 +6996,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, proto->getArgTypes(), EPI); + return getFunctionType(retType, proto->getParamTypes(), EPI); } if (allLTypes) return lhs; @@ -7387,18 +7300,16 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool ASTContext::FunctionTypesMatchOnNSConsumedAttrs( const FunctionProtoType *FromFunctionType, const FunctionProtoType *ToFunctionType) { - if (FromFunctionType->hasAnyConsumedArgs() != - ToFunctionType->hasAnyConsumedArgs()) + if (FromFunctionType->hasAnyConsumedParams() != + ToFunctionType->hasAnyConsumedParams()) return false; FunctionProtoType::ExtProtoInfo FromEPI = FromFunctionType->getExtProtoInfo(); FunctionProtoType::ExtProtoInfo ToEPI = ToFunctionType->getExtProtoInfo(); - if (FromEPI.ConsumedArguments && ToEPI.ConsumedArguments) - for (unsigned ArgIdx = 0, NumArgs = FromFunctionType->getNumArgs(); - ArgIdx != NumArgs; ++ArgIdx) { - if (FromEPI.ConsumedArguments[ArgIdx] != - ToEPI.ConsumedArguments[ArgIdx]) + if (FromEPI.ConsumedParameters && ToEPI.ConsumedParameters) + for (unsigned i = 0, n = FromFunctionType->getNumParams(); i != n; ++i) { + if (FromEPI.ConsumedParameters[i] != ToEPI.ConsumedParameters[i]) return false; } return true; @@ -7416,10 +7327,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { if (RHSCan->isFunctionType()) { if (!LHSCan->isFunctionType()) return QualType(); - QualType OldReturnType = - cast<FunctionType>(RHSCan.getTypePtr())->getResultType(); + QualType OldReturnType = + cast<FunctionType>(RHSCan.getTypePtr())->getReturnType(); QualType NewReturnType = - cast<FunctionType>(LHSCan.getTypePtr())->getResultType(); + cast<FunctionType>(LHSCan.getTypePtr())->getReturnType(); QualType ResReturnType = mergeObjCGCQualifiers(NewReturnType, OldReturnType); if (ResReturnType.isNull()) @@ -7432,7 +7343,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType = - getFunctionType(OldReturnType, FPT->getArgTypes(), EPI); + getFunctionType(OldReturnType, FPT->getParamTypes(), EPI); return ResultType; } } @@ -7573,6 +7484,19 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, assert(HowLong <= 2 && "Can't have LLLL modifier"); ++HowLong; break; + case 'W': + // This modifier represents int64 type. + assert(HowLong == 0 && "Can't use both 'L' and 'W' modifiers!"); + switch (Context.getTargetInfo().getInt64Type()) { + default: + llvm_unreachable("Unexpected integer type"); + case TargetInfo::SignedLong: + HowLong = 1; + break; + case TargetInfo::SignedLongLong: + HowLong = 2; + break; + } } } @@ -7834,7 +7758,8 @@ QualType ASTContext::GetBuiltinType(unsigned Id, return getFunctionType(ResType, ArgTypes, EPI); } -GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { +static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, + const FunctionDecl *FD) { if (!FD->isExternallyVisible()) return GVA_Internal; @@ -7846,68 +7771,126 @@ GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { break; case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + return GVA_StrongODR; + // C++11 [temp.explicit]p10: + // [ Note: The intent is that an inline function that is the subject of + // an explicit instantiation declaration will still be implicitly + // instantiated when used so that the body can be considered for + // inlining, but that no out-of-line copy of the inline function would be + // generated in the translation unit. -- end note ] case TSK_ExplicitInstantiationDeclaration: + return GVA_AvailableExternally; + case TSK_ImplicitInstantiation: - External = GVA_TemplateInstantiation; + External = GVA_DiscardableODR; break; } if (!FD->isInlined()) return External; - if ((!getLangOpts().CPlusPlus && !getLangOpts().MicrosoftMode) || + if ((!Context.getLangOpts().CPlusPlus && !Context.getLangOpts().MSVCCompat && + !FD->hasAttr<DLLExportAttr>()) || FD->hasAttr<GNUInlineAttr>()) { + // FIXME: This doesn't match gcc's behavior for dllexport inline functions. + // GNU or C99 inline semantics. Determine whether this symbol should be // externally visible. if (FD->isInlineDefinitionExternallyVisible()) return External; // C99 inline semantics, where the symbol is not externally visible. - return GVA_C99Inline; + return GVA_AvailableExternally; } - // C++0x [temp.explicit]p9: - // [ Note: The intent is that an inline function that is the subject of - // an explicit instantiation declaration will still be implicitly - // instantiated when used so that the body can be considered for - // inlining, but that no out-of-line copy of the inline function would be - // generated in the translation unit. -- end note ] - if (FD->getTemplateSpecializationKind() - == TSK_ExplicitInstantiationDeclaration) - return GVA_C99Inline; + // Functions specified with extern and inline in -fms-compatibility mode + // forcibly get emitted. While the body of the function cannot be later + // replaced, the function definition cannot be discarded. + if (FD->getMostRecentDecl()->isMSExternInline()) + return GVA_StrongODR; - return GVA_CXXInline; + return GVA_DiscardableODR; } -GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { +static GVALinkage adjustGVALinkageForDLLAttribute(GVALinkage L, const Decl *D) { + // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx + // dllexport/dllimport on inline functions. + if (D->hasAttr<DLLImportAttr>()) { + if (L == GVA_DiscardableODR || L == GVA_StrongODR) + return GVA_AvailableExternally; + } else if (D->hasAttr<DLLExportAttr>()) { + if (L == GVA_DiscardableODR) + return GVA_StrongODR; + } + return L; +} + +GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) const { + return adjustGVALinkageForDLLAttribute(basicGVALinkageForFunction(*this, FD), + FD); +} + +static GVALinkage basicGVALinkageForVariable(const ASTContext &Context, + const VarDecl *VD) { if (!VD->isExternallyVisible()) return GVA_Internal; + if (VD->isStaticLocal()) { + GVALinkage StaticLocalLinkage = GVA_DiscardableODR; + const DeclContext *LexicalContext = VD->getParentFunctionOrMethod(); + while (LexicalContext && !isa<FunctionDecl>(LexicalContext)) + LexicalContext = LexicalContext->getLexicalParent(); + + // Let the static local variable inherit it's linkage from the nearest + // enclosing function. + if (LexicalContext) + StaticLocalLinkage = + Context.GetGVALinkageForFunction(cast<FunctionDecl>(LexicalContext)); + + // GVA_StrongODR function linkage is stronger than what we need, + // downgrade to GVA_DiscardableODR. + // This allows us to discard the variable if we never end up needing it. + return StaticLocalLinkage == GVA_StrongODR ? GVA_DiscardableODR + : StaticLocalLinkage; + } + + // MSVC treats in-class initialized static data members as definitions. + // By giving them non-strong linkage, out-of-line definitions won't + // cause link errors. + if (Context.isMSStaticDataMemberInlineDefinition(VD)) + return GVA_DiscardableODR; + switch (VD->getTemplateSpecializationKind()) { case TSK_Undeclared: case TSK_ExplicitSpecialization: return GVA_StrongExternal; - case TSK_ExplicitInstantiationDeclaration: - llvm_unreachable("Variable should not be instantiated"); - // Fall through to treat this like any other instantiation. - case TSK_ExplicitInstantiationDefinition: - return GVA_ExplicitTemplateInstantiation; + return GVA_StrongODR; + + case TSK_ExplicitInstantiationDeclaration: + return GVA_AvailableExternally; case TSK_ImplicitInstantiation: - return GVA_TemplateInstantiation; + return GVA_DiscardableODR; } llvm_unreachable("Invalid Linkage!"); } +GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { + return adjustGVALinkageForDLLAttribute(basicGVALinkageForVariable(*this, VD), + VD); +} + bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (!VD->isFileVarDecl()) return false; + // Global named register variables (GNU extension) are never emitted. + if (VD->getStorageClass() == SC_Register) + return false; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { // We never need to emit an uninstantiated function template. if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) @@ -7954,8 +7937,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // static, static inline, always_inline, and extern inline functions can // always be deferred. Normal inline functions can be deferred in C99/C++. // Implicit template instantiations can also be deferred in C++. - if (Linkage == GVA_Internal || Linkage == GVA_C99Inline || - Linkage == GVA_CXXInline || Linkage == GVA_TemplateInstantiation) + if (Linkage == GVA_Internal || Linkage == GVA_AvailableExternally || + Linkage == GVA_DiscardableODR) return false; return true; } @@ -7963,12 +7946,14 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { const VarDecl *VD = cast<VarDecl>(D); assert(VD->isFileVarDecl() && "Expected file scoped var"); - if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) + if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly && + !isMSStaticDataMemberInlineDefinition(VD)) return false; // Variables that can be needed in other TUs are required. GVALinkage L = GetGVALinkageForVariable(VD); - if (L != GVA_Internal && L != GVA_TemplateInstantiation) + if (L != GVA_Internal && L != GVA_AvailableExternally && + L != GVA_DiscardableODR) return true; // Variables that have destruction with side-effects are required. @@ -7996,12 +7981,23 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { return ABI->isNearlyEmpty(RD); } +VTableContextBase *ASTContext::getVTableContext() { + if (!VTContext.get()) { + if (Target->getCXXABI().isMicrosoft()) + VTContext.reset(new MicrosoftVTableContext(*this)); + else + VTContext.reset(new ItaniumVTableContext(*this)); + } + return VTContext.get(); +} + MangleContext *ASTContext::createMangleContext() { switch (Target->getCXXABI().getKind()) { case TargetCXXABI::GenericAArch64: case TargetCXXABI::GenericItanium: case TargetCXXABI::GenericARM: case TargetCXXABI::iOS: + case TargetCXXABI::iOS64: return ItaniumMangleContext::create(*this, getDiagnostics()); case TargetCXXABI::Microsoft: return MicrosoftMangleContext::create(*this, getDiagnostics()); @@ -8071,6 +8067,17 @@ unsigned ASTContext::getManglingNumber(const NamedDecl *ND) const { return I != MangleNumbers.end() ? I->second : 1; } +void ASTContext::setStaticLocalNumber(const VarDecl *VD, unsigned Number) { + if (Number > 1) + StaticLocalNumbers[VD] = Number; +} + +unsigned ASTContext::getStaticLocalNumber(const VarDecl *VD) const { + llvm::DenseMap<const VarDecl *, unsigned>::const_iterator I = + StaticLocalNumbers.find(VD); + return I != StaticLocalNumbers.end() ? I->second : 1; +} + MangleNumberingContext & ASTContext::getManglingNumberContext(const DeclContext *DC) { assert(LangOpts.CPlusPlus); // We don't need mangling numbers for plain C. @@ -8105,7 +8112,7 @@ ASTContext::getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, llvm::DenseMap<const MaterializeTemporaryExpr *, APValue>::iterator I = MaterializedTemporaryValues.find(E); - return I == MaterializedTemporaryValues.end() ? 0 : &I->second; + return I == MaterializedTemporaryValues.end() ? nullptr : &I->second; } bool ASTContext::AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const { @@ -8168,18 +8175,45 @@ namespace { template <typename T> bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { - if (Node == NULL) + if (!Node) return true; - if (ParentStack.size() > 0) - // FIXME: Currently we add the same parent multiple times, for example - // when we visit all subexpressions of template instantiations; this is - // suboptimal, bug benign: the only way to visit those is with - // hasAncestor / hasParent, and those do not create new matches. + if (ParentStack.size() > 0) { + // FIXME: Currently we add the same parent multiple times, but only + // when no memoization data is available for the type. + // For example when we visit all subexpressions of template + // instantiations; this is suboptimal, but benign: the only way to + // visit those is with hasAncestor / hasParent, and those do not create + // new matches. // The plan is to enable DynTypedNode to be storable in a map or hash // map. The main problem there is to implement hash functions / // comparison operators for all types that DynTypedNode supports that // do not have pointer identity. - (*Parents)[Node].push_back(ParentStack.back()); + auto &NodeOrVector = (*Parents)[Node]; + if (NodeOrVector.isNull()) { + NodeOrVector = new ast_type_traits::DynTypedNode(ParentStack.back()); + } else { + if (NodeOrVector.template is<ast_type_traits::DynTypedNode *>()) { + auto *Node = + NodeOrVector.template get<ast_type_traits::DynTypedNode *>(); + auto *Vector = new ASTContext::ParentVector(1, *Node); + NodeOrVector = Vector; + delete Node; + } + assert(NodeOrVector.template is<ASTContext::ParentVector *>()); + + auto *Vector = + NodeOrVector.template get<ASTContext::ParentVector *>(); + // Skip duplicates for types that have memoization data. + // We must check that the type has memoization data before calling + // std::find() because DynTypedNode::operator== can't compare all + // types. + bool Found = ParentStack.back().getMemoizationData() && + std::find(Vector->begin(), Vector->end(), + ParentStack.back()) != Vector->end(); + if (!Found) + Vector->push_back(ParentStack.back()); + } + } ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); bool Result = (this ->* traverse) (Node); ParentStack.pop_back(); @@ -8217,7 +8251,11 @@ ASTContext::getParents(const ast_type_traits::DynTypedNode &Node) { if (I == AllParents->end()) { return ParentVector(); } - return I->second; + if (I->second.is<ast_type_traits::DynTypedNode *>()) { + return ParentVector(1, *I->second.get<ast_type_traits::DynTypedNode *>()); + } + const auto &Parents = *I->second.get<ParentVector *>(); + return ParentVector(Parents.begin(), Parents.end()); } bool @@ -8230,8 +8268,7 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, if (MethodDecl->getObjCDeclQualifier() != MethodImpl->getObjCDeclQualifier()) return false; - if (!hasSameType(MethodDecl->getResultType(), - MethodImpl->getResultType())) + if (!hasSameType(MethodDecl->getReturnType(), MethodImpl->getReturnType())) return false; if (MethodDecl->param_size() != MethodImpl->param_size()) @@ -8251,3 +8288,12 @@ ASTContext::ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, return (MethodDecl->isVariadic() == MethodImpl->isVariadic()); } + +// Explicitly instantiate this in case a Redeclarable<T> is used from a TU that +// doesn't include ASTContext.h +template +clang::LazyGenerationalUpdatePtr< + const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::ValueType +clang::LazyGenerationalUpdatePtr< + const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue( + const clang::ASTContext &Ctx, Decl *Value); diff --git a/lib/AST/ASTDiagnostic.cpp b/lib/AST/ASTDiagnostic.cpp index fce8f64b3328..8c8b1dff0cbf 100644 --- a/lib/AST/ASTDiagnostic.cpp +++ b/lib/AST/ASTDiagnostic.cpp @@ -12,6 +12,8 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" +#include "clang/AST/Attr.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/ExprCXX.h" @@ -51,6 +53,11 @@ static QualType Desugar(ASTContext &Context, QualType QT, bool &ShouldAKA) { QT = AT->desugar(); continue; } + // ...or an adjusted type... + if (const AdjustedType *AT = dyn_cast<AdjustedType>(Ty)) { + QT = AT->desugar(); + continue; + } // ... or an auto type. if (const AutoType *AT = dyn_cast<AutoType>(Ty)) { if (!AT->isSugared()) @@ -155,9 +162,8 @@ break; \ /// diagnostic message static std::string ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, - const DiagnosticsEngine::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, - ArrayRef<intptr_t> QualTypeVals) { + ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, + ArrayRef<intptr_t> QualTypeVals) { // FIXME: Playing with std::string is really slow. bool ForceAKA = false; QualType CanTy = Ty.getCanonicalType(); @@ -195,7 +201,7 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, // Check to see if we already desugared this type in this // diagnostic. If so, don't do it again. bool Repeated = false; - for (unsigned i = 0; i != NumPrevArgs; ++i) { + for (unsigned i = 0, e = PrevArgs.size(); i != e; ++i) { // TODO: Handle ak_declcontext case. if (PrevArgs[i].first == DiagnosticsEngine::ak_qualtype) { void *Ptr = (void*)PrevArgs[i].second; @@ -222,6 +228,20 @@ ConvertTypeToDiagnosticString(ASTContext &Context, QualType Ty, return S; } } + + // Give some additional info on vector types. These are either not desugared + // or displaying complex __attribute__ expressions so add details of the + // type and element count. + if (Ty->isVectorType()) { + const VectorType *VTy = Ty->getAs<VectorType>(); + std::string DecoratedString; + llvm::raw_string_ostream OS(DecoratedString); + const char *Values = VTy->getNumElements() > 1 ? "values" : "value"; + OS << "'" << S << "' (vector of " << VTy->getNumElements() << " '" + << VTy->getElementType().getAsString(Context.getPrintingPolicy()) + << "' " << Values << ")"; + return OS.str(); + } } S = "'" + S + "'"; @@ -236,12 +256,9 @@ static bool FormatTemplateTypeDiff(ASTContext &Context, QualType FromType, void clang::FormatASTNodeDiagnosticArgument( DiagnosticsEngine::ArgumentKind Kind, intptr_t Val, - const char *Modifier, - unsigned ModLen, - const char *Argument, - unsigned ArgLen, - const DiagnosticsEngine::ArgumentValue *PrevArgs, - unsigned NumPrevArgs, + StringRef Modifier, + StringRef Argument, + ArrayRef<DiagnosticsEngine::ArgumentValue> PrevArgs, SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals) { @@ -276,28 +293,26 @@ void clang::FormatASTNodeDiagnosticArgument( // Attempting to do a template diff on non-templates. Set the variables // and continue with regular type printing of the appropriate type. Val = TDT.PrintFromType ? TDT.FromType : TDT.ToType; - ModLen = 0; - ArgLen = 0; + Modifier = StringRef(); + Argument = StringRef(); // Fall through } case DiagnosticsEngine::ak_qualtype: { - assert(ModLen == 0 && ArgLen == 0 && + assert(Modifier.empty() && Argument.empty() && "Invalid modifier for QualType argument"); QualType Ty(QualType::getFromOpaquePtr(reinterpret_cast<void*>(Val))); - OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, NumPrevArgs, - QualTypeVals); + OS << ConvertTypeToDiagnosticString(Context, Ty, PrevArgs, QualTypeVals); NeedQuotes = false; break; } case DiagnosticsEngine::ak_declarationname: { - if (ModLen == 9 && !memcmp(Modifier, "objcclass", 9) && ArgLen == 0) + if (Modifier == "objcclass" && Argument.empty()) OS << '+'; - else if (ModLen == 12 && !memcmp(Modifier, "objcinstance", 12) - && ArgLen==0) + else if (Modifier == "objcinstance" && Argument.empty()) OS << '-'; else - assert(ModLen == 0 && ArgLen == 0 && + assert(Modifier.empty() && Argument.empty() && "Invalid modifier for DeclarationName argument"); OS << DeclarationName::getFromOpaqueInteger(Val); @@ -305,10 +320,10 @@ void clang::FormatASTNodeDiagnosticArgument( } case DiagnosticsEngine::ak_nameddecl: { bool Qualified; - if (ModLen == 1 && Modifier[0] == 'q' && ArgLen == 0) + if (Modifier == "q" && Argument.empty()) Qualified = true; else { - assert(ModLen == 0 && ArgLen == 0 && + assert(Modifier.empty() && Argument.empty() && "Invalid modifier for NamedDecl* argument"); Qualified = false; } @@ -325,7 +340,8 @@ void clang::FormatASTNodeDiagnosticArgument( case DiagnosticsEngine::ak_declcontext: { DeclContext *DC = reinterpret_cast<DeclContext *> (Val); assert(DC && "Should never have a null declaration context"); - + NeedQuotes = false; + if (DC->isTranslationUnit()) { // FIXME: Get these strings from some localized place if (Context.getLangOpts().CPlusPlus) @@ -335,10 +351,17 @@ void clang::FormatASTNodeDiagnosticArgument( } else if (TypeDecl *Type = dyn_cast<TypeDecl>(DC)) { OS << ConvertTypeToDiagnosticString(Context, Context.getTypeDeclType(Type), - PrevArgs, NumPrevArgs, - QualTypeVals); + PrevArgs, QualTypeVals); } else { // FIXME: Get these strings from some localized place + if (isa<BlockDecl>(DC)) { + OS << "block literal"; + break; + } + if (isLambdaCallOperator(DC)) { + OS << "lambda expression"; + break; + } NamedDecl *ND = cast<NamedDecl>(DC); if (isa<NamespaceDecl>(ND)) OS << "namespace "; @@ -351,9 +374,16 @@ void clang::FormatASTNodeDiagnosticArgument( ND->getNameForDiagnostic(OS, Context.getPrintingPolicy(), true); OS << '\''; } + break; + } + case DiagnosticsEngine::ak_attr: { + const Attr *At = reinterpret_cast<Attr *>(Val); + assert(At && "Received null Attr object!"); + OS << '\'' << At->getSpelling() << '\''; NeedQuotes = false; break; } + } OS.flush(); @@ -442,6 +472,9 @@ class TemplateDiff { /// FromExpr, ToExpr - The expression arguments. Expr *FromExpr, *ToExpr; + /// FromNullPtr, ToNullPtr - If the template argument is a nullptr + bool FromNullPtr, ToNullPtr; + /// FromTD, ToTD - The template decl for template template /// arguments or the type arguments that are templates. TemplateDecl *FromTD, *ToTD; @@ -470,10 +503,12 @@ class TemplateDiff { DiffNode(unsigned ParentNode = 0) : Kind(Invalid), NextNode(0), ChildNode(0), ParentNode(ParentNode), - FromType(), ToType(), FromExpr(0), ToExpr(0), FromTD(0), ToTD(0), - IsValidFromInt(false), IsValidToInt(false), FromValueDecl(0), - ToValueDecl(0), FromAddressOf(false), ToAddressOf(false), - FromDefault(false), ToDefault(false), Same(false) { } + FromType(), ToType(), FromExpr(nullptr), ToExpr(nullptr), + FromNullPtr(false), ToNullPtr(false), + FromTD(nullptr), ToTD(nullptr), IsValidFromInt(false), + IsValidToInt(false), FromValueDecl(nullptr), ToValueDecl(nullptr), + FromAddressOf(false), ToAddressOf(false), FromDefault(false), + ToDefault(false), Same(false) {} }; /// FlatTree - A flattened tree used to store the DiffNodes. @@ -543,6 +578,12 @@ class TemplateDiff { FlatTree[CurrentNode].Same = Same; } + /// SetNullPtr - Sets the NullPtr flags of the current node. + void SetNullPtr(bool FromNullPtr, bool ToNullPtr) { + FlatTree[CurrentNode].FromNullPtr = FromNullPtr; + FlatTree[CurrentNode].ToNullPtr = ToNullPtr; + } + /// SetDefault - Sets FromDefault and ToDefault flags of the current node. void SetDefault(bool FromDefault, bool ToDefault) { FlatTree[CurrentNode].FromDefault = FromDefault; @@ -665,6 +706,16 @@ class TemplateDiff { return FlatTree[ReadNode].NextNode != 0; } + /// FromNullPtr - Returns true if the from argument is null. + bool FromNullPtr() { + return FlatTree[ReadNode].FromNullPtr; + } + + /// ToNullPtr - Returns true if the to argument is null. + bool ToNullPtr() { + return FlatTree[ReadNode].ToNullPtr; + } + /// FromDefault - Return true if the from argument is the default. bool FromDefault() { return FlatTree[ReadNode].FromDefault; @@ -718,7 +769,7 @@ class TemplateDiff { TSTiterator(ASTContext &Context, const TemplateSpecializationType *TST) : TST(TST), DesugarTST(GetTemplateSpecializationType(Context, TST->desugar())), - Index(0), CurrentTA(0), EndTA(0) { + Index(0), CurrentTA(nullptr), EndTA(nullptr) { if (isEnd()) return; // Set to first template argument. If not a parameter pack, done. @@ -809,13 +860,13 @@ class TemplateDiff { const RecordType *RT = Ty->getAs<RecordType>(); if (!RT) - return 0; + return nullptr; const ClassTemplateSpecializationDecl *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(RT->getDecl()); if (!CTSD) - return 0; + return nullptr; Ty = Context.getTemplateSpecializationType( TemplateName(CTSD->getSpecializedTemplate()), @@ -887,9 +938,9 @@ class TemplateDiff { // Handle Expressions if (NonTypeTemplateParmDecl *DefaultNTTPD = dyn_cast<NonTypeTemplateParmDecl>(ParamND)) { - Expr *FromExpr = 0, *ToExpr = 0; + Expr *FromExpr = nullptr, *ToExpr = nullptr; llvm::APSInt FromInt, ToInt; - ValueDecl *FromValueDecl = 0, *ToValueDecl = 0; + ValueDecl *FromValueDecl = nullptr, *ToValueDecl = nullptr; unsigned ParamWidth = 128; // Safe default if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) ParamWidth = Context.getIntWidth(DefaultNTTPD->getType()); @@ -903,6 +954,10 @@ class TemplateDiff { bool HasToValueDecl = !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::Declaration; + bool FromNullPtr = !FromIter.isEnd() && + FromIter->getKind() == TemplateArgument::NullPtr; + bool ToNullPtr = + !ToIter.isEnd() && ToIter->getKind() == TemplateArgument::NullPtr; assert(((!HasFromInt && !HasToInt) || (!HasFromValueDecl && !HasToValueDecl)) && @@ -912,41 +967,54 @@ class TemplateDiff { FromInt = FromIter->getAsIntegral(); else if (HasFromValueDecl) FromValueDecl = FromIter->getAsDecl(); - else + else if (!FromNullPtr) FromExpr = GetExpr(FromIter, DefaultNTTPD); if (HasToInt) ToInt = ToIter->getAsIntegral(); else if (HasToValueDecl) ToValueDecl = ToIter->getAsDecl(); - else + else if (!ToNullPtr) ToExpr = GetExpr(ToIter, DefaultNTTPD); + bool TemplateArgumentIsPointerType = + DefaultNTTPD->getType()->isPointerType(); + if (FromExpr && TemplateArgumentIsPointerType) { + FromNullPtr = CheckForNullPtr(FromExpr); + } + if (ToExpr && TemplateArgumentIsPointerType) { + ToNullPtr = CheckForNullPtr(ToExpr); + } + if (!HasFromInt && !HasToInt && !HasFromValueDecl && !HasToValueDecl) { Tree.SetNode(FromExpr, ToExpr); Tree.SetDefault(FromIter.isEnd() && FromExpr, ToIter.isEnd() && ToExpr); if (DefaultNTTPD->getType()->isIntegralOrEnumerationType()) { if (FromExpr) - FromInt = GetInt(FromIter, FromExpr); + HasFromInt = GetInt(FromIter, FromExpr, FromInt); if (ToExpr) - ToInt = GetInt(ToIter, ToExpr); - Tree.SetNode(FromInt, ToInt, FromExpr, ToExpr); + HasToInt = GetInt(ToIter, ToExpr, ToInt); + } + if (HasFromInt && HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetKind(DiffTree::Integer); + } else if (HasFromInt || HasToInt) { + Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); + Tree.SetSame(false); + Tree.SetKind(DiffTree::Integer); } else { - Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr)); + Tree.SetSame(IsEqualExpr(Context, ParamWidth, FromExpr, ToExpr) || + (FromNullPtr && ToNullPtr)); + Tree.SetNullPtr(FromNullPtr, ToNullPtr); Tree.SetKind(DiffTree::Expression); } } else if (HasFromInt || HasToInt) { - if (!HasFromInt && FromExpr) { - FromInt = GetInt(FromIter, FromExpr); - HasFromInt = true; - } - if (!HasToInt && ToExpr) { - ToInt = GetInt(ToIter, ToExpr); - HasToInt = true; - } + if (!HasFromInt && FromExpr) + HasFromInt = GetInt(FromIter, FromExpr, FromInt); + if (!HasToInt && ToExpr) + HasToInt = GetInt(ToIter, ToExpr, ToInt); Tree.SetNode(FromInt, ToInt, HasFromInt, HasToInt); Tree.SetSame(IsSameConvertedInt(ParamWidth, FromInt, ToInt)); Tree.SetDefault(FromIter.isEnd() && HasFromInt, @@ -958,12 +1026,36 @@ class TemplateDiff { if (!HasToValueDecl && ToExpr) ToValueDecl = GetValueDecl(ToIter, ToExpr); QualType ArgumentType = DefaultNTTPD->getType(); - bool FromAddressOf = FromValueDecl && - !ArgumentType->isReferenceType() && - !FromValueDecl->getType()->isArrayType(); - bool ToAddressOf = ToValueDecl && - !ArgumentType->isReferenceType() && - !ToValueDecl->getType()->isArrayType(); + bool FromAddressOf = false; + if (FromValueDecl) { + if (FromExpr) { + if (UnaryOperator *UO = + dyn_cast<UnaryOperator>(FromExpr->IgnoreParens())) { + if (UO->getOpcode() == UO_AddrOf) + FromAddressOf = true; + } + } else { + if (!ArgumentType->isReferenceType()) { + FromAddressOf = true; + } + } + } + bool ToAddressOf = false; + if (ToValueDecl) { + if (ToExpr) { + if (UnaryOperator *UO = + dyn_cast<UnaryOperator>(ToExpr->IgnoreParens())) { + if (UO->getOpcode() == UO_AddrOf) { + ToAddressOf = true; + } + } + } else { + if (!ArgumentType->isReferenceType()) { + ToAddressOf = true; + } + } + } + Tree.SetNullPtr(FromNullPtr, ToNullPtr); Tree.SetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); Tree.SetSame(FromValueDecl && ToValueDecl && FromValueDecl->getCanonicalDecl() == @@ -984,6 +1076,7 @@ class TemplateDiff { Tree.SetSame( FromDecl && ToDecl && FromDecl->getCanonicalDecl() == ToDecl->getCanonicalDecl()); + Tree.SetDefault(FromIter.isEnd() && FromDecl, ToIter.isEnd() && ToDecl); Tree.SetKind(DiffTree::TemplateTemplate); } @@ -1072,7 +1165,7 @@ class TemplateDiff { /// GetExpr - Retrieves the template expression argument, including default /// arguments. Expr *GetExpr(const TSTiterator &Iter, NonTypeTemplateParmDecl *DefaultNTTPD) { - Expr *ArgExpr = 0; + Expr *ArgExpr = nullptr; bool isVariadic = DefaultNTTPD->isParameterPack(); if (!Iter.isEnd()) @@ -1090,20 +1183,28 @@ class TemplateDiff { /// GetInt - Retrieves the template integer argument, including evaluating /// default arguments. - llvm::APInt GetInt(const TSTiterator &Iter, Expr *ArgExpr) { + bool GetInt(const TSTiterator &Iter, Expr *ArgExpr, llvm::APInt &Int) { // Default, value-depenedent expressions require fetching - // from the desugared TemplateArgument - if (Iter.isEnd() && ArgExpr->isValueDependent()) + // from the desugared TemplateArgument, otherwise expression needs to + // be evaluatable. + if (Iter.isEnd() && ArgExpr->isValueDependent()) { switch (Iter.getDesugar().getKind()) { case TemplateArgument::Integral: - return Iter.getDesugar().getAsIntegral(); + Int = Iter.getDesugar().getAsIntegral(); + return true; case TemplateArgument::Expression: ArgExpr = Iter.getDesugar().getAsExpr(); - return ArgExpr->EvaluateKnownConstInt(Context); + Int = ArgExpr->EvaluateKnownConstInt(Context); + return true; default: - assert(0 && "Unexpected template argument kind"); + llvm_unreachable("Unexpected template argument kind"); } - return ArgExpr->EvaluateKnownConstInt(Context); + } else if (ArgExpr->isEvaluatable(Context)) { + Int = ArgExpr->EvaluateKnownConstInt(Context); + return true; + } + + return false; } /// GetValueDecl - Retrieves the template Decl argument, including @@ -1119,16 +1220,40 @@ class TemplateDiff { ArgExpr = Iter.getDesugar().getAsExpr(); return cast<DeclRefExpr>(ArgExpr)->getDecl(); default: - assert(0 && "Unexpected template argument kind"); + llvm_unreachable("Unexpected template argument kind"); } DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ArgExpr); if (!DRE) { - DRE = cast<DeclRefExpr>(cast<UnaryOperator>(ArgExpr)->getSubExpr()); + UnaryOperator *UO = dyn_cast<UnaryOperator>(ArgExpr->IgnoreParens()); + if (!UO) + return nullptr; + DRE = cast<DeclRefExpr>(UO->getSubExpr()); } return DRE->getDecl(); } + /// CheckForNullPtr - returns true if the expression can be evaluated as + /// a null pointer + bool CheckForNullPtr(Expr *E) { + assert(E && "Expected expression"); + + E = E->IgnoreParenCasts(); + if (E->isNullPointerConstant(Context, Expr::NPC_ValueDependentIsNull)) + return true; + + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E); + if (!DRE) + return false; + + VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl()); + if (!VD || !VD->hasInit()) + return false; + + return VD->getInit()->IgnoreParenCasts()->isNullPointerConstant( + Context, Expr::NPC_ValueDependentIsNull); + } + /// GetTemplateDecl - Retrieves the template template arguments, including /// default arguments. TemplateDecl *GetTemplateDecl(const TSTiterator &Iter, @@ -1136,7 +1261,7 @@ class TemplateDiff { bool isVariadic = DefaultTTPD->isParameterPack(); TemplateArgument TA = DefaultTTPD->getDefaultArgument().getArgument(); - TemplateDecl *DefaultTD = 0; + TemplateDecl *DefaultTD = nullptr; if (TA.getKind() != TemplateArgument::Null) DefaultTD = TA.getAsTemplate().getAsTemplateDecl(); @@ -1145,7 +1270,7 @@ class TemplateDiff { if (!isVariadic) return DefaultTD; - return 0; + return nullptr; } /// IsSameConvertedInt - Returns true if both integers are equal when @@ -1166,11 +1291,8 @@ class TemplateDiff { if (!FromExpr || !ToExpr) return false; - FromExpr = FromExpr->IgnoreParens(); - ToExpr = ToExpr->IgnoreParens(); - - DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr), - *ToDRE = dyn_cast<DeclRefExpr>(ToExpr); + DeclRefExpr *FromDRE = dyn_cast<DeclRefExpr>(FromExpr->IgnoreParens()), + *ToDRE = dyn_cast<DeclRefExpr>(ToExpr->IgnoreParens()); if (FromDRE || ToDRE) { if (!FromDRE || !ToDRE) @@ -1180,8 +1302,12 @@ class TemplateDiff { Expr::EvalResult FromResult, ToResult; if (!FromExpr->EvaluateAsRValue(FromResult, Context) || - !ToExpr->EvaluateAsRValue(ToResult, Context)) - return false; + !ToExpr->EvaluateAsRValue(ToResult, Context)) { + llvm::FoldingSetNodeID FromID, ToID; + FromExpr->Profile(FromID, Context, true); + ToExpr->Profile(ToID, Context, true); + return FromID == ToID; + } APValue &FromVal = FromResult.Val; APValue &ToVal = ToResult.Val; @@ -1235,8 +1361,8 @@ class TemplateDiff { case DiffTree::Expression: { Expr *FromExpr, *ToExpr; Tree.GetNode(FromExpr, ToExpr); - PrintExpr(FromExpr, ToExpr, Tree.FromDefault(), Tree.ToDefault(), - Tree.NodeIsSame()); + PrintExpr(FromExpr, ToExpr, Tree.FromNullPtr(), Tree.ToNullPtr(), + Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::TemplateTemplate: { @@ -1262,7 +1388,8 @@ class TemplateDiff { bool FromAddressOf, ToAddressOf; Tree.GetNode(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf); PrintValueDecl(FromValueDecl, ToValueDecl, FromAddressOf, ToAddressOf, - Tree.FromDefault(), Tree.ToDefault(), Tree.NodeIsSame()); + Tree.FromNullPtr(), Tree.ToNullPtr(), Tree.FromDefault(), + Tree.ToDefault(), Tree.NodeIsSame()); return; } case DiffTree::Template: { @@ -1341,7 +1468,7 @@ class TemplateDiff { "Only one template argument may be missing."); if (Same) { - OS << FromType.getAsString(); + OS << FromType.getAsString(Policy); return; } @@ -1349,22 +1476,22 @@ class TemplateDiff { FromType.getLocalUnqualifiedType() == ToType.getLocalUnqualifiedType()) { Qualifiers FromQual = FromType.getLocalQualifiers(), - ToQual = ToType.getLocalQualifiers(), - CommonQual; + ToQual = ToType.getLocalQualifiers(); PrintQualifiers(FromQual, ToQual); FromType.getLocalUnqualifiedType().print(OS, Policy); return; } std::string FromTypeStr = FromType.isNull() ? "(no argument)" - : FromType.getAsString(); + : FromType.getAsString(Policy); std::string ToTypeStr = ToType.isNull() ? "(no argument)" - : ToType.getAsString(); + : ToType.getAsString(Policy); // Switch to canonical typename if it is better. // TODO: merge this with other aka printing above. if (FromTypeStr == ToTypeStr) { - std::string FromCanTypeStr = FromType.getCanonicalType().getAsString(); - std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(); + std::string FromCanTypeStr = + FromType.getCanonicalType().getAsString(Policy); + std::string ToCanTypeStr = ToType.getCanonicalType().getAsString(Policy); if (FromCanTypeStr != ToCanTypeStr) { FromTypeStr = FromCanTypeStr; ToTypeStr = ToCanTypeStr; @@ -1388,36 +1515,41 @@ class TemplateDiff { /// PrintExpr - Prints out the expr template arguments, highlighting argument /// differences. - void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, - bool FromDefault, bool ToDefault, bool Same) { + void PrintExpr(const Expr *FromExpr, const Expr *ToExpr, bool FromNullPtr, + bool ToNullPtr, bool FromDefault, bool ToDefault, bool Same) { assert((FromExpr || ToExpr) && "Only one template argument may be missing."); if (Same) { - PrintExpr(FromExpr); + PrintExpr(FromExpr, FromNullPtr); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); - PrintExpr(FromExpr); + PrintExpr(FromExpr, FromNullPtr); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - PrintExpr(FromExpr); + PrintExpr(FromExpr, FromNullPtr); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - PrintExpr(ToExpr); + PrintExpr(ToExpr, ToNullPtr); Unbold(); OS << ']'; } } /// PrintExpr - Actual formatting and printing of expressions. - void PrintExpr(const Expr *E) { - if (!E) - OS << "(no argument)"; - else - E->printPretty(OS, 0, Policy); return; + void PrintExpr(const Expr *E, bool NullPtr = false) { + if (E) { + E->printPretty(OS, nullptr, Policy); + return; + } + if (NullPtr) { + OS << "nullptr"; + return; + } + OS << "(no argument)"; } /// PrintTemplateTemplate - Handles printing of template template arguments, @@ -1487,6 +1619,8 @@ class TemplateDiff { Bold(); } OS << Val.toString(10); + } else if (E) { + PrintExpr(E); } else { OS << "(no argument)"; } @@ -1507,35 +1641,46 @@ class TemplateDiff { return true; } + void PrintValueDecl(ValueDecl *VD, bool AddressOf, bool NullPtr) { + if (VD) { + if (AddressOf) + OS << "&"; + OS << VD->getName(); + return; + } + + if (NullPtr) { + OS << "nullptr"; + return; + } + + OS << "(no argument)"; + } + /// PrintDecl - Handles printing of Decl arguments, highlighting /// argument differences. void PrintValueDecl(ValueDecl *FromValueDecl, ValueDecl *ToValueDecl, - bool FromAddressOf, bool ToAddressOf, bool FromDefault, - bool ToDefault, bool Same) { - assert((FromValueDecl || ToValueDecl) && + bool FromAddressOf, bool ToAddressOf, bool FromNullPtr, + bool ToNullPtr, bool FromDefault, bool ToDefault, + bool Same) { + assert((FromValueDecl || FromNullPtr || ToValueDecl || ToNullPtr) && "Only one Decl argument may be NULL"); if (Same) { - OS << FromValueDecl->getName(); + PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); } else if (!PrintTree) { OS << (FromDefault ? "(default) " : ""); Bold(); - if (FromAddressOf) - OS << "&"; - OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); + PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); Unbold(); } else { OS << (FromDefault ? "[(default) " : "["); Bold(); - if (FromAddressOf) - OS << "&"; - OS << (FromValueDecl ? FromValueDecl->getName() : "(no argument)"); + PrintValueDecl(FromValueDecl, FromAddressOf, FromNullPtr); Unbold(); OS << " != " << (ToDefault ? "(default) " : ""); Bold(); - if (ToAddressOf) - OS << "&"; - OS << (ToValueDecl ? ToValueDecl->getName() : "(no argument)"); + PrintValueDecl(ToValueDecl, ToAddressOf, ToNullPtr); Unbold(); OS << ']'; } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 670fd0ed3a93..df7a2cb4712b 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -149,11 +149,43 @@ namespace { } }; + class ChildDumper { + ASTDumper &Dumper; + + const Decl *Prev; + bool PrevRef; + public: + ChildDumper(ASTDumper &Dumper) : Dumper(Dumper), Prev(nullptr) {} + ~ChildDumper() { + if (Prev) { + Dumper.lastChild(); + dump(nullptr); + } + } + + // FIXME: This should take an arbitrary callable as the dumping action. + void dump(const Decl *D, bool Ref = false) { + if (Prev) { + if (PrevRef) + Dumper.dumpDeclRef(Prev); + else + Dumper.dumpDecl(Prev); + } + Prev = D; + PrevRef = Ref; + } + void dumpRef(const Decl *D) { dump(D, true); } + + // Give up ownership of the children of the node. By calling this, + // the caller takes back responsibility for calling lastChild(). + void release() { dump(nullptr); } + }; + public: ASTDumper(raw_ostream &OS, const CommandTraits *Traits, const SourceManager *SM) : OS(OS), Traits(Traits), SM(SM), IsFirstLine(true), MoreChildren(false), - LastLocFilename(""), LastLocLine(~0U), FC(0), + LastLocFilename(""), LastLocLine(~0U), FC(nullptr), ShowColors(SM && SM->getDiagnostics().getShowColors()) { } ASTDumper(raw_ostream &OS, const CommandTraits *Traits, @@ -184,7 +216,7 @@ namespace { void dumpBareType(QualType T); void dumpType(QualType T); void dumpBareDeclRef(const Decl *Node); - void dumpDeclRef(const Decl *Node, const char *Label = 0); + void dumpDeclRef(const Decl *Node, const char *Label = nullptr); void dumpName(const NamedDecl *D); bool hasNodes(const DeclContext *DC); void dumpDeclContext(const DeclContext *DC); @@ -222,6 +254,13 @@ namespace { void VisitTypeAliasTemplateDecl(const TypeAliasTemplateDecl *D); void VisitCXXRecordDecl(const CXXRecordDecl *D); void VisitStaticAssertDecl(const StaticAssertDecl *D); + template<typename SpecializationDecl> + void VisitTemplateDeclSpecialization(ChildDumper &Children, + const SpecializationDecl *D, + bool DumpExplicitInst, + bool DumpRefOnly); + template<typename TemplateDecl> + void VisitTemplateDecl(const TemplateDecl *D, bool DumpExplicitInst); void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D); void VisitClassTemplateDecl(const ClassTemplateDecl *D); void VisitClassTemplateSpecializationDecl( @@ -276,6 +315,7 @@ namespace { void VisitIntegerLiteral(const IntegerLiteral *Node); void VisitFloatingLiteral(const FloatingLiteral *Node); void VisitStringLiteral(const StringLiteral *Str); + void VisitInitListExpr(const InitListExpr *ILE); void VisitUnaryOperator(const UnaryOperator *Node); void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Node); void VisitMemberExpr(const MemberExpr *Node); @@ -405,6 +445,9 @@ void ASTDumper::dumpPointer(const void *Ptr) { } void ASTDumper::dumpLocation(SourceLocation Loc) { + if (!SM) + return; + ColorScope Color(*this, LocationColor); SourceLocation SpellingLoc = SM->getSpellingLoc(Loc); @@ -511,17 +554,14 @@ bool ASTDumper::hasNodes(const DeclContext *DC) { void ASTDumper::dumpDeclContext(const DeclContext *DC) { if (!DC) return; - bool HasUndeserializedDecls = DC->hasExternalLexicalStorage(); - for (DeclContext::decl_iterator I = DC->noload_decls_begin(), - E = DC->noload_decls_end(); - I != E; ++I) { - DeclContext::decl_iterator Next = I; - ++Next; - if (Next == E && !HasUndeserializedDecls) - lastChild(); - dumpDecl(*I); - } - if (HasUndeserializedDecls) { + + ChildDumper Children(*this); + for (auto *D : DC->noload_decls()) + Children.dump(D); + + if (DC->hasExternalLexicalStorage()) { + Children.release(); + lastChild(); IndentScope Indent(*this); ColorScope Color(*this, UndeserializedColor); @@ -580,6 +620,7 @@ void ASTDumper::dumpAttr(const Attr *A) { IndentScope Indent(*this); { ColorScope Color(*this, AttrColor); + switch (A->getKind()) { #define ATTR(X) case attr::X: OS << #X; break; #include "clang/Basic/AttrList.inc" @@ -589,6 +630,10 @@ void ASTDumper::dumpAttr(const Attr *A) { } dumpPointer(A); dumpSourceRange(A->getRange()); + if (A->isInherited()) + OS << " Inherited"; + if (A->isImplicit()) + OS << " Implicit"; #include "clang/AST/AttrDump.inc" } @@ -753,13 +798,23 @@ void ASTDumper::dumpDecl(const Decl *D) { OS << " parent " << cast<Decl>(D->getDeclContext()); dumpPreviousDecl(OS, D); dumpSourceRange(D->getSourceRange()); + OS << ' '; + dumpLocation(D->getLocation()); if (Module *M = D->getOwningModule()) OS << " in " << M->getFullModuleName(); if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) if (ND->isHidden()) OS << " hidden"; + if (D->isImplicit()) + OS << " implicit"; + if (D->isUsed()) + OS << " used"; + else if (D->isReferenced()) + OS << " referenced"; + if (D->isInvalidDecl()) + OS << " invalid"; - bool HasAttrs = D->attr_begin() != D->attr_end(); + bool HasAttrs = D->hasAttrs(); const FullComment *Comment = D->getASTContext().getLocalCommentForDeclUncached(D); // Decls within functions are visited by the body @@ -781,9 +836,6 @@ void ASTDumper::dumpDecl(const Decl *D) { lastChild(); dumpFullComment(Comment); - if (D->isInvalidDecl()) - OS << " invalid"; - setMoreChildren(false); if (HasDeclContext) dumpDeclContext(cast<DeclContext>(D)); @@ -835,13 +887,10 @@ void ASTDumper::VisitEnumConstantDecl(const EnumConstantDecl *D) { void ASTDumper::VisitIndirectFieldDecl(const IndirectFieldDecl *D) { dumpName(D); dumpType(D->getType()); - for (IndirectFieldDecl::chain_iterator I = D->chain_begin(), - E = D->chain_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpDeclRef(*I); - } + + ChildDumper Children(*this); + for (auto *Child : D->chain()) + Children.dumpRef(Child); } void ASTDumper::VisitFunctionDecl(const FunctionDecl *D) { @@ -975,6 +1024,11 @@ void ASTDumper::VisitVarDecl(const VarDecl *D) { if (D->isNRVOVariable()) OS << " nrvo"; if (D->hasInit()) { + switch (D->getInitStyle()) { + case VarDecl::CInit: OS << " cinit"; break; + case VarDecl::CallInit: OS << " callinit"; break; + case VarDecl::ListInit: OS << " listinit"; break; + } lastChild(); dumpStmt(D->getInit()); } @@ -1027,15 +1081,13 @@ void ASTDumper::VisitCXXRecordDecl(const CXXRecordDecl *D) { if (!D->isCompleteDefinition()) return; - for (CXXRecordDecl::base_class_const_iterator I = D->bases_begin(), - E = D->bases_end(); - I != E; ++I) { + for (const auto &I : D->bases()) { IndentScope Indent(*this); - if (I->isVirtual()) + if (I.isVirtual()) OS << "virtual "; - dumpAccessSpecifier(I->getAccessSpecifier()); - dumpType(I->getType()); - if (I->isPackExpansion()) + dumpAccessSpecifier(I.getAccessSpecifier()); + dumpType(I.getType()); + if (I.isPackExpansion()) OS << "..."; } } @@ -1046,63 +1098,69 @@ void ASTDumper::VisitStaticAssertDecl(const StaticAssertDecl *D) { dumpStmt(D->getMessage()); } -void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { - dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); - dumpDecl(D->getTemplatedDecl()); - for (FunctionTemplateDecl::spec_iterator I = D->spec_begin(), - E = D->spec_end(); - I != E; ++I) { - FunctionTemplateDecl::spec_iterator Next = I; - ++Next; - if (Next == E) - lastChild(); - switch (I->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: +template<typename SpecializationDecl> +void ASTDumper::VisitTemplateDeclSpecialization(ChildDumper &Children, + const SpecializationDecl *D, + bool DumpExplicitInst, + bool DumpRefOnly) { + bool DumpedAny = false; + for (auto *RedeclWithBadType : D->redecls()) { + // FIXME: The redecls() range sometimes has elements of a less-specific + // type. (In particular, ClassTemplateSpecializationDecl::redecls() gives + // us TagDecls, and should give CXXRecordDecls). + auto *Redecl = dyn_cast<SpecializationDecl>(RedeclWithBadType); + if (!Redecl) { + // Found the injected-class-name for a class template. This will be dumped + // as part of its surrounding class so we don't need to dump it here. + assert(isa<CXXRecordDecl>(RedeclWithBadType) && + "expected an injected-class-name"); + continue; + } + + switch (Redecl->getTemplateSpecializationKind()) { case TSK_ExplicitInstantiationDeclaration: case TSK_ExplicitInstantiationDefinition: - if (D == D->getCanonicalDecl()) - dumpDecl(*I); - else - dumpDeclRef(*I); + if (!DumpExplicitInst) + break; + // Fall through. + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + Children.dump(Redecl, DumpRefOnly); + DumpedAny = true; break; case TSK_ExplicitSpecialization: - dumpDeclRef(*I); break; } } + + // Ensure we dump at least one decl for each specialization. + if (!DumpedAny) + Children.dumpRef(D); } -void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { +template<typename TemplateDecl> +void ASTDumper::VisitTemplateDecl(const TemplateDecl *D, + bool DumpExplicitInst) { dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - ClassTemplateDecl::spec_iterator I = D->spec_begin(); - ClassTemplateDecl::spec_iterator E = D->spec_end(); - if (I == E) - lastChild(); - dumpDecl(D->getTemplatedDecl()); - for (; I != E; ++I) { - ClassTemplateDecl::spec_iterator Next = I; - ++Next; - if (Next == E) - lastChild(); - switch (I->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - if (D == D->getCanonicalDecl()) - dumpDecl(*I); - else - dumpDeclRef(*I); - break; - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - dumpDeclRef(*I); - break; - } - } + ChildDumper Children(*this); + Children.dump(D->getTemplatedDecl()); + + for (auto *Child : D->specializations()) + VisitTemplateDeclSpecialization(Children, Child, DumpExplicitInst, + !D->isCanonicalDecl()); +} + +void ASTDumper::VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) { + // FIXME: We don't add a declaration of a function template specialization + // to its context when it's explicitly instantiated, so dump explicit + // instantiations when we dump the template itself. + VisitTemplateDecl(D, true); +} + +void ASTDumper::VisitClassTemplateDecl(const ClassTemplateDecl *D) { + VisitTemplateDecl(D, false); } void ASTDumper::VisitClassTemplateSpecializationDecl( @@ -1125,34 +1183,7 @@ void ASTDumper::VisitClassScopeFunctionSpecializationDecl( } void ASTDumper::VisitVarTemplateDecl(const VarTemplateDecl *D) { - dumpName(D); - dumpTemplateParameters(D->getTemplateParameters()); - - VarTemplateDecl::spec_iterator I = D->spec_begin(); - VarTemplateDecl::spec_iterator E = D->spec_end(); - if (I == E) - lastChild(); - dumpDecl(D->getTemplatedDecl()); - for (; I != E; ++I) { - VarTemplateDecl::spec_iterator Next = I; - ++Next; - if (Next == E) - lastChild(); - switch (I->getTemplateSpecializationKind()) { - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - if (D == D->getCanonicalDecl()) - dumpDecl(*I); - else - dumpDeclRef(*I); - break; - case TSK_ExplicitSpecialization: - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - dumpDeclRef(*I); - break; - } - } + VisitTemplateDecl(D, false); } void ASTDumper::VisitVarTemplateSpecializationDecl( @@ -1175,8 +1206,10 @@ void ASTDumper::VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) { if (D->isParameterPack()) OS << " ..."; dumpName(D); - if (D->hasDefaultArgument()) - dumpType(D->getDefaultArgument()); + if (D->hasDefaultArgument()) { + lastChild(); + dumpTemplateArgument(D->getDefaultArgument()); + } } void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { @@ -1184,8 +1217,10 @@ void ASTDumper::VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) { if (D->isParameterPack()) OS << " ..."; dumpName(D); - if (D->hasDefaultArgument()) - dumpStmt(D->getDefaultArgument()); + if (D->hasDefaultArgument()) { + lastChild(); + dumpTemplateArgument(D->getDefaultArgument()); + } } void ASTDumper::VisitTemplateTemplateParmDecl( @@ -1194,8 +1229,10 @@ void ASTDumper::VisitTemplateTemplateParmDecl( OS << " ..."; dumpName(D); dumpTemplateParameters(D->getTemplateParameters()); - if (D->hasDefaultArgument()) + if (D->hasDefaultArgument()) { + lastChild(); dumpTemplateArgumentLoc(D->getDefaultArgument()); + } } void ASTDumper::VisitUsingDecl(const UsingDecl *D) { @@ -1252,8 +1289,6 @@ void ASTDumper::VisitObjCIvarDecl(const ObjCIvarDecl *D) { dumpType(D->getType()); if (D->getSynthesize()) OS << " synthesize"; - if (D->getBackingIvarReferencedInAccessor()) - OS << " BackingIvarReferencedInAccessor"; switch (D->getAccessControl()) { case ObjCIvarDecl::None: @@ -1280,7 +1315,7 @@ void ASTDumper::VisitObjCMethodDecl(const ObjCMethodDecl *D) { else OS << " +"; dumpName(D); - dumpType(D->getResultType()); + dumpType(D->getReturnType()); bool OldMoreChildren = hasMoreChildren(); bool IsVariadic = D->isVariadic(); @@ -1338,28 +1373,20 @@ void ASTDumper::VisitObjCCategoryImplDecl(const ObjCCategoryImplDecl *D) { void ASTDumper::VisitObjCProtocolDecl(const ObjCProtocolDecl *D) { dumpName(D); - for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), - E = D->protocol_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpDeclRef(*I); - } + + ChildDumper Children(*this); + for (auto *Child : D->protocols()) + Children.dumpRef(Child); } void ASTDumper::VisitObjCInterfaceDecl(const ObjCInterfaceDecl *D) { dumpName(D); dumpDeclRef(D->getSuperClass(), "super"); - if (D->protocol_begin() == D->protocol_end()) - lastChild(); - dumpDeclRef(D->getImplementation()); - for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(), - E = D->protocol_end(); - I != E; ++I) { - if (I + 1 == E) - lastChild(); - dumpDeclRef(*I); - } + + ChildDumper Children(*this); + Children.dumpRef(D->getImplementation()); + for (auto *Child : D->protocols()) + Children.dumpRef(Child); } void ASTDumper::VisitObjCImplementationDecl(const ObjCImplementationDecl *D) { @@ -1438,9 +1465,8 @@ void ASTDumper::VisitObjCPropertyImplDecl(const ObjCPropertyImplDecl *D) { } void ASTDumper::VisitBlockDecl(const BlockDecl *D) { - for (BlockDecl::param_const_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) - dumpDecl(*I); + for (auto I : D->params()) + dumpDecl(I); if (D->isVariadic()) { IndentScope Indent(*this); @@ -1451,20 +1477,19 @@ void ASTDumper::VisitBlockDecl(const BlockDecl *D) { IndentScope Indent(*this); OS << "capture this"; } - for (BlockDecl::capture_iterator I = D->capture_begin(), E = D->capture_end(); - I != E; ++I) { + for (const auto &I : D->captures()) { IndentScope Indent(*this); OS << "capture"; - if (I->isByRef()) + if (I.isByRef()) OS << " byref"; - if (I->isNested()) + if (I.isNested()) OS << " nested"; - if (I->getVariable()) { + if (I.getVariable()) { OS << ' '; - dumpBareDeclRef(I->getVariable()); + dumpBareDeclRef(I.getVariable()); } - if (I->hasCopyExpr()) - dumpStmt(I->getCopyExpr()); + if (I.hasCopyExpr()) + dumpStmt(I.getCopyExpr()); } lastChild(); dumpStmt(D->getBody()); @@ -1675,6 +1700,7 @@ void ASTDumper::VisitPredefinedExpr(const PredefinedExpr *Node) { case PredefinedExpr::FuncDName: OS << " __FUNCDNAME__"; break; case PredefinedExpr::LFunction: OS << " L__FUNCTION__"; break; case PredefinedExpr::PrettyFunction: OS << " __PRETTY_FUNCTION__";break; + case PredefinedExpr::FuncSig: OS << " __FUNCSIG__"; break; } } @@ -1705,6 +1731,22 @@ void ASTDumper::VisitStringLiteral(const StringLiteral *Str) { Str->outputString(OS); } +void ASTDumper::VisitInitListExpr(const InitListExpr *ILE) { + VisitExpr(ILE); + if (auto *Filler = ILE->getArrayFiller()) { + if (!ILE->getNumInits()) + lastChild(); + IndentScope Indent(*this); + OS << "array filler"; + lastChild(); + dumpStmt(Filler); + } + if (auto *Field = ILE->getInitializedFieldInUnion()) { + OS << " field "; + dumpBareDeclRef(Field); + } +} + void ASTDumper::VisitUnaryOperator(const UnaryOperator *Node) { VisitExpr(Node); OS << " " << (Node->isPostfix() ? "postfix" : "prefix") @@ -1849,7 +1891,8 @@ void ASTDumper::dumpCXXTemporary(const CXXTemporary *Temporary) { void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { VisitExpr(Node); - OS << " selector=" << Node->getSelector().getAsString(); + OS << " selector="; + Node->getSelector().print(OS); switch (Node->getReceiverKind()) { case ObjCMessageExpr::Instance: break; @@ -1871,7 +1914,8 @@ void ASTDumper::VisitObjCMessageExpr(const ObjCMessageExpr *Node) { void ASTDumper::VisitObjCBoxedExpr(const ObjCBoxedExpr *Node) { VisitExpr(Node); - OS << " selector=" << Node->getBoxingMethod()->getSelector().getAsString(); + OS << " selector="; + Node->getBoxingMethod()->getSelector().print(OS); } void ASTDumper::VisitObjCAtCatchStmt(const ObjCAtCatchStmt *Node) { @@ -1890,7 +1934,8 @@ void ASTDumper::VisitObjCEncodeExpr(const ObjCEncodeExpr *Node) { void ASTDumper::VisitObjCSelectorExpr(const ObjCSelectorExpr *Node) { VisitExpr(Node); - OS << " " << Node->getSelector().getAsString(); + OS << " "; + Node->getSelector().print(OS); } void ASTDumper::VisitObjCProtocolExpr(const ObjCProtocolExpr *Node) { @@ -1904,13 +1949,13 @@ void ASTDumper::VisitObjCPropertyRefExpr(const ObjCPropertyRefExpr *Node) { if (Node->isImplicitProperty()) { OS << " Kind=MethodRef Getter=\""; if (Node->getImplicitPropertyGetter()) - OS << Node->getImplicitPropertyGetter()->getSelector().getAsString(); + Node->getImplicitPropertyGetter()->getSelector().print(OS); else OS << "(null)"; OS << "\" Setter=\""; if (ObjCMethodDecl *Setter = Node->getImplicitPropertySetter()) - OS << Setter->getSelector().getAsString(); + Setter->getSelector().print(OS); else OS << "(null)"; OS << "\""; @@ -1937,7 +1982,7 @@ void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { else OS << " Kind=DictionarySubscript GetterForDictionary=\""; if (Node->getAtIndexMethodDecl()) - OS << Node->getAtIndexMethodDecl()->getSelector().getAsString(); + Node->getAtIndexMethodDecl()->getSelector().print(OS); else OS << "(null)"; @@ -1946,7 +1991,7 @@ void ASTDumper::VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node) { else OS << "\" SetterForDictionary=\""; if (Node->setAtIndexMethodDecl()) - OS << Node->setAtIndexMethodDecl()->getSelector().getAsString(); + Node->setAtIndexMethodDecl()->getSelector().print(OS); else OS << "(null)"; } @@ -1975,7 +2020,7 @@ void ASTDumper::dumpFullComment(const FullComment *C) { FC = C; dumpComment(C); - FC = 0; + FC = nullptr; } void ASTDumper::dumpComment(const Comment *C) { @@ -2065,7 +2110,7 @@ void ASTDumper::visitParamCommandComment(const ParamCommandComment *C) { OS << " Param=\"" << C->getParamNameAsWritten() << "\""; } - if (C->isParamIndexValid()) + if (C->isParamIndexValid() && !C->isVarArgParam()) OS << " ParamIndex=" << C->getParamIndex(); } @@ -2106,27 +2151,25 @@ void ASTDumper::visitVerbatimLineComment(const VerbatimLineComment *C) { // Decl method implementations //===----------------------------------------------------------------------===// -void Decl::dump() const { - dump(llvm::errs()); -} +LLVM_DUMP_METHOD void Decl::dump() const { dump(llvm::errs()); } -void Decl::dump(raw_ostream &OS) const { +LLVM_DUMP_METHOD void Decl::dump(raw_ostream &OS) const { ASTDumper P(OS, &getASTContext().getCommentCommandTraits(), &getASTContext().getSourceManager()); P.dumpDecl(this); } -void Decl::dumpColor() const { +LLVM_DUMP_METHOD void Decl::dumpColor() const { ASTDumper P(llvm::errs(), &getASTContext().getCommentCommandTraits(), &getASTContext().getSourceManager(), /*ShowColors*/true); P.dumpDecl(this); } -void DeclContext::dumpLookups() const { +LLVM_DUMP_METHOD void DeclContext::dumpLookups() const { dumpLookups(llvm::errs()); } -void DeclContext::dumpLookups(raw_ostream &OS) const { +LLVM_DUMP_METHOD void DeclContext::dumpLookups(raw_ostream &OS) const { const DeclContext *DC = this; while (!DC->isTranslationUnit()) DC = DC->getParent(); @@ -2139,22 +2182,22 @@ void DeclContext::dumpLookups(raw_ostream &OS) const { // Stmt method implementations //===----------------------------------------------------------------------===// -void Stmt::dump(SourceManager &SM) const { +LLVM_DUMP_METHOD void Stmt::dump(SourceManager &SM) const { dump(llvm::errs(), SM); } -void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { - ASTDumper P(OS, 0, &SM); +LLVM_DUMP_METHOD void Stmt::dump(raw_ostream &OS, SourceManager &SM) const { + ASTDumper P(OS, nullptr, &SM); P.dumpStmt(this); } -void Stmt::dump() const { - ASTDumper P(llvm::errs(), 0, 0); +LLVM_DUMP_METHOD void Stmt::dump() const { + ASTDumper P(llvm::errs(), nullptr, nullptr); P.dumpStmt(this); } -void Stmt::dumpColor() const { - ASTDumper P(llvm::errs(), 0, 0, /*ShowColors*/true); +LLVM_DUMP_METHOD void Stmt::dumpColor() const { + ASTDumper P(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); P.dumpStmt(this); } @@ -2162,11 +2205,11 @@ void Stmt::dumpColor() const { // Comment method implementations //===----------------------------------------------------------------------===// -void Comment::dump() const { - dump(llvm::errs(), 0, 0); +LLVM_DUMP_METHOD void Comment::dump() const { + dump(llvm::errs(), nullptr, nullptr); } -void Comment::dump(const ASTContext &Context) const { +LLVM_DUMP_METHOD void Comment::dump(const ASTContext &Context) const { dump(llvm::errs(), &Context.getCommentCommandTraits(), &Context.getSourceManager()); } @@ -2178,8 +2221,8 @@ void Comment::dump(raw_ostream &OS, const CommandTraits *Traits, D.dumpFullComment(FC); } -void Comment::dumpColor() const { +LLVM_DUMP_METHOD void Comment::dumpColor() const { const FullComment *FC = dyn_cast<FullComment>(this); - ASTDumper D(llvm::errs(), 0, 0, /*ShowColors*/true); + ASTDumper D(llvm::errs(), nullptr, nullptr, /*ShowColors*/true); D.dumpFullComment(FC); } diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index e16015b7c4ed..b0e0b1dc9e00 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -81,7 +81,7 @@ namespace clang { bool ImportDeclParts(NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, SourceLocation &Loc); - void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = 0); + void ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD = nullptr); void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); @@ -407,10 +407,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, return false; break; + case Type::Adjusted: case Type::Decayed: if (!IsStructurallyEquivalent(Context, - cast<DecayedType>(T1)->getPointeeType(), - cast<DecayedType>(T2)->getPointeeType())) + cast<AdjustedType>(T1)->getOriginalType(), + cast<AdjustedType>(T2)->getOriginalType())) return false; break; @@ -534,12 +535,11 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::FunctionProto: { const FunctionProtoType *Proto1 = cast<FunctionProtoType>(T1); const FunctionProtoType *Proto2 = cast<FunctionProtoType>(T2); - if (Proto1->getNumArgs() != Proto2->getNumArgs()) + if (Proto1->getNumParams() != Proto2->getNumParams()) return false; - for (unsigned I = 0, N = Proto1->getNumArgs(); I != N; ++I) { - if (!IsStructurallyEquivalent(Context, - Proto1->getArgType(I), - Proto2->getArgType(I))) + for (unsigned I = 0, N = Proto1->getNumParams(); I != N; ++I) { + if (!IsStructurallyEquivalent(Context, Proto1->getParamType(I), + Proto2->getParamType(I))) return false; } if (Proto1->isVariadic() != Proto2->isVariadic()) @@ -570,9 +570,8 @@ static bool IsStructurallyEquivalent(StructuralEquivalenceContext &Context, case Type::FunctionNoProto: { const FunctionType *Function1 = cast<FunctionType>(T1); const FunctionType *Function2 = cast<FunctionType>(T2); - if (!IsStructurallyEquivalent(Context, - Function1->getResultType(), - Function2->getResultType())) + if (!IsStructurallyEquivalent(Context, Function1->getReturnType(), + Function2->getReturnType())) return false; if (Function1->getExtInfo() != Function2->getExtInfo()) return false; @@ -931,10 +930,8 @@ static Optional<unsigned> findAnonymousStructOrUnionIndex(RecordDecl *Anon) { return None; unsigned Index = 0; - for (DeclContext::decl_iterator D = Owner->noload_decls_begin(), - DEnd = Owner->noload_decls_end(); - D != DEnd; ++D) { - FieldDecl *F = dyn_cast<FieldDecl>(*D); + for (const auto *D : Owner->noload_decls()) { + const auto *F = dyn_cast<FieldDecl>(D); if (!F || !F->isAnonymousStructOrUnion()) continue; @@ -1586,7 +1583,7 @@ QualType ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { // FIXME: What happens if we're importing a function without a prototype // into C++? Should we make it variadic? - QualType ToResultType = Importer.Import(T->getResultType()); + QualType ToResultType = Importer.Import(T->getReturnType()); if (ToResultType.isNull()) return QualType(); @@ -1595,16 +1592,14 @@ ASTNodeImporter::VisitFunctionNoProtoType(const FunctionNoProtoType *T) { } QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { - QualType ToResultType = Importer.Import(T->getResultType()); + QualType ToResultType = Importer.Import(T->getReturnType()); if (ToResultType.isNull()) return QualType(); // Import argument types SmallVector<QualType, 4> ArgTypes; - for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(), - AEnd = T->arg_type_end(); - A != AEnd; ++A) { - QualType ArgType = Importer.Import(*A); + for (const auto &A : T->param_types()) { + QualType ArgType = Importer.Import(A); if (ArgType.isNull()) return QualType(); ArgTypes.push_back(ArgType); @@ -1612,10 +1607,8 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { // Import exception types SmallVector<QualType, 4> ExceptionTypes; - for (FunctionProtoType::exception_iterator E = T->exception_begin(), - EEnd = T->exception_end(); - E != EEnd; ++E) { - QualType ExceptionType = Importer.Import(*E); + for (const auto &E : T->exceptions()) { + QualType ExceptionType = Importer.Import(E); if (ExceptionType.isNull()) return QualType(); ExceptionTypes.push_back(ExceptionType); @@ -1631,7 +1624,7 @@ QualType ASTNodeImporter::VisitFunctionProtoType(const FunctionProtoType *T) { ToEPI.RefQualifier = FromEPI.RefQualifier; ToEPI.NumExceptions = ExceptionTypes.size(); ToEPI.Exceptions = ExceptionTypes.data(); - ToEPI.ConsumedArguments = FromEPI.ConsumedArguments; + ToEPI.ConsumedParameters = FromEPI.ConsumedParameters; ToEPI.ExceptionSpecType = FromEPI.ExceptionSpecType; ToEPI.NoexceptExpr = Importer.Import(FromEPI.NoexceptExpr); ToEPI.ExceptionSpecDecl = cast_or_null<FunctionDecl>( @@ -1756,7 +1749,7 @@ QualType ASTNodeImporter::VisitTemplateSpecializationType( } QualType ASTNodeImporter::VisitElaboratedType(const ElaboratedType *T) { - NestedNameSpecifier *ToQualifier = 0; + NestedNameSpecifier *ToQualifier = nullptr; // Note: the qualifier in an ElaboratedType is optional. if (T->getQualifier()) { ToQualifier = Importer.Import(T->getQualifier()); @@ -1787,11 +1780,9 @@ QualType ASTNodeImporter::VisitObjCObjectType(const ObjCObjectType *T) { return QualType(); SmallVector<ObjCProtocolDecl *, 4> Protocols; - for (ObjCObjectType::qual_iterator P = T->qual_begin(), - PEnd = T->qual_end(); - P != PEnd; ++P) { + for (auto *P : T->quals()) { ObjCProtocolDecl *Protocol - = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(*P)); + = dyn_cast_or_null<ObjCProtocolDecl>(Importer.Import(P)); if (!Protocol) return QualType(); Protocols.push_back(Protocol); @@ -1909,11 +1900,8 @@ void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { return; } - for (DeclContext::decl_iterator From = FromDC->decls_begin(), - FromEnd = FromDC->decls_end(); - From != FromEnd; - ++From) - Importer.Import(*From); + for (auto *From : FromDC->decls()) + Importer.Import(From); } bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, @@ -1946,6 +1934,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.HasProtectedFields = FromData.HasProtectedFields; ToData.HasPublicFields = FromData.HasPublicFields; ToData.HasMutableFields = FromData.HasMutableFields; + ToData.HasVariantMembers = FromData.HasVariantMembers; ToData.HasOnlyCMembers = FromData.HasOnlyCMembers; ToData.HasInClassInitializer = FromData.HasInClassInitializer; ToData.HasUninitializedReferenceMember @@ -1986,29 +1975,25 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToData.IsLambda = FromData.IsLambda; SmallVector<CXXBaseSpecifier *, 4> Bases; - for (CXXRecordDecl::base_class_iterator - Base1 = FromCXX->bases_begin(), - FromBaseEnd = FromCXX->bases_end(); - Base1 != FromBaseEnd; - ++Base1) { - QualType T = Importer.Import(Base1->getType()); + for (const auto &Base1 : FromCXX->bases()) { + QualType T = Importer.Import(Base1.getType()); if (T.isNull()) return true; SourceLocation EllipsisLoc; - if (Base1->isPackExpansion()) - EllipsisLoc = Importer.Import(Base1->getEllipsisLoc()); + if (Base1.isPackExpansion()) + EllipsisLoc = Importer.Import(Base1.getEllipsisLoc()); // Ensure that we have a definition for the base. - ImportDefinitionIfNeeded(Base1->getType()->getAsCXXRecordDecl()); + ImportDefinitionIfNeeded(Base1.getType()->getAsCXXRecordDecl()); Bases.push_back( new (Importer.getToContext()) - CXXBaseSpecifier(Importer.Import(Base1->getSourceRange()), - Base1->isVirtual(), - Base1->isBaseOfClass(), - Base1->getAccessSpecifierAsWritten(), - Importer.Import(Base1->getTypeSourceInfo()), + CXXBaseSpecifier(Importer.Import(Base1.getSourceRange()), + Base1.isVirtual(), + Base1.isBaseOfClass(), + Base1.getAccessSpecifierAsWritten(), + Importer.Import(Base1.getTypeSourceInfo()), EllipsisLoc)); } if (!Bases.empty()) @@ -2075,8 +2060,8 @@ TemplateParameterList *ASTNodeImporter::ImportTemplateParameterList( P != PEnd; ++P) { Decl *To = Importer.Import(*P); if (!To) - return 0; - + return nullptr; + ToParams.push_back(cast<NamedDecl>(To)); } @@ -2236,7 +2221,7 @@ bool ASTNodeImporter::IsStructuralMatch(VarTemplateDecl *From, Decl *ASTNodeImporter::VisitDecl(Decl *D) { Importer.FromDiag(D->getLocation(), diag::err_unsupported_ast_node) << D->getDeclKindName(); - return 0; + return nullptr; } Decl *ASTNodeImporter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { @@ -2254,9 +2239,9 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - - NamespaceDecl *MergeWithNamespace = 0; + return nullptr; + + NamespaceDecl *MergeWithNamespace = nullptr; if (!Name) { // This is an anonymous namespace. Adopt an existing anonymous // namespace if we can. @@ -2296,7 +2281,7 @@ Decl *ASTNodeImporter::VisitNamespaceDecl(NamespaceDecl *D) { D->isInline(), Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(), - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); @@ -2322,8 +2307,8 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // If this typedef is not in block scope, determine whether we've // seen a typedef with the same name (that we can merge with) or any // other entity by that name (which name lookup could conflict with). @@ -2350,15 +2335,15 @@ Decl *ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } // Import the underlying type of this typedef; QualType T = Importer.Import(D->getUnderlyingType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); SourceLocation StartL = Importer.Import(D->getLocStart()); @@ -2396,8 +2381,8 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Figure out what enum name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; @@ -2440,7 +2425,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Create the enum declaration. EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), 0, + Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), D->isScopedUsingClassTag(), D->isFixed()); // Import the qualifier, if any. @@ -2453,12 +2438,12 @@ Decl *ASTNodeImporter::VisitEnumDecl(EnumDecl *D) { // Import the integer type. QualType ToIntegerType = Importer.Import(D->getIntegerType()); if (ToIntegerType.isNull()) - return 0; + return nullptr; D2->setIntegerType(ToIntegerType); // Import the definition if (D->isCompleteDefinition() && ImportDefinition(D, D2)) - return 0; + return nullptr; return D2; } @@ -2471,8 +2456,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -2481,8 +2466,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Figure out what structure name we're looking for. unsigned IDNS = Decl::IDNS_Tag; DeclarationName SearchName = Name; @@ -2493,7 +2478,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { IDNS |= Decl::IDNS_Ordinary; // We may already have a record of the same name; try to find and match it. - RecordDecl *AdoptDecl = 0; + RecordDecl *AdoptDecl = nullptr; if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; SmallVector<NamedDecl *, 2> FoundDecls; @@ -2538,6 +2523,21 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward // declaration rather than building a new one. + + // If one or both can be completed from external storage then try one + // last time to complete and compare them before doing this. + + if (FoundRecord->hasExternalLexicalStorage() && + !FoundRecord->isCompleteDefinition()) + FoundRecord->getASTContext().getExternalSource()->CompleteType(FoundRecord); + if (D->hasExternalLexicalStorage()) + D->getASTContext().getExternalSource()->CompleteType(D); + + if (FoundRecord->isCompleteDefinition() && + D->isCompleteDefinition() && + !IsStructuralMatch(D, FoundRecord)) + continue; + AdoptDecl = FoundRecord; continue; } else if (!SearchName) { @@ -2581,8 +2581,8 @@ Decl *ASTNodeImporter::VisitRecordDecl(RecordDecl *D) { Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) - return 0; - + return nullptr; + return D2; } @@ -2592,11 +2592,11 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; // Determine whether there are any other declarations with the same name and // in the same context. @@ -2623,14 +2623,14 @@ Decl *ASTNodeImporter::VisitEnumConstantDecl(EnumConstantDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } Expr *Init = Importer.Import(D->getInitExpr()); if (D->getInitExpr() && !Init) - return 0; - + return nullptr; + EnumConstantDecl *ToEnumerator = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc, Name.getAsIdentifierInfo(), T, @@ -2648,7 +2648,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. @@ -2694,7 +2694,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } @@ -2716,7 +2716,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { FromEPI.NoexceptExpr) { FunctionProtoType::ExtProtoInfo DefaultEPI; FromTy = Importer.getFromContext().getFunctionType( - FromFPT->getResultType(), FromFPT->getArgTypes(), DefaultEPI); + FromFPT->getReturnType(), FromFPT->getParamTypes(), DefaultEPI); usedDifferentExceptionSpec = true; } } @@ -2724,22 +2724,21 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Import the type. QualType T = Importer.Import(FromTy); if (T.isNull()) - return 0; - + return nullptr; + // Import the function parameters. SmallVector<ParmVarDecl *, 8> Parameters; - for (FunctionDecl::param_iterator P = D->param_begin(), PEnd = D->param_end(); - P != PEnd; ++P) { - ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*P)); + for (auto P : D->params()) { + ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(P)); if (!ToP) - return 0; - + return nullptr; + Parameters.push_back(ToP); } // Create the imported function. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - FunctionDecl *ToFunction = 0; + FunctionDecl *ToFunction = nullptr; if (CXXConstructorDecl *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), cast<CXXRecordDecl>(DC), @@ -2804,7 +2803,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { // Update FunctionProtoType::ExtProtoInfo. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; ToFunction->setType(T); } @@ -2838,10 +2837,8 @@ static unsigned getFieldIndex(Decl *F) { return 0; unsigned Index = 1; - for (DeclContext::decl_iterator D = Owner->noload_decls_begin(), - DEnd = Owner->noload_decls_end(); - D != DEnd; ++D) { - if (*D == F) + for (const auto *D : Owner->noload_decls()) { + if (D == F) return Index; if (isa<FieldDecl>(*D) || isa<IndirectFieldDecl>(*D)) @@ -2857,8 +2854,8 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); @@ -2878,20 +2875,20 @@ Decl *ASTNodeImporter::VisitFieldDecl(FieldDecl *D) { << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); Expr *BitWidth = Importer.Import(D->getBitWidth()); if (!BitWidth && D->getBitWidth()) - return 0; - + return nullptr; + FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), @@ -2913,7 +2910,7 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Determine whether we've already imported this field. SmallVector<NamedDecl *, 2> FoundDecls; @@ -2940,24 +2937,23 @@ Decl *ASTNodeImporter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { << Name << D->getType() << FoundField->getType(); Importer.ToDiag(FoundField->getLocation(), diag::note_odr_value_here) << FoundField->getType(); - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; NamedDecl **NamedChain = new (Importer.getToContext())NamedDecl*[D->getChainingSize()]; unsigned i = 0; - for (IndirectFieldDecl::chain_iterator PI = D->chain_begin(), - PE = D->chain_end(); PI != PE; ++PI) { - Decl* D = Importer.Import(*PI); + for (auto *PI : D->chain()) { + Decl *D = Importer.Import(PI); if (!D) - return 0; + return nullptr; NamedChain[i++] = cast<NamedDecl>(D); } @@ -2978,8 +2974,8 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Determine whether we've already imported this ivar SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); @@ -2995,27 +2991,26 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl(ObjCIvarDecl *D) { << Name << D->getType() << FoundIvar->getType(); Importer.ToDiag(FoundIvar->getLocation(), diag::note_odr_value_here) << FoundIvar->getType(); - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); Expr *BitWidth = Importer.Import(D->getBitWidth()); if (!BitWidth && D->getBitWidth()) - return 0; - + return nullptr; + ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), cast<ObjCContainerDecl>(DC), Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize(), - D->getBackingIvarReferencedInAccessor()); + BitWidth, D->getSynthesize()); ToIvar->setLexicalDeclContext(LexicalDC); Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); @@ -3029,12 +3024,12 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // Try to find a variable in our own ("to") context with the same name and // in the same context as the variable we're importing. if (D->isFileVarDecl()) { - VarDecl *MergeWithVar = 0; + VarDecl *MergeWithVar = nullptr; SmallVector<NamedDecl *, 4> ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; SmallVector<NamedDecl *, 2> FoundDecls; @@ -3063,8 +3058,8 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + FoundVar->setType(T); MergeWithVar = FoundVar; break; @@ -3115,15 +3110,15 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { ConflictingDecls.data(), ConflictingDecls.size()); if (!Name) - return 0; + return nullptr; } } // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the imported variable. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, @@ -3139,7 +3134,7 @@ Decl *ASTNodeImporter::VisitVarDecl(VarDecl *D) { // Merge the initializer. if (ImportDefinition(D, ToVar)) - return 0; + return nullptr; return ToVar; } @@ -3152,16 +3147,16 @@ Decl *ASTNodeImporter::VisitImplicitParamDecl(ImplicitParamDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); // Import the parameter's type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the imported parameter. ImplicitParamDecl *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, @@ -3178,23 +3173,23 @@ Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); // Import the parameter's type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Create the imported parameter. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), - /*FIXME: Default argument*/ 0); + /*FIXME: Default argument*/nullptr); ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); return Importer.Imported(D, ToParm); } @@ -3205,8 +3200,8 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { @@ -3215,15 +3210,15 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { continue; // Check return types. - if (!Importer.IsStructurallyEquivalent(D->getResultType(), - FoundMethod->getResultType())) { + if (!Importer.IsStructurallyEquivalent(D->getReturnType(), + FoundMethod->getReturnType())) { Importer.ToDiag(Loc, diag::err_odr_objc_method_result_type_inconsistent) - << D->isInstanceMethod() << Name - << D->getResultType() << FoundMethod->getResultType(); + << D->isInstanceMethod() << Name << D->getReturnType() + << FoundMethod->getReturnType(); Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return 0; + return nullptr; } // Check the number of parameters. @@ -3234,7 +3229,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return 0; + return nullptr; } // Check parameter types. @@ -3249,7 +3244,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { << (*P)->getType() << (*FoundP)->getType(); Importer.ToDiag((*FoundP)->getLocation(), diag::note_odr_value_here) << (*FoundP)->getType(); - return 0; + return nullptr; } } @@ -3261,7 +3256,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { Importer.ToDiag(FoundMethod->getLocation(), diag::note_odr_objc_method_here) << D->isInstanceMethod() << Name; - return 0; + return nullptr; } // FIXME: Any other bits we need to merge? @@ -3270,39 +3265,28 @@ Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { } // Import the result type. - QualType ResultTy = Importer.Import(D->getResultType()); + QualType ResultTy = Importer.Import(D->getReturnType()); if (ResultTy.isNull()) - return 0; + return nullptr; + + TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); - TypeSourceInfo *ResultTInfo = Importer.Import(D->getResultTypeSourceInfo()); - - ObjCMethodDecl *ToMethod - = ObjCMethodDecl::Create(Importer.getToContext(), - Loc, - Importer.Import(D->getLocEnd()), - Name.getObjCSelector(), - ResultTy, ResultTInfo, DC, - D->isInstanceMethod(), - D->isVariadic(), - D->isPropertyAccessor(), - D->isImplicit(), - D->isDefined(), - D->getImplementationControl(), - D->hasRelatedResultType()); + ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create( + Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), + Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(), + D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), + D->getImplementationControl(), D->hasRelatedResultType()); // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. // Import the parameters SmallVector<ParmVarDecl *, 5> ToParams; - for (ObjCMethodDecl::param_iterator FromP = D->param_begin(), - FromPEnd = D->param_end(); - FromP != FromPEnd; - ++FromP) { - ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(*FromP)); + for (auto *FromP : D->params()) { + ParmVarDecl *ToP = cast_or_null<ParmVarDecl>(Importer.Import(FromP)); if (!ToP) - return 0; - + return nullptr; + ToParams.push_back(ToP); } @@ -3327,13 +3311,13 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + ObjCInterfaceDecl *ToInterface = cast_or_null<ObjCInterfaceDecl>(Importer.Import(D->getClassInterface())); if (!ToInterface) - return 0; - + return nullptr; + // Determine if we've already encountered this category. ObjCCategoryDecl *MergeWithCategory = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); @@ -3363,7 +3347,7 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { ObjCProtocolDecl *ToProto = cast_or_null<ObjCProtocolDecl>(Importer.Import(*FromProto)); if (!ToProto) - return 0; + return nullptr; Protocols.push_back(ToProto); ProtocolLocs.push_back(Importer.Import(*FromProtoLoc)); } @@ -3385,8 +3369,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { = cast_or_null<ObjCCategoryImplDecl>( Importer.Import(D->getImplementation())); if (!Impl) - return 0; - + return nullptr; + ToCategory->setImplementation(Impl); } @@ -3441,8 +3425,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -3451,9 +3435,9 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; - ObjCProtocolDecl *MergeWithProtocol = 0; + ObjCProtocolDecl *MergeWithProtocol = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { @@ -3469,7 +3453,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, Name.getAsIdentifierInfo(), Loc, Importer.Import(D->getAtStartLoc()), - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); } @@ -3477,8 +3461,8 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { Importer.Imported(D, ToProto); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) - return 0; - + return nullptr; + return ToProto; } @@ -3558,12 +3542,8 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, // Import categories. When the categories themselves are imported, they'll // hook themselves into this interface. - for (ObjCInterfaceDecl::known_categories_iterator - Cat = From->known_categories_begin(), - CatEnd = From->known_categories_end(); - Cat != CatEnd; ++Cat) { - Importer.Import(*Cat); - } + for (auto *Cat : From->known_categories()) + Importer.Import(Cat); // If we have an @implementation, import it as well. if (From->getImplementation()) { @@ -3590,8 +3570,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -3600,10 +3580,10 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Look for an existing interface with the same name. - ObjCInterfaceDecl *MergeWithIface = 0; + ObjCInterfaceDecl *MergeWithIface = nullptr; SmallVector<NamedDecl *, 2> FoundDecls; DC->localUncachedLookup(Name, FoundDecls); for (unsigned I = 0, N = FoundDecls.size(); I != N; ++I) { @@ -3620,7 +3600,7 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), - /*PrevDecl=*/0,Loc, + /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()); ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); @@ -3628,8 +3608,8 @@ Decl *ASTNodeImporter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { Importer.Imported(D, ToIface); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToIface)) - return 0; - + return nullptr; + return ToIface; } @@ -3637,14 +3617,14 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { ObjCCategoryDecl *Category = cast_or_null<ObjCCategoryDecl>( Importer.Import(D->getCategoryDecl())); if (!Category) - return 0; - + return nullptr; + ObjCCategoryImplDecl *ToImpl = Category->getImplementation(); if (!ToImpl) { DeclContext *DC = Importer.ImportContext(D->getDeclContext()); if (!DC) - return 0; - + return nullptr; + SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, Importer.Import(D->getIdentifier()), @@ -3657,8 +3637,8 @@ Decl *ASTNodeImporter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; - + return nullptr; + ToImpl->setLexicalDeclContext(LexicalDC); } @@ -3676,15 +3656,15 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { ObjCInterfaceDecl *Iface = cast_or_null<ObjCInterfaceDecl>( Importer.Import(D->getClassInterface())); if (!Iface) - return 0; + return nullptr; // Import the superclass, if any. - ObjCInterfaceDecl *Super = 0; + ObjCInterfaceDecl *Super = nullptr; if (D->getSuperClass()) { Super = cast_or_null<ObjCInterfaceDecl>( Importer.Import(D->getSuperClass())); if (!Super) - return 0; + return nullptr; } ObjCImplementationDecl *Impl = Iface->getImplementation(); @@ -3704,7 +3684,7 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; Impl->setLexicalDeclContext(LexicalDC); } @@ -3717,28 +3697,29 @@ Decl *ASTNodeImporter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { // Verify that the existing @implementation has the same superclass. if ((Super && !Impl->getSuperClass()) || (!Super && Impl->getSuperClass()) || - (Super && Impl->getSuperClass() && - !declaresSameEntity(Super->getCanonicalDecl(), Impl->getSuperClass()))) { - Importer.ToDiag(Impl->getLocation(), - diag::err_odr_objc_superclass_inconsistent) - << Iface->getDeclName(); - // FIXME: It would be nice to have the location of the superclass - // below. - if (Impl->getSuperClass()) - Importer.ToDiag(Impl->getLocation(), + (Super && Impl->getSuperClass() && + !declaresSameEntity(Super->getCanonicalDecl(), + Impl->getSuperClass()))) { + Importer.ToDiag(Impl->getLocation(), + diag::err_odr_objc_superclass_inconsistent) + << Iface->getDeclName(); + // FIXME: It would be nice to have the location of the superclass + // below. + if (Impl->getSuperClass()) + Importer.ToDiag(Impl->getLocation(), + diag::note_odr_objc_superclass) + << Impl->getSuperClass()->getDeclName(); + else + Importer.ToDiag(Impl->getLocation(), + diag::note_odr_objc_missing_superclass); + if (D->getSuperClass()) + Importer.FromDiag(D->getLocation(), diag::note_odr_objc_superclass) - << Impl->getSuperClass()->getDeclName(); - else - Importer.ToDiag(Impl->getLocation(), + << D->getSuperClass()->getDeclName(); + else + Importer.FromDiag(D->getLocation(), diag::note_odr_objc_missing_superclass); - if (D->getSuperClass()) - Importer.FromDiag(D->getLocation(), - diag::note_odr_objc_superclass) - << D->getSuperClass()->getDeclName(); - else - Importer.FromDiag(D->getLocation(), - diag::note_odr_objc_missing_superclass); - return 0; + return nullptr; } } @@ -3754,7 +3735,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // Check whether we have already imported this property. SmallVector<NamedDecl *, 2> FoundDecls; @@ -3769,7 +3750,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { << Name << D->getType() << FoundProp->getType(); Importer.ToDiag(FoundProp->getLocation(), diag::note_odr_value_here) << FoundProp->getType(); - return 0; + return nullptr; } // FIXME: Check property attributes, getters, setters, etc.? @@ -3783,7 +3764,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { // Import the type. TypeSourceInfo *T = Importer.Import(D->getTypeSourceInfo()); if (!T) - return 0; + return nullptr; // Create the new property. ObjCPropertyDecl *ToProperty @@ -3815,31 +3796,31 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { ObjCPropertyDecl *Property = cast_or_null<ObjCPropertyDecl>( Importer.Import(D->getPropertyDecl())); if (!Property) - return 0; + return nullptr; DeclContext *DC = Importer.ImportContext(D->getDeclContext()); if (!DC) - return 0; - + return nullptr; + // Import the lexical declaration context. DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; } ObjCImplDecl *InImpl = dyn_cast<ObjCImplDecl>(LexicalDC); if (!InImpl) - return 0; + return nullptr; // Import the ivar (for an @synthesize). - ObjCIvarDecl *Ivar = 0; + ObjCIvarDecl *Ivar = nullptr; if (D->getPropertyIvarDecl()) { Ivar = cast_or_null<ObjCIvarDecl>( Importer.Import(D->getPropertyIvarDecl())); if (!Ivar) - return 0; + return nullptr; } ObjCPropertyImplDecl *ToImpl @@ -3868,7 +3849,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { diag::note_odr_objc_property_impl_kind) << D->getPropertyDecl()->getDeclName() << (D->getPropertyImplementation() == ObjCPropertyImplDecl::Dynamic); - return 0; + return nullptr; } // For @synthesize, check that we have the same @@ -3882,7 +3863,7 @@ Decl *ASTNodeImporter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { Importer.FromDiag(D->getPropertyIvarDeclLoc(), diag::note_odr_objc_synthesize_ivar_here) << D->getPropertyIvarDecl()->getDeclName(); - return 0; + return nullptr; } // Merge the existing implementation with the new implementation. @@ -3914,21 +3895,21 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); // Import the type of this declaration. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; - + return nullptr; + // Import type-source information. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); if (D->getTypeSourceInfo() && !TInfo) - return 0; - + return nullptr; + // FIXME: Import default argument. return NonTypeTemplateParmDecl::Create(Importer.getToContext(), @@ -3944,8 +3925,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { // Import the name of this declaration. DeclarationName Name = Importer.Import(D->getDeclName()); if (D->getDeclName() && !Name) - return 0; - + return nullptr; + // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); @@ -3953,8 +3934,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) - return 0; - + return nullptr; + // FIXME: Import default argument. return TemplateTemplateParmDecl::Create(Importer.getToContext(), @@ -3975,8 +3956,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { Decl *ImportedDef = Importer.Import(Definition->getDescribedClassTemplate()); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -3985,8 +3966,8 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; - + return nullptr; + // We may already have a template of the same name; try to find and match it. if (!DC->isFunctionOrMethod()) { SmallVector<NamedDecl *, 4> ConflictingDecls; @@ -4019,7 +4000,7 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { } if (!Name) - return 0; + return nullptr; } CXXRecordDecl *DTemplated = D->getTemplatedDecl(); @@ -4039,12 +4020,12 @@ Decl *ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) - return 0; - + return nullptr; + ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated, - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); D2Templated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); @@ -4072,8 +4053,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; - + return nullptr; + return Importer.Imported(D, ImportedDef); } @@ -4081,18 +4062,18 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( = cast_or_null<ClassTemplateDecl>(Importer.Import( D->getSpecializedTemplate())); if (!ClassTemplate) - return 0; - + return nullptr; + // Import the context of this declaration. DeclContext *DC = ClassTemplate->getDeclContext(); if (!DC) - return 0; - + return nullptr; + DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; } // Import the location of this declaration. @@ -4104,13 +4085,12 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( if (ImportTemplateArguments(D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) - return 0; - + return nullptr; + // Try to find an existing specialization with these template arguments. - void *InsertPos = 0; + void *InsertPos = nullptr; ClassTemplateSpecializationDecl *D2 - = ClassTemplate->findSpecialization(TemplateArgs.data(), - TemplateArgs.size(), InsertPos); + = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); if (D2) { // We already have a class template specialization with these template // arguments. @@ -4133,7 +4113,7 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( ClassTemplate, TemplateArgs.data(), TemplateArgs.size(), - /*PrevDecl=*/0); + /*PrevDecl=*/nullptr); D2->setSpecializationKind(D->getSpecializationKind()); // Add this specialization to the class template. @@ -4149,8 +4129,8 @@ Decl *ASTNodeImporter::VisitClassTemplateSpecializationDecl( Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2)) - return 0; - + return nullptr; + return D2; } @@ -4164,7 +4144,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { if (Definition && Definition != D->getTemplatedDecl()) { Decl *ImportedDef = Importer.Import(Definition->getDescribedVarTemplate()); if (!ImportedDef) - return 0; + return nullptr; return Importer.Imported(D, ImportedDef); } @@ -4174,7 +4154,7 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { DeclarationName Name; SourceLocation Loc; if (ImportDeclParts(D, DC, LexicalDC, Name, Loc)) - return 0; + return nullptr; // We may already have a template of the same name; try to find and match it. assert(!DC->isFunctionOrMethod() && @@ -4206,14 +4186,14 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { } if (!Name) - return 0; + return nullptr; VarDecl *DTemplated = D->getTemplatedDecl(); // Import the type. QualType T = Importer.Import(DTemplated->getType()); if (T.isNull()) - return 0; + return nullptr; // Create the declaration that is being templated. SourceLocation StartLoc = Importer.Import(DTemplated->getLocStart()); @@ -4231,17 +4211,16 @@ Decl *ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { // Merge the initializer. if (ImportDefinition(DTemplated, D2Templated)) - return 0; + return nullptr; // Create the variable template declaration itself. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) - return 0; + return nullptr; VarTemplateDecl *D2 = VarTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated, - /*PrevDecl=*/0); + Importer.getToContext(), DC, Loc, Name, TemplateParams, D2Templated); D2Templated->setDescribedVarTemplate(D2); D2->setAccess(D->getAccess()); @@ -4269,7 +4248,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( if (Definition && Definition != D) { Decl *ImportedDef = Importer.Import(Definition); if (!ImportedDef) - return 0; + return nullptr; return Importer.Imported(D, ImportedDef); } @@ -4277,18 +4256,18 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( VarTemplateDecl *VarTemplate = cast_or_null<VarTemplateDecl>( Importer.Import(D->getSpecializedTemplate())); if (!VarTemplate) - return 0; + return nullptr; // Import the context of this declaration. DeclContext *DC = VarTemplate->getDeclContext(); if (!DC) - return 0; + return nullptr; DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); if (!LexicalDC) - return 0; + return nullptr; } // Import the location of this declaration. @@ -4299,12 +4278,12 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( SmallVector<TemplateArgument, 2> TemplateArgs; if (ImportTemplateArguments(D->getTemplateArgs().data(), D->getTemplateArgs().size(), TemplateArgs)) - return 0; + return nullptr; // Try to find an existing specialization with these template arguments. - void *InsertPos = 0; + void *InsertPos = nullptr; VarTemplateSpecializationDecl *D2 = VarTemplate->findSpecialization( - TemplateArgs.data(), TemplateArgs.size(), InsertPos); + TemplateArgs, InsertPos); if (D2) { // We already have a variable template specialization with these template // arguments. @@ -4325,7 +4304,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( // Import the type. QualType T = Importer.Import(D->getType()); if (T.isNull()) - return 0; + return nullptr; TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); // Create a new specialization. @@ -4348,7 +4327,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( Importer.Imported(D, D2); if (D->isThisDeclarationADefinition() && ImportDefinition(D, D2)) - return 0; + return nullptr; return D2; } @@ -4360,7 +4339,7 @@ Decl *ASTNodeImporter::VisitVarTemplateSpecializationDecl( Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { Importer.FromDiag(S->getLocStart(), diag::err_unsupported_ast_node) << S->getStmtClassName(); - return 0; + return nullptr; } //---------------------------------------------------------------------------- @@ -4369,24 +4348,24 @@ Stmt *ASTNodeImporter::VisitStmt(Stmt *S) { Expr *ASTNodeImporter::VisitExpr(Expr *E) { Importer.FromDiag(E->getLocStart(), diag::err_unsupported_ast_node) << E->getStmtClassName(); - return 0; + return nullptr; } Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { ValueDecl *ToD = cast_or_null<ValueDecl>(Importer.Import(E->getDecl())); if (!ToD) - return 0; + return nullptr; - NamedDecl *FoundD = 0; + NamedDecl *FoundD = nullptr; if (E->getDecl() != E->getFoundDecl()) { FoundD = cast_or_null<NamedDecl>(Importer.Import(E->getFoundDecl())); if (!FoundD) - return 0; + return nullptr; } QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; DeclRefExpr *DRE = DeclRefExpr::Create(Importer.getToContext(), Importer.Import(E->getQualifierLoc()), @@ -4396,7 +4375,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Importer.Import(E->getLocation()), T, E->getValueKind(), FoundD, - /*FIXME:TemplateArgs=*/0); + /*FIXME:TemplateArgs=*/nullptr); if (E->hadMultipleCandidates()) DRE->setHadMultipleCandidates(true); return DRE; @@ -4405,7 +4384,7 @@ Expr *ASTNodeImporter::VisitDeclRefExpr(DeclRefExpr *E) { Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; return IntegerLiteral::Create(Importer.getToContext(), E->getValue(), T, @@ -4415,8 +4394,8 @@ Expr *ASTNodeImporter::VisitIntegerLiteral(IntegerLiteral *E) { Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; - + return nullptr; + return new (Importer.getToContext()) CharacterLiteral(E->getValue(), E->getKind(), T, Importer.Import(E->getLocation())); @@ -4425,8 +4404,8 @@ Expr *ASTNodeImporter::VisitCharacterLiteral(CharacterLiteral *E) { Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; - + return nullptr; + return new (Importer.getToContext()) ParenExpr(Importer.Import(E->getLParen()), Importer.Import(E->getRParen()), @@ -4436,12 +4415,12 @@ Expr *ASTNodeImporter::VisitParenExpr(ParenExpr *E) { Expr *ASTNodeImporter::VisitUnaryOperator(UnaryOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; - + return nullptr; + return new (Importer.getToContext()) UnaryOperator(SubExpr, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), @@ -4455,8 +4434,8 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( if (E->isArgumentType()) { TypeSourceInfo *TInfo = Importer.Import(E->getArgumentTypeInfo()); if (!TInfo) - return 0; - + return nullptr; + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), TInfo, ResultType, Importer.Import(E->getOperatorLoc()), @@ -4465,8 +4444,8 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( Expr *SubExpr = Importer.Import(E->getArgumentExpr()); if (!SubExpr) - return 0; - + return nullptr; + return new (Importer.getToContext()) UnaryExprOrTypeTraitExpr(E->getKind(), SubExpr, ResultType, Importer.Import(E->getOperatorLoc()), @@ -4476,16 +4455,16 @@ Expr *ASTNodeImporter::VisitUnaryExprOrTypeTraitExpr( Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; Expr *LHS = Importer.Import(E->getLHS()); if (!LHS) - return 0; - + return nullptr; + Expr *RHS = Importer.Import(E->getRHS()); if (!RHS) - return 0; - + return nullptr; + return new (Importer.getToContext()) BinaryOperator(LHS, RHS, E->getOpcode(), T, E->getValueKind(), E->getObjectKind(), @@ -4496,24 +4475,24 @@ Expr *ASTNodeImporter::VisitBinaryOperator(BinaryOperator *E) { Expr *ASTNodeImporter::VisitCompoundAssignOperator(CompoundAssignOperator *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; - + return nullptr; + QualType CompLHSType = Importer.Import(E->getComputationLHSType()); if (CompLHSType.isNull()) - return 0; - + return nullptr; + QualType CompResultType = Importer.Import(E->getComputationResultType()); if (CompResultType.isNull()) - return 0; - + return nullptr; + Expr *LHS = Importer.Import(E->getLHS()); if (!LHS) - return 0; - + return nullptr; + Expr *RHS = Importer.Import(E->getRHS()); if (!RHS) - return 0; - + return nullptr; + return new (Importer.getToContext()) CompoundAssignOperator(LHS, RHS, E->getOpcode(), T, E->getValueKind(), @@ -4533,15 +4512,15 @@ static bool ImportCastPath(CastExpr *E, CXXCastPath &Path) { Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; + return nullptr; Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; + return nullptr; CXXCastPath BasePath; if (ImportCastPath(E, BasePath)) - return 0; + return nullptr; return ImplicitCastExpr::Create(Importer.getToContext(), T, E->getCastKind(), SubExpr, &BasePath, E->getValueKind()); @@ -4550,19 +4529,19 @@ Expr *ASTNodeImporter::VisitImplicitCastExpr(ImplicitCastExpr *E) { Expr *ASTNodeImporter::VisitCStyleCastExpr(CStyleCastExpr *E) { QualType T = Importer.Import(E->getType()); if (T.isNull()) - return 0; - + return nullptr; + Expr *SubExpr = Importer.Import(E->getSubExpr()); if (!SubExpr) - return 0; + return nullptr; TypeSourceInfo *TInfo = Importer.Import(E->getTypeInfoAsWritten()); if (!TInfo && E->getTypeInfoAsWritten()) - return 0; - + return nullptr; + CXXCastPath BasePath; if (ImportCastPath(E, BasePath)) - return 0; + return nullptr; return CStyleCastExpr::Create(Importer.getToContext(), T, E->getValueKind(), E->getCastKind(), @@ -4616,7 +4595,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { // on the type and a single location. Implement a real version of this. QualType T = Import(FromTSI->getType()); if (T.isNull()) - return 0; + return nullptr; return ToContext.getTrivialTypeSourceInfo(T, FromTSI->getTypeLoc().getLocStart()); @@ -4624,7 +4603,7 @@ TypeSourceInfo *ASTImporter::Import(TypeSourceInfo *FromTSI) { Decl *ASTImporter::Import(Decl *FromD) { if (!FromD) - return 0; + return nullptr; ASTNodeImporter Importer(*this); @@ -4639,8 +4618,8 @@ Decl *ASTImporter::Import(Decl *FromD) { // Import the type Decl *ToD = Importer.Visit(FromD); if (!ToD) - return 0; - + return nullptr; + // Record the imported declaration. ImportedDecls[FromD] = ToD; @@ -4675,8 +4654,8 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { DeclContext *ToDC = cast_or_null<DeclContext>(Import(cast<Decl>(FromDC))); if (!ToDC) - return 0; - + return nullptr; + // When we're using a record/enum/Objective-C class/protocol as a context, we // need it to have a definition. if (RecordDecl *ToRecord = dyn_cast<RecordDecl>(ToDC)) { @@ -4726,14 +4705,14 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { Expr *ASTImporter::Import(Expr *FromE) { if (!FromE) - return 0; + return nullptr; return cast_or_null<Expr>(Import(cast<Stmt>(FromE))); } Stmt *ASTImporter::Import(Stmt *FromS) { if (!FromS) - return 0; + return nullptr; // Check whether we've already imported this declaration. llvm::DenseMap<Stmt *, Stmt *>::iterator Pos = ImportedStmts.find(FromS); @@ -4744,8 +4723,8 @@ Stmt *ASTImporter::Import(Stmt *FromS) { ASTNodeImporter Importer(*this); Stmt *ToS = Importer.Visit(FromS); if (!ToS) - return 0; - + return nullptr; + // Record the imported declaration. ImportedStmts[FromS] = ToS; return ToS; @@ -4753,7 +4732,7 @@ Stmt *ASTImporter::Import(Stmt *FromS) { NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (!FromNNS) - return 0; + return nullptr; NestedNameSpecifier *prefix = Import(FromNNS->getPrefix()); @@ -4762,21 +4741,21 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { if (IdentifierInfo *II = Import(FromNNS->getAsIdentifier())) { return NestedNameSpecifier::Create(ToContext, prefix, II); } - return 0; + return nullptr; case NestedNameSpecifier::Namespace: if (NamespaceDecl *NS = cast<NamespaceDecl>(Import(FromNNS->getAsNamespace()))) { return NestedNameSpecifier::Create(ToContext, prefix, NS); } - return 0; + return nullptr; case NestedNameSpecifier::NamespaceAlias: if (NamespaceAliasDecl *NSAD = cast<NamespaceAliasDecl>(Import(FromNNS->getAsNamespaceAlias()))) { return NestedNameSpecifier::Create(ToContext, prefix, NSAD); } - return 0; + return nullptr; case NestedNameSpecifier::Global: return NestedNameSpecifier::GlobalSpecifier(ToContext); @@ -4791,7 +4770,7 @@ NestedNameSpecifier *ASTImporter::Import(NestedNameSpecifier *FromNNS) { bTemplate, T.getTypePtr()); } } - return 0; + return nullptr; } llvm_unreachable("Invalid nested name specifier kind"); @@ -4943,8 +4922,7 @@ FileID ASTImporter::Import(FileID FromID) { llvm::MemoryBuffer *ToBuf = llvm::MemoryBuffer::getMemBufferCopy(FromBuf->getBuffer(), FromBuf->getBufferIdentifier()); - ToID = ToSM.createFileIDForMemBuffer(ToBuf, - FromSLoc.getFile().getFileCharacteristic()); + ToID = ToSM.createFileID(ToBuf, FromSLoc.getFile().getFileCharacteristic()); } @@ -5054,7 +5032,7 @@ DeclarationName ASTImporter::Import(DeclarationName FromName) { IdentifierInfo *ASTImporter::Import(const IdentifierInfo *FromId) { if (!FromId) - return 0; + return nullptr; return &ToContext.Idents.get(FromId->getName()); } diff --git a/lib/AST/ASTTypeTraits.cpp b/lib/AST/ASTTypeTraits.cpp index ae47ea98882b..baa8e48779a2 100644 --- a/lib/AST/ASTTypeTraits.cpp +++ b/lib/AST/ASTTypeTraits.cpp @@ -39,18 +39,24 @@ const ASTNodeKind::KindInfo ASTNodeKind::AllKindInfo[] = { #include "clang/AST/TypeNodes.def" }; -bool ASTNodeKind::isBaseOf(ASTNodeKind Other) const { - return isBaseOf(KindId, Other.KindId); +bool ASTNodeKind::isBaseOf(ASTNodeKind Other, unsigned *Distance) const { + return isBaseOf(KindId, Other.KindId, Distance); } bool ASTNodeKind::isSame(ASTNodeKind Other) const { return KindId != NKI_None && KindId == Other.KindId; } -bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived) { +bool ASTNodeKind::isBaseOf(NodeKindId Base, NodeKindId Derived, + unsigned *Distance) { if (Base == NKI_None || Derived == NKI_None) return false; - while (Derived != Base && Derived != NKI_None) + unsigned Dist = 0; + while (Derived != Base && Derived != NKI_None) { Derived = AllKindInfo[Derived].ParentId; + ++Dist; + } + if (Distance) + *Distance = Dist; return Derived == Base; } @@ -71,7 +77,7 @@ void DynTypedNode::print(llvm::raw_ostream &OS, else if (const Decl *D = get<Decl>()) D->print(OS, PP); else if (const Stmt *S = get<Stmt>()) - S->printPretty(OS, 0, PP); + S->printPretty(OS, nullptr, PP); else if (const Type *T = get<Type>()) QualType(T, 0).print(OS, PP); else diff --git a/lib/AST/AttrImpl.cpp b/lib/AST/AttrImpl.cpp index 7af3c8b16263..0bf6bcd9092e 100644 --- a/lib/AST/AttrImpl.cpp +++ b/lib/AST/AttrImpl.cpp @@ -24,6 +24,4 @@ void InheritableAttr::anchor() { } void InheritableParamAttr::anchor() { } -void MSInheritanceAttr::anchor() { } - #include "clang/AST/AttrImpl.inc" diff --git a/lib/AST/CMakeLists.txt b/lib/AST/CMakeLists.txt index 461e8b3ac18e..9006be64f73f 100644 --- a/lib/AST/CMakeLists.txt +++ b/lib/AST/CMakeLists.txt @@ -57,29 +57,8 @@ add_clang_library(clangAST TypePrinter.cpp VTableBuilder.cpp VTTBuilder.cpp - ) - -add_dependencies(clangAST - ClangARMNeon - ClangAttrClasses - ClangAttrList - ClangAttrImpl - ClangAttrDump - ClangCommentCommandInfo - ClangCommentCommandList - ClangCommentNodes - ClangCommentHTMLTags - ClangCommentHTMLTagsProperties - ClangCommentHTMLNamedCharacterReferences - ClangDeclNodes - ClangDiagnosticAST - ClangDiagnosticComment - ClangDiagnosticCommon - ClangDiagnosticSema - ClangStmtNodes - ) -target_link_libraries(clangAST + LINK_LIBS clangBasic clangLex ) diff --git a/lib/AST/CXXABI.h b/lib/AST/CXXABI.h index 89203f18ca77..12b929b88db0 100644 --- a/lib/AST/CXXABI.h +++ b/lib/AST/CXXABI.h @@ -44,7 +44,6 @@ public: }; /// Creates an instance of a C++ ABI class. -CXXABI *CreateARMCXXABI(ASTContext &Ctx); CXXABI *CreateItaniumCXXABI(ASTContext &Ctx); CXXABI *CreateMicrosoftCXXABI(ASTContext &Ctx); } diff --git a/lib/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp index b51014b7428f..6e80ee7c28a1 100644 --- a/lib/AST/CXXInheritance.cpp +++ b/lib/AST/CXXInheritance.cpp @@ -35,16 +35,12 @@ void CXXBasePaths::ComputeDeclsFound() { std::copy(Decls.begin(), Decls.end(), DeclsFound); } -CXXBasePaths::decl_iterator CXXBasePaths::found_decls_begin() { +CXXBasePaths::decl_range CXXBasePaths::found_decls() { if (NumDeclsFound == 0) ComputeDeclsFound(); - return DeclsFound; -} -CXXBasePaths::decl_iterator CXXBasePaths::found_decls_end() { - if (NumDeclsFound == 0) - ComputeDeclsFound(); - return DeclsFound + NumDeclsFound; + return decl_range(decl_iterator(DeclsFound), + decl_iterator(DeclsFound + NumDeclsFound)); } /// isAmbiguous - Determines whether the set of paths provided is @@ -62,7 +58,7 @@ void CXXBasePaths::clear() { Paths.clear(); ClassSubobjects.clear(); ScratchPath.clear(); - DetectedVirtual = 0; + DetectedVirtual = nullptr; } /// @brief Swaps the contents of this CXXBasePaths structure with the @@ -141,9 +137,8 @@ bool CXXRecordDecl::forallBases(ForallBasesCallback *BaseMatches, const CXXRecordDecl *Record = this; bool AllMatches = true; while (true) { - for (CXXRecordDecl::base_class_const_iterator - I = Record->bases_begin(), E = Record->bases_end(); I != E; ++I) { - const RecordType *Ty = I->getType()->getAs<RecordType>(); + for (const auto &I : Record->bases()) { + const RecordType *Ty = I.getType()->getAs<RecordType>(); if (!Ty) { if (AllowShortCircuit) return false; AllMatches = false; @@ -186,14 +181,11 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, AccessSpecifier AccessToHere = ScratchPath.Access; bool IsFirstStep = ScratchPath.empty(); - for (CXXRecordDecl::base_class_const_iterator BaseSpec = Record->bases_begin(), - BaseSpecEnd = Record->bases_end(); - BaseSpec != BaseSpecEnd; - ++BaseSpec) { + for (const auto &BaseSpec : Record->bases()) { // Find the record of the base class subobjects for this type. - QualType BaseType = Context.getCanonicalType(BaseSpec->getType()) - .getUnqualifiedType(); - + QualType BaseType = + Context.getCanonicalType(BaseSpec.getType()).getUnqualifiedType(); + // C++ [temp.dep]p3: // In the definition of a class template or a member of a class template, // if a base class of the class template depends on a template-parameter, @@ -208,10 +200,10 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, std::pair<bool, unsigned>& Subobjects = ClassSubobjects[BaseType]; bool VisitBase = true; bool SetVirtual = false; - if (BaseSpec->isVirtual()) { + if (BaseSpec.isVirtual()) { VisitBase = !Subobjects.first; Subobjects.first = true; - if (isDetectingVirtual() && DetectedVirtual == 0) { + if (isDetectingVirtual() && DetectedVirtual == nullptr) { // If this is the first virtual we find, remember it. If it turns out // there is no base path here, we'll reset it later. DetectedVirtual = BaseType->getAs<RecordType>(); @@ -223,9 +215,9 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, if (isRecordingPaths()) { // Add this base specifier to the current path. CXXBasePathElement Element; - Element.Base = &*BaseSpec; + Element.Base = &BaseSpec; Element.Class = Record; - if (BaseSpec->isVirtual()) + if (BaseSpec.isVirtual()) Element.SubobjectNumber = 0; else Element.SubobjectNumber = Subobjects.second; @@ -247,16 +239,16 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // 3. Otherwise, overall access is determined by the most restrictive // access in the sequence. if (IsFirstStep) - ScratchPath.Access = BaseSpec->getAccessSpecifier(); + ScratchPath.Access = BaseSpec.getAccessSpecifier(); else ScratchPath.Access = CXXRecordDecl::MergeAccess(AccessToHere, - BaseSpec->getAccessSpecifier()); + BaseSpec.getAccessSpecifier()); } // Track whether there's a path involving this specific base. bool FoundPathThroughBase = false; - if (BaseMatches(BaseSpec, ScratchPath, UserData)) { + if (BaseMatches(&BaseSpec, ScratchPath, UserData)) { // We've found a path that terminates at this base. FoundPath = FoundPathThroughBase = true; if (isRecordingPaths()) { @@ -269,7 +261,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, } } else if (VisitBase) { CXXRecordDecl *BaseRecord - = cast<CXXRecordDecl>(BaseSpec->getType()->castAs<RecordType>() + = cast<CXXRecordDecl>(BaseSpec.getType()->castAs<RecordType>() ->getDecl()); if (lookupInBases(Context, BaseRecord, BaseMatches, UserData)) { // C++ [class.member.lookup]p2: @@ -294,7 +286,7 @@ bool CXXBasePaths::lookupInBases(ASTContext &Context, // If we set a virtual earlier, and this isn't a path, forget it again. if (SetVirtual && !FoundPathThroughBase) { - DetectedVirtual = 0; + DetectedVirtual = nullptr; } } @@ -333,7 +325,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, for (CXXBasePath::iterator PE = P->begin(), PEEnd = P->end(); PE != PEEnd && !Hidden; ++PE) { if (PE->Base->isVirtual()) { - CXXRecordDecl *VBase = 0; + CXXRecordDecl *VBase = nullptr; if (const RecordType *Record = PE->Base->getType()->getAs<RecordType>()) VBase = cast<CXXRecordDecl>(Record->getDecl()); if (!VBase) @@ -347,7 +339,7 @@ bool CXXRecordDecl::lookupInBases(BaseMatchesCallback *BaseMatches, HidingPEnd = Paths.end(); HidingP != HidingPEnd; ++HidingP) { - CXXRecordDecl *HidingClass = 0; + CXXRecordDecl *HidingClass = nullptr; if (const RecordType *Record = HidingP->back().Base->getType()->getAs<RecordType>()) HidingClass = cast<CXXRecordDecl>(Record->getDecl()); @@ -501,14 +493,13 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, SubobjectNumber = ++SubobjectCount[cast<CXXRecordDecl>(RD->getCanonicalDecl())]; - for (CXXRecordDecl::base_class_const_iterator Base = RD->bases_begin(), - BaseEnd = RD->bases_end(); Base != BaseEnd; ++Base) { - if (const RecordType *RT = Base->getType()->getAs<RecordType>()) { + for (const auto &Base : RD->bases()) { + if (const RecordType *RT = Base.getType()->getAs<RecordType>()) { const CXXRecordDecl *BaseDecl = cast<CXXRecordDecl>(RT->getDecl()); if (!BaseDecl->isPolymorphic()) continue; - if (Overriders.empty() && !Base->isVirtual()) { + if (Overriders.empty() && !Base.isVirtual()) { // There are no other overriders of virtual member functions, // so let the base class fill in our overriders for us. Collect(BaseDecl, false, InVirtualSubobject, Overriders); @@ -522,7 +513,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, // its base classes) more than once. CXXFinalOverriderMap ComputedBaseOverriders; CXXFinalOverriderMap *BaseOverriders = &ComputedBaseOverriders; - if (Base->isVirtual()) { + if (Base.isVirtual()) { CXXFinalOverriderMap *&MyVirtualOverriders = VirtualOverriders[BaseDecl]; BaseOverriders = MyVirtualOverriders; if (!MyVirtualOverriders) { @@ -551,10 +542,7 @@ void FinalOverriderCollector::Collect(const CXXRecordDecl *RD, } } - for (CXXRecordDecl::method_iterator M = RD->method_begin(), - MEnd = RD->method_end(); - M != MEnd; - ++M) { + for (auto *M : RD->methods()) { // We only care about virtual methods. if (!M->isVirtual()) continue; @@ -637,7 +625,7 @@ FinalOverriderCollector::~FinalOverriderCollector() { void CXXRecordDecl::getFinalOverriders(CXXFinalOverriderMap &FinalOverriders) const { FinalOverriderCollector Collector; - Collector.Collect(this, false, 0, FinalOverriders); + Collector.Collect(this, false, nullptr, FinalOverriders); // Weed out any final overriders that come from virtual base class // subobjects that were hidden by other subobjects along any path. @@ -702,13 +690,12 @@ AddIndirectPrimaryBases(const CXXRecordDecl *RD, ASTContext &Context, if (Layout.isPrimaryBaseVirtual()) Bases.insert(Layout.getPrimaryBase()); - for (CXXRecordDecl::base_class_const_iterator I = RD->bases_begin(), - E = RD->bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + for (const auto &I : RD->bases()) { + assert(!I.getType()->isDependentType() && "Cannot get indirect primary bases for class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); // Only bases with virtual bases participate in computing the // indirect primary virtual base classes. @@ -725,13 +712,12 @@ CXXRecordDecl::getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const { if (!getNumVBases()) return; - for (CXXRecordDecl::base_class_const_iterator I = bases_begin(), - E = bases_end(); I != E; ++I) { - assert(!I->getType()->isDependentType() && + for (const auto &I : bases()) { + assert(!I.getType()->isDependentType() && "Cannot get indirect primary bases for class with dependent bases."); const CXXRecordDecl *BaseDecl = - cast<CXXRecordDecl>(I->getType()->castAs<RecordType>()->getDecl()); + cast<CXXRecordDecl>(I.getType()->castAs<RecordType>()->getDecl()); // Only bases with virtual bases participate in computing the // indirect primary virtual base classes. diff --git a/lib/AST/Comment.cpp b/lib/AST/Comment.cpp index f24a23d34c57..4f433467f9bc 100644 --- a/lib/AST/Comment.cpp +++ b/lib/AST/Comment.cpp @@ -136,7 +136,7 @@ void DeclInfo::fill() { IsInstanceMethod = false; IsClassMethod = false; ParamVars = None; - TemplateParameters = NULL; + TemplateParameters = nullptr; if (!CommentDecl) { // If there is no declaration, the defaults is our only guess. @@ -159,7 +159,7 @@ void DeclInfo::fill() { Kind = FunctionKind; ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), FD->getNumParams()); - ResultType = FD->getResultType(); + ReturnType = FD->getReturnType(); unsigned NumLists = FD->getNumTemplateParameterLists(); if (NumLists != 0) { TemplateKind = TemplateSpecialization; @@ -180,7 +180,7 @@ void DeclInfo::fill() { Kind = FunctionKind; ParamVars = ArrayRef<const ParmVarDecl *>(MD->param_begin(), MD->param_size()); - ResultType = MD->getResultType(); + ReturnType = MD->getReturnType(); IsObjCMethod = true; IsInstanceMethod = MD->isInstanceMethod(); IsClassMethod = !IsInstanceMethod; @@ -193,7 +193,7 @@ void DeclInfo::fill() { const FunctionDecl *FD = FTD->getTemplatedDecl(); ParamVars = ArrayRef<const ParmVarDecl *>(FD->param_begin(), FD->getNumParams()); - ResultType = FD->getResultType(); + ReturnType = FD->getReturnType(); TemplateParameters = FTD->getTemplateParameters(); break; } @@ -251,6 +251,16 @@ void DeclInfo::fill() { TL = PointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } + // Look through reference types. + if (ReferenceTypeLoc ReferenceTL = TL.getAs<ReferenceTypeLoc>()) { + TL = ReferenceTL.getPointeeLoc().getUnqualifiedLoc(); + continue; + } + // Look through adjusted types. + if (AdjustedTypeLoc ATL = TL.getAs<AdjustedTypeLoc>()) { + TL = ATL.getOriginalLoc(); + continue; + } if (BlockPointerTypeLoc BlockPointerTL = TL.getAs<BlockPointerTypeLoc>()) { TL = BlockPointerTL.getPointeeLoc().getUnqualifiedLoc(); @@ -261,13 +271,39 @@ void DeclInfo::fill() { TL = MemberPointerTL.getPointeeLoc().getUnqualifiedLoc(); continue; } + if (ElaboratedTypeLoc ETL = TL.getAs<ElaboratedTypeLoc>()) { + TL = ETL.getNamedTypeLoc(); + continue; + } // Is this a typedef for a function type? if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { Kind = FunctionKind; ArrayRef<ParmVarDecl *> Params = FTL.getParams(); ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), Params.size()); - ResultType = FTL.getResultLoc().getType(); + ReturnType = FTL.getReturnLoc().getType(); + break; + } + if (TemplateSpecializationTypeLoc STL = + TL.getAs<TemplateSpecializationTypeLoc>()) { + // If we have a typedef to a template specialization with exactly one + // template argument of a function type, this looks like std::function, + // boost::function, or other function wrapper. Treat these typedefs as + // functions. + if (STL.getNumArgs() != 1) + break; + TemplateArgumentLoc MaybeFunction = STL.getArgLoc(0); + if (MaybeFunction.getArgument().getKind() != TemplateArgument::Type) + break; + TypeSourceInfo *MaybeFunctionTSI = MaybeFunction.getTypeSourceInfo(); + TypeLoc TL = MaybeFunctionTSI->getTypeLoc().getUnqualifiedLoc(); + if (FunctionTypeLoc FTL = TL.getAs<FunctionTypeLoc>()) { + Kind = FunctionKind; + ArrayRef<ParmVarDecl *> Params = FTL.getParams(); + ParamVars = ArrayRef<const ParmVarDecl *>(Params.data(), + Params.size()); + ReturnType = FTL.getReturnLoc().getType(); + } break; } break; diff --git a/lib/AST/CommentCommandTraits.cpp b/lib/AST/CommentCommandTraits.cpp index 01bd12e5fefa..a7b07a40c985 100644 --- a/lib/AST/CommentCommandTraits.cpp +++ b/lib/AST/CommentCommandTraits.cpp @@ -43,47 +43,42 @@ const CommandInfo *CommandTraits::getCommandInfo(unsigned CommandID) const { return getRegisteredCommandInfo(CommandID); } -static void -HelperTypoCorrectCommandInfo(SmallVectorImpl<const CommandInfo *> &BestCommand, - StringRef Typo, const CommandInfo *Command) { - const unsigned MaxEditDistance = 1; - unsigned BestEditDistance = MaxEditDistance + 1; - StringRef Name = Command->Name; - - unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); - if (MinPossibleEditDistance > 0 && - Typo.size() / MinPossibleEditDistance < 1) - return; - unsigned EditDistance = Typo.edit_distance(Name, true, MaxEditDistance); - if (EditDistance > MaxEditDistance) - return; - if (EditDistance == BestEditDistance) - BestCommand.push_back(Command); - else if (EditDistance < BestEditDistance) { - BestCommand.clear(); - BestCommand.push_back(Command); - BestEditDistance = EditDistance; - } -} - const CommandInfo * CommandTraits::getTypoCorrectCommandInfo(StringRef Typo) const { - // single character command impostures, such as \t or \n must not go + // Single-character command impostures, such as \t or \n, should not go // through the fixit logic. if (Typo.size() <= 1) - return NULL; - + return nullptr; + + // The maximum edit distance we're prepared to accept. + const unsigned MaxEditDistance = 1; + + unsigned BestEditDistance = MaxEditDistance; SmallVector<const CommandInfo *, 2> BestCommand; - - const int NumOfCommands = llvm::array_lengthof(Commands); - for (int i = 0; i < NumOfCommands; i++) - HelperTypoCorrectCommandInfo(BestCommand, Typo, &Commands[i]); - - for (unsigned i = 0, e = RegisteredCommands.size(); i != e; ++i) - if (!RegisteredCommands[i]->IsUnknownCommand) - HelperTypoCorrectCommandInfo(BestCommand, Typo, RegisteredCommands[i]); - - return (BestCommand.size() != 1) ? NULL : BestCommand[0]; + + auto ConsiderCorrection = [&](const CommandInfo *Command) { + StringRef Name = Command->Name; + + unsigned MinPossibleEditDistance = abs((int)Name.size() - (int)Typo.size()); + if (MinPossibleEditDistance <= BestEditDistance) { + unsigned EditDistance = Typo.edit_distance(Name, true, BestEditDistance); + if (EditDistance < BestEditDistance) { + BestEditDistance = EditDistance; + BestCommand.clear(); + } + if (EditDistance == BestEditDistance) + BestCommand.push_back(Command); + } + }; + + for (const auto &Command : Commands) + ConsiderCorrection(&Command); + + for (const auto *Command : RegisteredCommands) + if (!Command->IsUnknownCommand) + ConsiderCorrection(Command); + + return BestCommand.size() == 1 ? BestCommand[0] : nullptr; } CommandInfo *CommandTraits::createCommandInfoWithName(StringRef CommandName) { @@ -118,7 +113,7 @@ const CommandInfo *CommandTraits::getBuiltinCommandInfo( unsigned CommandID) { if (CommandID < llvm::array_lengthof(Commands)) return &Commands[CommandID]; - return NULL; + return nullptr; } const CommandInfo *CommandTraits::getRegisteredCommandInfo( @@ -127,7 +122,7 @@ const CommandInfo *CommandTraits::getRegisteredCommandInfo( if (RegisteredCommands[i]->Name == Name) return RegisteredCommands[i]; } - return NULL; + return nullptr; } const CommandInfo *CommandTraits::getRegisteredCommandInfo( diff --git a/lib/AST/CommentLexer.cpp b/lib/AST/CommentLexer.cpp index 01ed3ce80a66..792a8320449b 100644 --- a/lib/AST/CommentLexer.cpp +++ b/lib/AST/CommentLexer.cpp @@ -268,6 +268,19 @@ const char *findCCommentEnd(const char *BufferPtr, const char *BufferEnd) { } // unnamed namespace +void Lexer::formTokenWithChars(Token &Result, const char *TokEnd, + tok::TokenKind Kind) { + const unsigned TokLen = TokEnd - BufferPtr; + Result.setLocation(getSourceLocation(BufferPtr)); + Result.setKind(Kind); + Result.setLength(TokLen); +#ifndef NDEBUG + Result.TextPtr = "<UNSET>"; + Result.IntVal = 7; +#endif + BufferPtr = TokEnd; +} + void Lexer::lexCommentText(Token &T) { assert(CommentState == LCS_InsideBCPLComment || CommentState == LCS_InsideCComment); diff --git a/lib/AST/CommentParser.cpp b/lib/AST/CommentParser.cpp index 03e01015b954..cb37ec35f4d3 100644 --- a/lib/AST/CommentParser.cpp +++ b/lib/AST/CommentParser.cpp @@ -311,9 +311,9 @@ void Parser::parseBlockCommandArgs(BlockCommandComment *BC, BlockCommandComment *Parser::parseBlockCommand() { assert(Tok.is(tok::backslash_command) || Tok.is(tok::at_command)); - ParamCommandComment *PC = 0; - TParamCommandComment *TPC = 0; - BlockCommandComment *BC = 0; + ParamCommandComment *PC = nullptr; + TParamCommandComment *TPC = nullptr; + BlockCommandComment *BC = nullptr; const CommandInfo *Info = Traits.getCommandInfo(Tok.getCommandID()); CommandMarkerKind CommandMarker = Tok.is(tok::backslash_command) ? CMK_Backslash : CMK_At; diff --git a/lib/AST/CommentSema.cpp b/lib/AST/CommentSema.cpp index 1c6222f9ec02..12823c37dfc6 100644 --- a/lib/AST/CommentSema.cpp +++ b/lib/AST/CommentSema.cpp @@ -29,7 +29,8 @@ Sema::Sema(llvm::BumpPtrAllocator &Allocator, const SourceManager &SourceMgr, DiagnosticsEngine &Diags, CommandTraits &Traits, const Preprocessor *PP) : Allocator(Allocator), SourceMgr(SourceMgr), Diags(Diags), Traits(Traits), - PP(PP), ThisDeclInfo(NULL), BriefCommand(NULL), HeaderfileCommand(NULL) { + PP(PP), ThisDeclInfo(nullptr), BriefCommand(nullptr), + HeaderfileCommand(nullptr) { } void Sema::setDecl(const Decl *D) { @@ -68,8 +69,12 @@ void Sema::actOnBlockCommandFinish(BlockCommandComment *Command, Command->setParagraph(Paragraph); checkBlockCommandEmptyParagraph(Command); checkBlockCommandDuplicate(Command); - checkReturnsCommand(Command); - checkDeprecatedCommand(Command); + if (ThisDeclInfo) { + // These checks only make sense if the comment is attached to a + // declaration. + checkReturnsCommand(Command); + checkDeprecatedCommand(Command); + } } ParamCommandComment *Sema::actOnParamCommandStart( @@ -122,7 +127,7 @@ void Sema::checkFunctionDeclVerbatimLine(const BlockCommandComment *Comment) { << (DiagSelect-1) << (DiagSelect-1) << Comment->getSourceRange(); } - + void Sema::checkContainerDeclVerbatimLine(const BlockCommandComment *Comment) { const CommandInfo *Info = Traits.getCommandInfo(Comment->getCommandID()); if (!Info->IsRecordLikeDeclarationCommand) @@ -478,6 +483,7 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, if (isHTMLEndTagForbidden(TagName)) { Diag(HET->getLocation(), diag::warn_doc_html_end_forbidden) << TagName << HET->getSourceRange(); + HET->setIsMalformed(); return HET; } @@ -493,14 +499,19 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, if (!FoundOpen) { Diag(HET->getLocation(), diag::warn_doc_html_end_unbalanced) << HET->getSourceRange(); + HET->setIsMalformed(); return HET; } while (!HTMLOpenTags.empty()) { - const HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); + HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); StringRef LastNotClosedTagName = HST->getTagName(); - if (LastNotClosedTagName == TagName) + if (LastNotClosedTagName == TagName) { + // If the start tag is malformed, end tag is malformed as well. + if (HST->isMalformed()) + HET->setIsMalformed(); break; + } if (isHTMLEndTagOptional(LastNotClosedTagName)) continue; @@ -514,16 +525,18 @@ HTMLEndTagComment *Sema::actOnHTMLEndTag(SourceLocation LocBegin, HET->getLocation(), &CloseLineInvalid); - if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) + if (OpenLineInvalid || CloseLineInvalid || OpenLine == CloseLine) { Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch) << HST->getTagName() << HET->getTagName() << HST->getSourceRange() << HET->getSourceRange(); - else { + HST->setIsMalformed(); + } else { Diag(HST->getLocation(), diag::warn_doc_html_start_end_mismatch) << HST->getTagName() << HET->getTagName() << HST->getSourceRange(); Diag(HET->getLocation(), diag::note_doc_html_end_tag) << HET->getSourceRange(); + HST->setIsMalformed(); } } @@ -534,6 +547,18 @@ FullComment *Sema::actOnFullComment( ArrayRef<BlockContentComment *> Blocks) { FullComment *FC = new (Allocator) FullComment(Blocks, ThisDeclInfo); resolveParamCommandIndexes(FC); + + // Complain about HTML tags that are not closed. + while (!HTMLOpenTags.empty()) { + HTMLStartTagComment *HST = HTMLOpenTags.pop_back_val(); + if (isHTMLEndTagOptional(HST->getTagName())) + continue; + + Diag(HST->getLocation(), diag::warn_doc_html_missing_end_tag) + << HST->getTagName() << HST->getSourceRange(); + HST->setIsMalformed(); + } + return FC; } @@ -558,8 +583,11 @@ void Sema::checkBlockCommandEmptyParagraph(BlockCommandComment *Command) { void Sema::checkReturnsCommand(const BlockCommandComment *Command) { if (!Traits.getCommandInfo(Command->getCommandID())->IsReturnsCommand) return; + + assert(ThisDeclInfo && "should not call this check on a bare comment"); + if (isFunctionDecl()) { - if (ThisDeclInfo->ResultType->isVoidType()) { + if (ThisDeclInfo->ReturnType->isVoidType()) { unsigned DiagKind; switch (ThisDeclInfo->CommentDecl->getKind()) { default: @@ -586,7 +614,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { } else if (isObjCPropertyDecl()) return; - + Diag(Command->getLocation(), diag::warn_doc_returns_not_attached_to_a_function_decl) << Command->getCommandMarker() @@ -596,7 +624,7 @@ void Sema::checkReturnsCommand(const BlockCommandComment *Command) { void Sema::checkBlockCommandDuplicate(const BlockCommandComment *Command) { const CommandInfo *Info = Traits.getCommandInfo(Command->getCommandID()); - const BlockCommandComment *PrevCommand = NULL; + const BlockCommandComment *PrevCommand = nullptr; if (Info->IsBriefCommand) { if (!BriefCommand) { BriefCommand = Command; @@ -636,6 +664,8 @@ void Sema::checkDeprecatedCommand(const BlockCommandComment *Command) { if (!Traits.getCommandInfo(Command->getCommandID())->IsDeprecatedCommand) return; + assert(ThisDeclInfo && "should not call this check on a bare comment"); + const Decl *D = ThisDeclInfo->CommentDecl; if (!D) return; @@ -694,7 +724,7 @@ void Sema::resolveParamCommandIndexes(const FullComment *FC) { SmallVector<ParamCommandComment *, 8> ParamVarDocs; ArrayRef<const ParmVarDecl *> ParamVars = getParamVars(); - ParamVarDocs.resize(ParamVars.size(), NULL); + ParamVarDocs.resize(ParamVars.size(), nullptr); // First pass over all \\param commands: resolve all parameter names. for (Comment::child_iterator I = FC->child_begin(), E = FC->child_end(); @@ -783,11 +813,14 @@ bool Sema::isAnyFunctionDecl() { } bool Sema::isFunctionOrMethodVariadic() { - if (!isAnyFunctionDecl() && !isObjCMethodDecl()) + if (!isAnyFunctionDecl() && !isObjCMethodDecl() && !isFunctionTemplateDecl()) return false; if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ThisDeclInfo->CurrentDecl)) return FD->isVariadic(); + if (const FunctionTemplateDecl *FTD = + dyn_cast<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)) + return FTD->getTemplatedDecl()->isVariadic(); if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(ThisDeclInfo->CurrentDecl)) return MD->isVariadic(); @@ -812,7 +845,7 @@ bool Sema::isFunctionPointerVarDecl() { } return false; } - + bool Sema::isObjCPropertyDecl() { if (!ThisDeclInfo) return false; @@ -834,8 +867,8 @@ bool Sema::isRecordLikeDecl() { return false; if (!ThisDeclInfo->IsFilled) inspectThisDecl(); - return isUnionDecl() || isClassOrStructDecl() - || isObjCInterfaceDecl() || isObjCProtocolDecl(); + return isUnionDecl() || isClassOrStructDecl() || isObjCInterfaceDecl() || + isObjCProtocolDecl(); } bool Sema::isUnionDecl() { @@ -848,7 +881,7 @@ bool Sema::isUnionDecl() { return RD->isUnion(); return false; } - + bool Sema::isClassOrStructDecl() { if (!ThisDeclInfo) return false; @@ -858,7 +891,7 @@ bool Sema::isClassOrStructDecl() { isa<RecordDecl>(ThisDeclInfo->CurrentDecl) && !isUnionDecl(); } - + bool Sema::isClassTemplateDecl() { if (!ThisDeclInfo) return false; @@ -874,7 +907,7 @@ bool Sema::isFunctionTemplateDecl() { if (!ThisDeclInfo->IsFilled) inspectThisDecl(); return ThisDeclInfo->CurrentDecl && - (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)); + (isa<FunctionTemplateDecl>(ThisDeclInfo->CurrentDecl)); } bool Sema::isObjCInterfaceDecl() { @@ -885,7 +918,7 @@ bool Sema::isObjCInterfaceDecl() { return ThisDeclInfo->CurrentDecl && isa<ObjCInterfaceDecl>(ThisDeclInfo->CurrentDecl); } - + bool Sema::isObjCProtocolDecl() { if (!ThisDeclInfo) return false; @@ -894,7 +927,7 @@ bool Sema::isObjCProtocolDecl() { return ThisDeclInfo->CurrentDecl && isa<ObjCProtocolDecl>(ThisDeclInfo->CurrentDecl); } - + ArrayRef<const ParmVarDecl *> Sema::getParamVars() { if (!ThisDeclInfo->IsFilled) inspectThisDecl(); @@ -930,7 +963,7 @@ class SimpleTypoCorrector { public: SimpleTypoCorrector(StringRef Typo) : Typo(Typo), MaxEditDistance((Typo.size() + 2) / 3), - BestDecl(NULL), BestEditDistance(MaxEditDistance + 1), + BestDecl(nullptr), BestEditDistance(MaxEditDistance + 1), BestIndex(0), NextIndex(0) { } @@ -938,7 +971,7 @@ public: const NamedDecl *getBestDecl() const { if (BestEditDistance > MaxEditDistance) - return NULL; + return nullptr; return BestDecl; } diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp index 6bd985851a39..7448de2ffbc9 100644 --- a/lib/AST/Decl.cpp +++ b/lib/AST/Decl.cpp @@ -13,6 +13,7 @@ #include "clang/AST/Decl.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTLambda.h" #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Attr.h" #include "clang/AST/DeclCXX.h" @@ -29,7 +30,6 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetInfo.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/type_traits.h" #include <algorithm> using namespace clang; @@ -158,8 +158,7 @@ static bool usesTypeVisibility(const NamedDecl *D) { /// Does the given declaration have member specialization information, /// and if so, is it an explicit specialization? template <class T> static typename -llvm::enable_if_c<!llvm::is_base_of<RedeclarableTemplateDecl, T>::value, - bool>::type +std::enable_if<!std::is_base_of<RedeclarableTemplateDecl, T>::value, bool>::type isExplicitMemberSpecialization(const T *D) { if (const MemberSpecializationInfo *member = D->getMemberSpecializationInfo()) { @@ -209,11 +208,8 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D, // If we're on Mac OS X, an 'availability' for Mac OS X attribute // implies visibility(default). if (D->getASTContext().getTargetInfo().getTriple().isOSDarwin()) { - for (specific_attr_iterator<AvailabilityAttr> - A = D->specific_attr_begin<AvailabilityAttr>(), - AEnd = D->specific_attr_end<AvailabilityAttr>(); - A != AEnd; ++A) - if ((*A)->getPlatform()->getName().equals("macosx")) + for (const auto *A : D->specific_attrs<AvailabilityAttr>()) + if (A->getPlatform()->getName().equals("macosx")) return DefaultVisibility; } @@ -231,23 +227,21 @@ getLVForType(const Type &T, LVComputationKind computation) { /// template parameter list. For visibility purposes, template /// parameters are part of the signature of a template. static LinkageInfo -getLVForTemplateParameterList(const TemplateParameterList *params, +getLVForTemplateParameterList(const TemplateParameterList *Params, LVComputationKind computation) { LinkageInfo LV; - for (TemplateParameterList::const_iterator P = params->begin(), - PEnd = params->end(); - P != PEnd; ++P) { - + for (const NamedDecl *P : *Params) { // Template type parameters are the most common and never // contribute to visibility, pack or not. - if (isa<TemplateTypeParmDecl>(*P)) + if (isa<TemplateTypeParmDecl>(P)) continue; // Non-type template parameters can be restricted by the value type, e.g. // template <enum X> class A { ... }; // We have to be careful here, though, because we can be dealing with // dependent types. - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + if (const NonTypeTemplateParmDecl *NTTP = + dyn_cast<NonTypeTemplateParmDecl>(P)) { // Handle the non-pack case first. if (!NTTP->isExpandedParameterPack()) { if (!NTTP->getType()->isDependentType()) { @@ -267,7 +261,7 @@ getLVForTemplateParameterList(const TemplateParameterList *params, // Template template parameters can be restricted by their // template parameters, recursively. - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + const TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(P); // Handle the non-pack case first. if (!TTP->isExpandedParameterPack()) { @@ -292,7 +286,7 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, LVComputationKind computation); static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { - const Decl *Ret = NULL; + const Decl *Ret = nullptr; const DeclContext *DC = D->getDeclContext(); while (DC->getDeclKind() != Decl::TranslationUnit) { if (isa<FunctionDecl>(DC) || isa<BlockDecl>(DC)) @@ -307,43 +301,41 @@ static const Decl *getOutermostFuncOrBlockContext(const Decl *D) { /// /// Note that we don't take an LVComputationKind because we always /// want to honor the visibility of template arguments in the same way. -static LinkageInfo -getLVForTemplateArgumentList(ArrayRef<TemplateArgument> args, - LVComputationKind computation) { +static LinkageInfo getLVForTemplateArgumentList(ArrayRef<TemplateArgument> Args, + LVComputationKind computation) { LinkageInfo LV; - for (unsigned i = 0, e = args.size(); i != e; ++i) { - const TemplateArgument &arg = args[i]; - switch (arg.getKind()) { + for (const TemplateArgument &Arg : Args) { + switch (Arg.getKind()) { case TemplateArgument::Null: case TemplateArgument::Integral: case TemplateArgument::Expression: continue; case TemplateArgument::Type: - LV.merge(getLVForType(*arg.getAsType(), computation)); + LV.merge(getLVForType(*Arg.getAsType(), computation)); continue; case TemplateArgument::Declaration: - if (NamedDecl *ND = dyn_cast<NamedDecl>(arg.getAsDecl())) { + if (NamedDecl *ND = dyn_cast<NamedDecl>(Arg.getAsDecl())) { assert(!usesTypeVisibility(ND)); LV.merge(getLVForDecl(ND, computation)); } continue; case TemplateArgument::NullPtr: - LV.merge(arg.getNullPtrType()->getLinkageAndVisibility()); + LV.merge(Arg.getNullPtrType()->getLinkageAndVisibility()); continue; case TemplateArgument::Template: case TemplateArgument::TemplateExpansion: - if (TemplateDecl *Template - = arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) + if (TemplateDecl *Template = + Arg.getAsTemplateOrTemplatePattern().getAsTemplateDecl()) LV.merge(getLVForDecl(Template, computation)); continue; case TemplateArgument::Pack: - LV.merge(getLVForTemplateArgumentList(arg.getPackAsArray(), computation)); + LV.merge(getLVForTemplateArgumentList(Arg.getPackAsArray(), computation)); continue; } llvm_unreachable("bad template argument kind"); @@ -479,6 +471,58 @@ static void mergeTemplateLV(LinkageInfo &LV, LV.mergeExternalVisibility(argsLV); } +/// Should we consider visibility associated with the template +/// arguments and parameters of the given variable template +/// specialization? As usual, follow class template specialization +/// logic up to initialization. +static bool shouldConsiderTemplateVisibility( + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + // Include visibility from the template parameters and arguments + // only if this is not an explicit instantiation or specialization + // with direct explicit visibility (and note that implicit + // instantiations won't have a direct attribute). + if (!spec->isExplicitInstantiationOrSpecialization()) + return true; + + // An explicit variable specialization is an independent, top-level + // declaration. As such, if it has an explicit visibility attribute, + // that must directly express the user's intent, and we should honor + // it. + if (spec->isExplicitSpecialization() && + hasExplicitVisibilityAlready(computation)) + return false; + + return !hasDirectVisibilityAttribute(spec, computation); +} + +/// Merge in template-related linkage and visibility for the given +/// variable template specialization. As usual, follow class template +/// specialization logic up to initialization. +static void mergeTemplateLV(LinkageInfo &LV, + const VarTemplateSpecializationDecl *spec, + LVComputationKind computation) { + bool considerVisibility = shouldConsiderTemplateVisibility(spec, computation); + + // Merge information from the template parameters, but ignore + // visibility if we're only considering template arguments. + + VarTemplateDecl *temp = spec->getSpecializedTemplate(); + LinkageInfo tempLV = + getLVForTemplateParameterList(temp->getTemplateParameters(), computation); + LV.mergeMaybeWithVisibility(tempLV, + considerVisibility && !hasExplicitVisibilityAlready(computation)); + + // Merge information from the template arguments. We ignore + // template-argument visibility if we've got an explicit + // instantiation with a visibility attribute. + const TemplateArgumentList &templateArgs = spec->getTemplateArgs(); + LinkageInfo argsLV = getLVForTemplateArgumentList(templateArgs, computation); + if (considerVisibility) + LV.mergeVisibility(argsLV); + LV.mergeExternalVisibility(argsLV); +} + static bool useInlineVisibilityHidden(const NamedDecl *D) { // FIXME: we should warn if -fvisibility-inlines-hidden is used with c. const LangOptions &Opts = D->getASTContext().getLangOpts(); @@ -498,7 +542,7 @@ static bool useInlineVisibilityHidden(const NamedDecl *D) { TSK = MSI->getTemplateSpecializationKind(); } - const FunctionDecl *Def = 0; + const FunctionDecl *Def = nullptr; // InlineVisibilityHidden only applies to definitions, and // isInlined() only gives meaningful answers on definitions // anyway. @@ -512,9 +556,9 @@ template <typename T> static bool isFirstInExternCContext(T *D) { return First->isInExternCContext(); } -static bool isSingleLineExternC(const Decl &D) { +static bool isSingleLineLanguageLinkage(const Decl &D) { if (const LinkageSpecDecl *SD = dyn_cast<LinkageSpecDecl>(D.getDeclContext())) - if (SD->getLanguage() == LinkageSpecDecl::lang_c && !SD->hasBraces()) + if (!SD->hasBraces()) return true; return false; } @@ -548,7 +592,7 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (Var->getStorageClass() != SC_Extern && Var->getStorageClass() != SC_PrivateExtern && - !isSingleLineExternC(*Var)) + !isSingleLineLanguageLinkage(*Var)) return LinkageInfo::internal(); } @@ -561,16 +605,10 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, if (PrevVar->getStorageClass() == SC_Static) return LinkageInfo::internal(); } - } else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) { + } else if (const FunctionDecl *Function = D->getAsFunction()) { // C++ [temp]p4: // A non-member function template can have internal linkage; any // other template name shall have external linkage. - const FunctionDecl *Function = 0; - if (const FunctionTemplateDecl *FunTmpl - = dyn_cast<FunctionTemplateDecl>(D)) - Function = FunTmpl->getTemplatedDecl(); - else - Function = cast<FunctionDecl>(D); // Explicitly declared static. if (Function->getCanonicalDecl()->getStorageClass() == SC_Static) @@ -676,6 +714,14 @@ static LinkageInfo getLVForNamespaceScopeDecl(const NamedDecl *D, // C99 6.2.2p4 and propagating the visibility attribute, so we don't have // to do it here. + // As per function and class template specializations (below), + // consider LV for the template and template arguments. We're at file + // scope, so we do not need to worry about nested specializations. + if (const VarTemplateSpecializationDecl *spec + = dyn_cast<VarTemplateSpecializationDecl>(Var)) { + mergeTemplateLV(LV, spec, computation); + } + // - a function, unless it has internal linkage; or } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { // In theory, we can modify the function's LV by the LV of its @@ -782,11 +828,18 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // really have linkage, but it's convenient to say they do for the // purposes of calculating linkage of pointer-to-data-member // template arguments. + // + // Templates also don't officially have linkage, but since we ignore + // the C++ standard and look at template arguments when determining + // linkage and visibility of a template specialization, we might hit + // a template template argument that way. If we do, we need to + // consider its linkage. if (!(isa<CXXMethodDecl>(D) || isa<VarDecl>(D) || isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || - isa<TagDecl>(D))) + isa<TagDecl>(D) || + isa<TemplateDecl>(D))) return LinkageInfo::none(); LinkageInfo LV; @@ -825,7 +878,7 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // we need to completely ignore the visibility from it. // Specifically, if this decl exists and has an explicit attribute. - const NamedDecl *explicitSpecSuppressor = 0; + const NamedDecl *explicitSpecSuppressor = nullptr; if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) { // If the type of the function uses a type with unique-external @@ -876,6 +929,10 @@ static LinkageInfo getLVForClassMember(const NamedDecl *D, // Static data members. } else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const VarTemplateSpecializationDecl *spec + = dyn_cast<VarTemplateSpecializationDecl>(VD)) + mergeTemplateLV(LV, spec, computation); + // Modify the variable's linkage by its type, but ignore the // type's visibility unless it's a definition. LinkageInfo typeLV = getLVForType(*VD->getType(), computation); @@ -989,6 +1046,10 @@ getExplicitVisibilityAux(const NamedDecl *ND, return getVisibilityOf(InstantiatedFrom, kind); } + if (const auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Var)) + return getVisibilityOf(VTSD->getSpecializedTemplate()->getTemplatedDecl(), + kind); + return None; } // Also handle function template specializations. @@ -1242,16 +1303,13 @@ public: // We have just computed the linkage for this decl. By induction we know // that all other computed linkages match, check that the one we just - // computed - // also does. - NamedDecl *Old = NULL; - for (NamedDecl::redecl_iterator I = D->redecls_begin(), - E = D->redecls_end(); - I != E; ++I) { - NamedDecl *T = cast<NamedDecl>(*I); + // computed also does. + NamedDecl *Old = nullptr; + for (auto I : D->redecls()) { + NamedDecl *T = cast<NamedDecl>(I); if (T == D) continue; - if (T->hasCachedLinkage()) { + if (!T->isInvalidDecl() && T->hasCachedLinkage()) { Old = T; break; } @@ -1270,13 +1328,9 @@ static LinkageInfo getLVForDecl(const NamedDecl *D, } std::string NamedDecl::getQualifiedNameAsString() const { - return getQualifiedNameAsString(getASTContext().getPrintingPolicy()); -} - -std::string NamedDecl::getQualifiedNameAsString(const PrintingPolicy &P) const { std::string QualName; llvm::raw_string_ostream OS(QualName); - printQualifiedName(OS, P); + printQualifiedName(OS, getASTContext().getPrintingPolicy()); return OS.str(); } @@ -1313,17 +1367,20 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, TemplateArgs.size(), P); } else if (const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(*I)) { + if (P.SuppressUnwrittenScope && + (ND->isAnonymousNamespace() || ND->isInline())) + continue; if (ND->isAnonymousNamespace()) - OS << "<anonymous namespace>"; + OS << "(anonymous namespace)"; else OS << *ND; } else if (const RecordDecl *RD = dyn_cast<RecordDecl>(*I)) { if (!RD->getIdentifier()) - OS << "<anonymous " << RD->getKindName() << '>'; + OS << "(anonymous " << RD->getKindName() << ')'; else OS << *RD; } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(*I)) { - const FunctionProtoType *FT = 0; + const FunctionProtoType *FT = nullptr; if (FD->hasWrittenPrototype()) FT = dyn_cast<FunctionProtoType>(FD->getType()->castAs<FunctionType>()); @@ -1352,7 +1409,7 @@ void NamedDecl::printQualifiedName(raw_ostream &OS, if (getDeclName()) OS << *this; else - OS << "<anonymous>"; + OS << "(anonymous)"; } void NamedDecl::getNameForDiagnostic(raw_ostream &OS, @@ -1392,6 +1449,7 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { if (isa<ObjCMethodDecl>(this)) return false; + // FIXME: Is this correct if one of the decls comes from an inline namespace? if (isa<ObjCInterfaceDecl>(this) && isa<ObjCCompatibleAliasDecl>(OldD)) return true; @@ -1418,14 +1476,19 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD) const { // A typedef of an Objective-C class type can replace an Objective-C class // declaration or definition, and vice versa. + // FIXME: Is this correct if one of the decls comes from an inline namespace? if ((isa<TypedefNameDecl>(this) && isa<ObjCInterfaceDecl>(OldD)) || (isa<ObjCInterfaceDecl>(this) && isa<TypedefNameDecl>(OldD))) return true; - + // For non-function declarations, if the declarations are of the - // same kind then this must be a redeclaration, or semantic analysis - // would not have given us the new declaration. - return this->getKind() == OldD->getKind(); + // same kind and have the same parent then this must be a redeclaration, + // or semantic analysis would not have given us the new declaration. + // Note that inline namespaces can give us two declarations with the same + // name and kind in the same scope but different contexts. + return this->getKind() == OldD->getKind() && + this->getDeclContext()->getRedeclContext()->Equals( + OldD->getDeclContext()->getRedeclContext()); } bool NamedDecl::hasLinkage() const { @@ -1453,11 +1516,9 @@ bool NamedDecl::isCXXInstanceMember() const { if (isa<FieldDecl>(D) || isa<IndirectFieldDecl>(D) || isa<MSPropertyDecl>(D)) return true; - if (isa<CXXMethodDecl>(D)) - return cast<CXXMethodDecl>(D)->isInstance(); - if (isa<FunctionTemplateDecl>(D)) - return cast<CXXMethodDecl>(cast<FunctionTemplateDecl>(D) - ->getTemplatedDecl())->isInstance(); + if (const CXXMethodDecl *MD = + dyn_cast_or_null<CXXMethodDecl>(D->getAsFunction())) + return MD->isInstance(); return false; } @@ -1574,7 +1635,9 @@ bool typeIsPostfix(clang::QualType QT) { SourceRange DeclaratorDecl::getSourceRange() const { SourceLocation RangeEnd = getLocation(); if (TypeSourceInfo *TInfo = getTypeSourceInfo()) { - if (typeIsPostfix(TInfo->getType())) + // If the declaration has no name or the type extends past the name take the + // end location of the type. + if (!getDeclName() || typeIsPostfix(TInfo->getType())) RangeEnd = TInfo->getTypeLoc().getSourceRange().getEnd(); } return SourceRange(getOuterLocStart(), RangeEnd); @@ -1584,13 +1647,13 @@ void QualifierInfo::setTemplateParameterListsInfo(ASTContext &Context, unsigned NumTPLists, TemplateParameterList **TPLists) { - assert((NumTPLists == 0 || TPLists != 0) && + assert((NumTPLists == 0 || TPLists != nullptr) && "Empty array of template parameters with positive size!"); // Free previous template parameters (if any). if (NumTemplParamLists > 0) { Context.Deallocate(TemplParamLists); - TemplParamLists = 0; + TemplParamLists = nullptr; NumTemplParamLists = 0; } // Set info on matched template parameter lists (if any). @@ -1620,12 +1683,16 @@ const char *VarDecl::getStorageClassSpecifierString(StorageClass SC) { llvm_unreachable("Invalid storage class"); } -VarDecl::VarDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, - SourceLocation IdLoc, IdentifierInfo *Id, QualType T, - TypeSourceInfo *TInfo, StorageClass SC) - : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Init() { - assert(sizeof(VarDeclBitfields) <= sizeof(unsigned)); - assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned)); +VarDecl::VarDecl(Kind DK, ASTContext &C, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, + StorageClass SC) + : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), + redeclarable_base(C), Init() { + static_assert(sizeof(VarDeclBitfields) <= sizeof(unsigned), + "VarDeclBitfields too large!"); + static_assert(sizeof(ParmVarDeclBitfields) <= sizeof(unsigned), + "ParmVarDeclBitfields too large!"); AllBits = 0; VarDeclBits.SClass = SC; // Everything else is implicitly initialized to false. @@ -1635,13 +1702,13 @@ VarDecl *VarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartL, SourceLocation IdL, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S) { - return new (C) VarDecl(Var, DC, StartL, IdL, Id, T, TInfo, S); + return new (C, DC) VarDecl(Var, C, DC, StartL, IdL, Id, T, TInfo, S); } VarDecl *VarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(VarDecl)); - return new (Mem) VarDecl(Var, 0, SourceLocation(), SourceLocation(), 0, - QualType(), 0, SC_None); + return new (C, ID) + VarDecl(Var, C, nullptr, SourceLocation(), SourceLocation(), nullptr, + QualType(), nullptr, SC_None); } void VarDecl::setStorageClass(StorageClass SC) { @@ -1649,6 +1716,21 @@ void VarDecl::setStorageClass(StorageClass SC) { VarDeclBits.SClass = SC; } +VarDecl::TLSKind VarDecl::getTLSKind() const { + switch (VarDeclBits.TSCSpec) { + case TSCS_unspecified: + if (hasAttr<ThreadAttr>()) + return TLS_Static; + return TLS_None; + case TSCS___thread: // Fall through. + case TSCS__Thread_local: + return TLS_Static; + case TSCS_thread_local: + return TLS_Dynamic; + } + llvm_unreachable("Unknown thread storage class specifier!"); +} + SourceRange VarDecl::getSourceRange() const { if (const Expr *Init = getInit()) { SourceLocation InitEnd = Init->getLocEnd(); @@ -1661,7 +1743,7 @@ SourceRange VarDecl::getSourceRange() const { } template<typename T> -static LanguageLinkage getLanguageLinkageTemplate(const T &D) { +static LanguageLinkage getDeclLanguageLinkage(const T &D) { // C++ [dcl.link]p1: All function types, function names with external linkage, // and variable names with external linkage have a language linkage. if (!D.hasExternalFormalLinkage()) @@ -1689,7 +1771,7 @@ static LanguageLinkage getLanguageLinkageTemplate(const T &D) { } template<typename T> -static bool isExternCTemplate(const T &D) { +static bool isDeclExternC(const T &D) { // Since the context is ignored for class members, they can only have C++ // language linkage or no language linkage. const DeclContext *DC = D.getDeclContext(); @@ -1702,11 +1784,11 @@ static bool isExternCTemplate(const T &D) { } LanguageLinkage VarDecl::getLanguageLinkage() const { - return getLanguageLinkageTemplate(*this); + return getDeclLanguageLinkage(*this); } bool VarDecl::isExternC() const { - return isExternCTemplate(*this); + return isDeclExternC(*this); } bool VarDecl::isInExternCContext() const { @@ -1775,7 +1857,7 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( // A declaration directly contained in a linkage-specification is treated // as if it contains the extern specifier for the purpose of determining // the linkage of the declared name and whether it is a definition. - if (isSingleLineExternC(*this)) + if (isSingleLineLanguageLinkage(*this)) return DeclarationOnly; // C99 6.9.2p2: @@ -1794,38 +1876,35 @@ VarDecl::DefinitionKind VarDecl::isThisDeclarationADefinition( VarDecl *VarDecl::getActingDefinition() { DefinitionKind Kind = isThisDeclarationADefinition(); if (Kind != TentativeDefinition) - return 0; + return nullptr; - VarDecl *LastTentative = 0; + VarDecl *LastTentative = nullptr; VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - Kind = (*I)->isThisDeclarationADefinition(); + for (auto I : First->redecls()) { + Kind = I->isThisDeclarationADefinition(); if (Kind == Definition) - return 0; + return nullptr; else if (Kind == TentativeDefinition) - LastTentative = *I; + LastTentative = I; } return LastTentative; } VarDecl *VarDecl::getDefinition(ASTContext &C) { VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - if ((*I)->isThisDeclarationADefinition(C) == Definition) - return *I; + for (auto I : First->redecls()) { + if (I->isThisDeclarationADefinition(C) == Definition) + return I; } - return 0; + return nullptr; } VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { DefinitionKind Kind = DeclarationOnly; const VarDecl *First = getFirstDecl(); - for (redecl_iterator I = First->redecls_begin(), E = First->redecls_end(); - I != E; ++I) { - Kind = std::max(Kind, (*I)->isThisDeclarationADefinition(C)); + for (auto I : First->redecls()) { + Kind = std::max(Kind, I->isThisDeclarationADefinition(C)); if (Kind == Definition) break; } @@ -1834,15 +1913,13 @@ VarDecl::DefinitionKind VarDecl::hasDefinition(ASTContext &C) const { } const Expr *VarDecl::getAnyInitializer(const VarDecl *&D) const { - redecl_iterator I = redecls_begin(), E = redecls_end(); - while (I != E && !I->getInit()) - ++I; - - if (I != E) { - D = *I; - return I->getInit(); + for (auto I : redecls()) { + if (auto Expr = I->getInit()) { + D = I; + return Expr; + } } - return 0; + return nullptr; } bool VarDecl::isOutOfLine() const { @@ -1863,15 +1940,14 @@ bool VarDecl::isOutOfLine() const { VarDecl *VarDecl::getOutOfLineDefinition() { if (!isStaticDataMember()) - return 0; - - for (VarDecl::redecl_iterator RD = redecls_begin(), RDEnd = redecls_end(); - RD != RDEnd; ++RD) { + return nullptr; + + for (auto RD : redecls()) { if (RD->getLexicalDeclContext()->isFileContext()) - return *RD; + return RD; } - - return 0; + + return nullptr; } void VarDecl::setInit(Expr *I) { @@ -1948,7 +2024,7 @@ APValue *VarDecl::evaluateValue( // first time it is evaluated. FIXME: The notes won't always be emitted the // first time we try evaluation, so might not be produced at all. if (Eval->WasEvaluated) - return Eval->Evaluated.isUninit() ? 0 : &Eval->Evaluated; + return Eval->Evaluated.isUninit() ? nullptr : &Eval->Evaluated; const Expr *Init = cast<Expr>(Eval->Value); assert(!Init->isValueDependent()); @@ -1957,7 +2033,7 @@ APValue *VarDecl::evaluateValue( // FIXME: Produce a diagnostic for self-initialization. Eval->CheckedICE = true; Eval->IsICE = false; - return 0; + return nullptr; } Eval->IsEvaluating = true; @@ -1983,7 +2059,7 @@ APValue *VarDecl::evaluateValue( Eval->IsICE = Result && Notes.empty(); } - return Result ? &Eval->Evaluated : 0; + return Result ? &Eval->Evaluated : nullptr; } bool VarDecl::checkInitIsICE() const { @@ -2025,8 +2101,8 @@ bool VarDecl::checkInitIsICE() const { VarDecl *VarDecl::getInstantiatedFromStaticDataMember() const { if (MemberSpecializationInfo *MSI = getMemberSpecializationInfo()) return cast<VarDecl>(MSI->getInstantiatedFrom()); - - return 0; + + return nullptr; } TemplateSpecializationKind VarDecl::getTemplateSpecializationKind() const { @@ -2066,7 +2142,7 @@ MemberSpecializationInfo *VarDecl::getMemberSpecializationInfo() const { // return getASTContext().getInstantiatedFromStaticDataMember(this); return getASTContext().getTemplateOrSpecializationInfo(this) .dyn_cast<MemberSpecializationInfo *>(); - return 0; + return nullptr; } void VarDecl::setTemplateSpecializationKind(TemplateSpecializationKind TSK, @@ -2108,8 +2184,8 @@ ParmVarDecl *ParmVarDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, StorageClass S, Expr *DefArg) { - return new (C) ParmVarDecl(ParmVar, DC, StartLoc, IdLoc, Id, T, TInfo, - S, DefArg); + return new (C, DC) ParmVarDecl(ParmVar, C, DC, StartLoc, IdLoc, Id, T, TInfo, + S, DefArg); } QualType ParmVarDecl::getOriginalType() const { @@ -2121,9 +2197,9 @@ QualType ParmVarDecl::getOriginalType() const { } ParmVarDecl *ParmVarDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ParmVarDecl)); - return new (Mem) ParmVarDecl(ParmVar, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, SC_None, 0); + return new (C, ID) + ParmVarDecl(ParmVar, C, nullptr, SourceLocation(), SourceLocation(), + nullptr, QualType(), nullptr, SC_None, nullptr); } SourceRange ParmVarDecl::getSourceRange() const { @@ -2196,9 +2272,9 @@ bool FunctionDecl::isVariadic() const { } bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + for (auto I : redecls()) { if (I->Body || I->IsLateTemplateParsed) { - Definition = *I; + Definition = I; return true; } } @@ -2221,10 +2297,10 @@ bool FunctionDecl::hasTrivialBody() const } bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) { + for (auto I : redecls()) { if (I->IsDeleted || I->IsDefaulted || I->Body || I->IsLateTemplateParsed || I->hasAttr<AliasAttr>()) { - Definition = I->IsDeleted ? I->getCanonicalDecl() : *I; + Definition = I->IsDeleted ? I->getCanonicalDecl() : I; return true; } } @@ -2234,12 +2310,12 @@ bool FunctionDecl::isDefined(const FunctionDecl *&Definition) const { Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const { if (!hasBody(Definition)) - return 0; + return nullptr; if (Definition->Body) return Definition->Body.get(getASTContext().getExternalSource()); - return 0; + return nullptr; } void FunctionDecl::setBody(Stmt *B) { @@ -2303,11 +2379,12 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { getDeclName().getCXXOverloadedOperator() == OO_Array_New || getDeclName().getCXXOverloadedOperator() == OO_Array_Delete); - if (isa<CXXRecordDecl>(getDeclContext())) return false; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; const FunctionProtoType *proto = getType()->castAs<FunctionProtoType>(); - if (proto->getNumArgs() != 2 || proto->isVariadic()) return false; + if (proto->getNumParams() != 2 || proto->isVariadic()) + return false; ASTContext &Context = cast<TranslationUnitDecl>(getDeclContext()->getRedeclContext()) @@ -2315,13 +2392,7 @@ bool FunctionDecl::isReservedGlobalPlacementOperator() const { // The result type and first argument type are constant across all // these operators. The second argument must be exactly void*. - return (proto->getArgType(1).getCanonicalType() == Context.VoidPtrTy); -} - -static bool isNamespaceStd(const DeclContext *DC) { - const NamespaceDecl *ND = dyn_cast<NamespaceDecl>(DC->getRedeclContext()); - return ND && isNamed(ND, "std") && - ND->getParent()->getRedeclContext()->isTranslationUnit(); + return (proto->getParamType(1).getCanonicalType() == Context.VoidPtrTy); } bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { @@ -2335,20 +2406,23 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { if (isa<CXXRecordDecl>(getDeclContext())) return false; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + + // This can only fail for an invalid 'operator new' declaration. + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return false; const FunctionProtoType *FPT = getType()->castAs<FunctionProtoType>(); - if (FPT->getNumArgs() > 2 || FPT->isVariadic()) + if (FPT->getNumParams() == 0 || FPT->getNumParams() > 2 || FPT->isVariadic()) return false; // If this is a single-parameter function, it must be a replaceable global // allocation or deallocation function. - if (FPT->getNumArgs() == 1) + if (FPT->getNumParams() == 1) return true; // Otherwise, we're looking for a second parameter whose type is // 'const std::nothrow_t &', or, in C++1y, 'std::size_t'. - QualType Ty = FPT->getArgType(1); + QualType Ty = FPT->getParamType(1); ASTContext &Ctx = getASTContext(); if (Ctx.getLangOpts().SizedDeallocation && Ctx.hasSameType(Ty, Ctx.getSizeType())) @@ -2358,30 +2432,31 @@ bool FunctionDecl::isReplaceableGlobalAllocationFunction() const { Ty = Ty->getPointeeType(); if (Ty.getCVRQualifiers() != Qualifiers::Const) return false; - // FIXME: Recognise nothrow_t in an inline namespace inside std? const CXXRecordDecl *RD = Ty->getAsCXXRecordDecl(); - return RD && isNamed(RD, "nothrow_t") && isNamespaceStd(RD->getDeclContext()); + return RD && isNamed(RD, "nothrow_t") && RD->isInStdNamespace(); } FunctionDecl * FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { ASTContext &Ctx = getASTContext(); if (!Ctx.getLangOpts().SizedDeallocation) - return 0; + return nullptr; if (getDeclName().getNameKind() != DeclarationName::CXXOperatorName) - return 0; + return nullptr; if (getDeclName().getCXXOverloadedOperator() != OO_Delete && getDeclName().getCXXOverloadedOperator() != OO_Array_Delete) - return 0; + return nullptr; if (isa<CXXRecordDecl>(getDeclContext())) - return 0; - assert(getDeclContext()->getRedeclContext()->isTranslationUnit()); + return nullptr; + + if (!getDeclContext()->getRedeclContext()->isTranslationUnit()) + return nullptr; if (getNumParams() != 2 || isVariadic() || - !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getArgType(1), + !Ctx.hasSameType(getType()->castAs<FunctionProtoType>()->getParamType(1), Ctx.getSizeType())) - return 0; + return nullptr; // This is a sized deallocation function. Find the corresponding unsized // deallocation function. @@ -2391,15 +2466,15 @@ FunctionDecl::getCorrespondingUnsizedGlobalDeallocationFunction() const { if (FunctionDecl *FD = dyn_cast<FunctionDecl>(*RI)) if (FD->getNumParams() == 1 && !FD->isVariadic()) return FD; - return 0; + return nullptr; } LanguageLinkage FunctionDecl::getLanguageLinkage() const { - return getLanguageLinkageTemplate(*this); + return getDeclLanguageLinkage(*this); } bool FunctionDecl::isExternC() const { - return isExternCTemplate(*this); + return isDeclExternC(*this); } bool FunctionDecl::isInExternCContext() const { @@ -2442,7 +2517,7 @@ FunctionDecl::setPreviousDeclaration(FunctionDecl *PrevDecl) { if (FunctionTemplateDecl *FunTmpl = getDescribedFunctionTemplate()) { FunctionTemplateDecl *PrevFunTmpl - = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : 0; + = PrevDecl? PrevDecl->getDescribedFunctionTemplate() : nullptr; assert((!PrevDecl || PrevFunTmpl) && "Function/function template mismatch"); FunTmpl->setPreviousDecl(PrevFunTmpl); } @@ -2488,7 +2563,7 @@ unsigned FunctionDecl::getBuiltinID() const { // If the function is marked "overloadable", it has a different mangled name // and is not the C library function. - if (getAttr<OverloadableAttr>()) + if (hasAttr<OverloadableAttr>()) return 0; if (!Context.BuiltinInfo.isPredefinedLibFunction(BuiltinID)) @@ -2510,16 +2585,13 @@ unsigned FunctionDecl::getBuiltinID() const { /// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. unsigned FunctionDecl::getNumParams() const { - const FunctionType *FT = getType()->castAs<FunctionType>(); - if (isa<FunctionNoProtoType>(FT)) - return 0; - return cast<FunctionProtoType>(FT)->getNumArgs(); - + const FunctionProtoType *FPT = getType()->getAs<FunctionProtoType>(); + return FPT ? FPT->getNumParams() : 0; } void FunctionDecl::setParams(ASTContext &C, ArrayRef<ParmVarDecl *> NewParamInfo) { - assert(ParamInfo == 0 && "Already has param info!"); + assert(!ParamInfo && "Already has param info!"); assert(NewParamInfo.size() == getNumParams() && "Parameter count mismatch!"); // Zero params -> null pointer. @@ -2536,44 +2608,67 @@ void FunctionDecl::setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls) { NamedDecl **A = new (getASTContext()) NamedDecl*[NewDecls.size()]; std::copy(NewDecls.begin(), NewDecls.end(), A); DeclsInPrototypeScope = ArrayRef<NamedDecl *>(A, NewDecls.size()); + // Move declarations introduced in prototype to the function context. + for (auto I : NewDecls) { + DeclContext *DC = I->getDeclContext(); + // Forward-declared reference to an enumeration is not added to + // declaration scope, so skip declaration that is absent from its + // declaration contexts. + if (DC->containsDecl(I)) { + DC->removeDecl(I); + I->setDeclContext(this); + addDecl(I); + } + } } } /// getMinRequiredArguments - Returns the minimum number of arguments /// needed to call this function. This may be fewer than the number of /// function parameters, if some of the parameters have default -/// arguments (in C++) or the last parameter is a parameter pack. +/// arguments (in C++) or are parameter packs (C++11). unsigned FunctionDecl::getMinRequiredArguments() const { if (!getASTContext().getLangOpts().CPlusPlus) return getNumParams(); - - unsigned NumRequiredArgs = getNumParams(); - - // If the last parameter is a parameter pack, we don't need an argument for - // it. - if (NumRequiredArgs > 0 && - getParamDecl(NumRequiredArgs - 1)->isParameterPack()) - --NumRequiredArgs; - - // If this parameter has a default argument, we don't need an argument for - // it. - while (NumRequiredArgs > 0 && - getParamDecl(NumRequiredArgs-1)->hasDefaultArg()) - --NumRequiredArgs; - - // We might have parameter packs before the end. These can't be deduced, - // but they can still handle multiple arguments. - unsigned ArgIdx = NumRequiredArgs; - while (ArgIdx > 0) { - if (getParamDecl(ArgIdx - 1)->isParameterPack()) - NumRequiredArgs = ArgIdx; - - --ArgIdx; - } - + + unsigned NumRequiredArgs = 0; + for (auto *Param : params()) + if (!Param->isParameterPack() && !Param->hasDefaultArg()) + ++NumRequiredArgs; return NumRequiredArgs; } +/// \brief The combination of the extern and inline keywords under MSVC forces +/// the function to be required. +/// +/// Note: This function assumes that we will only get called when isInlined() +/// would return true for this FunctionDecl. +bool FunctionDecl::isMSExternInline() const { + assert(isInlined() && "expected to get called on an inlined function!"); + + const ASTContext &Context = getASTContext(); + if (!Context.getLangOpts().MSVCCompat && !hasAttr<DLLExportAttr>()) + return false; + + for (const FunctionDecl *FD = this; FD; FD = FD->getPreviousDecl()) + if (FD->getStorageClass() == SC_Extern) + return true; + + return false; +} + +static bool redeclForcesDefMSVC(const FunctionDecl *Redecl) { + if (Redecl->getStorageClass() != SC_Extern) + return false; + + for (const FunctionDecl *FD = Redecl->getPreviousDecl(); FD; + FD = FD->getPreviousDecl()) + if (FD->getStorageClass() == SC_Extern) + return false; + + return true; +} + static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { // Only consider file-scope declarations in this test. if (!Redecl->getLexicalDeclContext()->isTranslationUnit()) @@ -2593,7 +2688,7 @@ static bool RedeclForcesDefC99(const FunctionDecl *Redecl) { /// \brief For a function declaration in C or C++, determine whether this /// declaration causes the definition to be externally visible. /// -/// Specifically, this determines if adding the current declaration to the set +/// For instance, this determines if adding the current declaration to the set /// of redeclarations of the given functions causes /// isInlineDefinitionExternallyVisible to change from false to true. bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { @@ -2602,6 +2697,13 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { ASTContext &Context = getASTContext(); + if (Context.getLangOpts().MSVCCompat) { + const FunctionDecl *Definition; + if (hasBody(Definition) && Definition->isInlined() && + redeclForcesDefMSVC(this)) + return true; + } + if (Context.getLangOpts().GNUInline || hasAttr<GNUInlineAttr>()) { // With GNU inlining, a declaration with 'inline' but not 'extern', forces // an externally visible definition. @@ -2649,6 +2751,26 @@ bool FunctionDecl::doesDeclarationForceExternallyVisibleDefinition() const { return FoundBody; } +SourceRange FunctionDecl::getReturnTypeSourceRange() const { + const TypeSourceInfo *TSI = getTypeSourceInfo(); + if (!TSI) + return SourceRange(); + FunctionTypeLoc FTL = + TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>(); + if (!FTL) + return SourceRange(); + + // Skip self-referential return types. + const SourceManager &SM = getASTContext().getSourceManager(); + SourceRange RTRange = FTL.getReturnLoc().getSourceRange(); + SourceLocation Boundary = getNameInfo().getLocStart(); + if (RTRange.isInvalid() || Boundary.isInvalid() || + !SM.isBeforeInTranslationUnit(RTRange.getEnd(), Boundary)) + return SourceRange(); + + return RTRange; +} + /// \brief For an inline function definition in C, or for a gnu_inline function /// in C++, determine whether the definition will be externally visible. /// @@ -2683,9 +2805,7 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // If any declaration is 'inline' but not 'extern', then this definition // is externally visible. - for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); - Redecl != RedeclEnd; - ++Redecl) { + for (auto Redecl : redecls()) { if (Redecl->isInlineSpecified() && Redecl->getStorageClass() != SC_Extern) return true; @@ -2702,10 +2822,8 @@ bool FunctionDecl::isInlineDefinitionExternallyVisible() const { // [...] If all of the file scope declarations for a function in a // translation unit include the inline function specifier without extern, // then the definition in that translation unit is an inline definition. - for (redecl_iterator Redecl = redecls_begin(), RedeclEnd = redecls_end(); - Redecl != RedeclEnd; - ++Redecl) { - if (RedeclForcesDefC99(*Redecl)) + for (auto Redecl : redecls()) { + if (RedeclForcesDefC99(Redecl)) return true; } @@ -2731,7 +2849,7 @@ const IdentifierInfo *FunctionDecl::getLiteralIdentifier() const { if (getDeclName().getNameKind() == DeclarationName::CXXLiteralOperatorName) return getDeclName().getCXXLiteralIdentifier(); else - return 0; + return nullptr; } FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { @@ -2753,8 +2871,8 @@ FunctionDecl::TemplatedKind FunctionDecl::getTemplatedKind() const { FunctionDecl *FunctionDecl::getInstantiatedFromMemberFunction() const { if (MemberSpecializationInfo *Info = getMemberSpecializationInfo()) return cast<FunctionDecl>(Info->getInstantiatedFrom()); - - return 0; + + return nullptr; } void @@ -2784,7 +2902,7 @@ bool FunctionDecl::isImplicitlyInstantiable() const { // It is possible to instantiate TSK_ExplicitSpecialization kind // if the FunctionDecl has a class scope specialization pattern. case TSK_ExplicitSpecialization: - return getClassScopeSpecializationPattern() != 0; + return getClassScopeSpecializationPattern() != nullptr; case TSK_ExplicitInstantiationDeclaration: // Handled below. @@ -2824,14 +2942,34 @@ FunctionDecl *FunctionDecl::getTemplateInstantiationPattern() const { // Handle class scope explicit specialization special case. if (getTemplateSpecializationKind() == TSK_ExplicitSpecialization) return getClassScopeSpecializationPattern(); - + + // If this is a generic lambda call operator specialization, its + // instantiation pattern is always its primary template's pattern + // even if its primary template was instantiated from another + // member template (which happens with nested generic lambdas). + // Since a lambda's call operator's body is transformed eagerly, + // we don't have to go hunting for a prototype definition template + // (i.e. instantiated-from-member-template) to use as an instantiation + // pattern. + + if (isGenericLambdaCallOperatorSpecialization( + dyn_cast<CXXMethodDecl>(this))) { + assert(getPrimaryTemplate() && "A generic lambda specialization must be " + "generated from a primary call operator " + "template"); + assert(getPrimaryTemplate()->getTemplatedDecl()->getBody() && + "A generic lambda call operator template must always have a body - " + "even if instantiated from a prototype (i.e. as written) member " + "template"); + return getPrimaryTemplate()->getTemplatedDecl(); + } + if (FunctionTemplateDecl *Primary = getPrimaryTemplate()) { while (Primary->getInstantiatedFromMemberTemplate()) { // If we have hit a point where the user provided a specialization of // this template, we're done looking. if (Primary->isMemberSpecialization()) break; - Primary = Primary->getInstantiatedFromMemberTemplate(); } @@ -2847,7 +2985,7 @@ FunctionTemplateDecl *FunctionDecl::getPrimaryTemplate() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->Template.getPointer(); } - return 0; + return nullptr; } FunctionDecl *FunctionDecl::getClassScopeSpecializationPattern() const { @@ -2861,7 +2999,7 @@ FunctionDecl::getTemplateSpecializationArgs() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArguments; } - return 0; + return nullptr; } const ASTTemplateArgumentListInfo * @@ -2871,7 +3009,7 @@ FunctionDecl::getTemplateSpecializationArgsAsWritten() const { .dyn_cast<FunctionTemplateSpecializationInfo*>()) { return Info->TemplateArgumentsAsWritten; } - return 0; + return nullptr; } void @@ -3101,14 +3239,14 @@ FieldDecl *FieldDecl::Create(const ASTContext &C, DeclContext *DC, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, Expr *BW, bool Mutable, InClassInitStyle InitStyle) { - return new (C) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, - BW, Mutable, InitStyle); + return new (C, DC) FieldDecl(Decl::Field, DC, StartLoc, IdLoc, Id, T, TInfo, + BW, Mutable, InitStyle); } FieldDecl *FieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FieldDecl)); - return new (Mem) FieldDecl(Field, 0, SourceLocation(), SourceLocation(), - 0, QualType(), 0, 0, false, ICIS_NoInit); + return new (C, ID) FieldDecl(Field, nullptr, SourceLocation(), + SourceLocation(), nullptr, QualType(), nullptr, + nullptr, false, ICIS_NoInit); } bool FieldDecl::isAnonymousStructOrUnion() const { @@ -3180,8 +3318,10 @@ TagDecl *TagDecl::getCanonicalDecl() { return getFirstDecl(); } void TagDecl::setTypedefNameForAnonDecl(TypedefNameDecl *TDD) { NamedDeclOrQualifier = TDD; - if (TypeForDecl) - assert(TypeForDecl->isLinkageValid()); + if (const Type *T = getTypeForDecl()) { + (void)T; + assert(T->isLinkageValid()); + } assert(isLinkageValid()); } @@ -3189,10 +3329,10 @@ void TagDecl::startDefinition() { IsBeingDefined = true; if (CXXRecordDecl *D = dyn_cast<CXXRecordDecl>(this)) { - struct CXXRecordDecl::DefinitionData *Data = + struct CXXRecordDecl::DefinitionData *Data = new (getASTContext()) struct CXXRecordDecl::DefinitionData(D); - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) - cast<CXXRecordDecl>(*I)->DefinitionData = Data; + for (auto I : redecls()) + cast<CXXRecordDecl>(I)->DefinitionData = Data; } } @@ -3224,12 +3364,11 @@ TagDecl *TagDecl::getDefinition() const { if (const CXXRecordDecl *CXXRD = dyn_cast<CXXRecordDecl>(this)) return CXXRD->getDefinition(); - for (redecl_iterator R = redecls_begin(), REnd = redecls_end(); - R != REnd; ++R) + for (auto R : redecls()) if (R->isCompleteDefinition()) - return *R; + return R; - return 0; + return nullptr; } void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { @@ -3244,7 +3383,7 @@ void TagDecl::setQualifierInfo(NestedNameSpecifierLoc QualifierLoc) { if (hasExtInfo()) { if (getExtInfo()->NumTemplParamLists == 0) { getASTContext().Deallocate(getExtInfo()); - NamedDeclOrQualifier = (TypedefNameDecl*) 0; + NamedDeclOrQualifier = (TypedefNameDecl*)nullptr; } else getExtInfo()->QualifierLoc = QualifierLoc; @@ -3275,21 +3414,28 @@ EnumDecl *EnumDecl::Create(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, EnumDecl *PrevDecl, bool IsScoped, bool IsScopedUsingClassTag, bool IsFixed) { - EnumDecl *Enum = new (C) EnumDecl(DC, StartLoc, IdLoc, Id, PrevDecl, - IsScoped, IsScopedUsingClassTag, IsFixed); + EnumDecl *Enum = new (C, DC) EnumDecl(C, DC, StartLoc, IdLoc, Id, PrevDecl, + IsScoped, IsScopedUsingClassTag, + IsFixed); Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; C.getTypeDeclType(Enum, PrevDecl); return Enum; } EnumDecl *EnumDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumDecl)); - EnumDecl *Enum = new (Mem) EnumDecl(0, SourceLocation(), SourceLocation(), - 0, 0, false, false, false); + EnumDecl *Enum = + new (C, ID) EnumDecl(C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr, false, false, false); Enum->MayHaveOutOfDateDef = C.getLangOpts().Modules; return Enum; } +SourceRange EnumDecl::getIntegerTypeRange() const { + if (const TypeSourceInfo *TI = getIntegerTypeSourceInfo()) + return TI->getTypeLoc().getSourceRange(); + return SourceRange(); +} + void EnumDecl::completeDefinition(QualType NewType, QualType NewPromotionType, unsigned NumPositiveBits, @@ -3325,7 +3471,7 @@ EnumDecl *EnumDecl::getInstantiatedFromMemberEnum() const { if (SpecializationInfo) return cast<EnumDecl>(SpecializationInfo->getInstantiatedFrom()); - return 0; + return nullptr; } void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, @@ -3338,10 +3484,11 @@ void EnumDecl::setInstantiationOfMemberEnum(ASTContext &C, EnumDecl *ED, // RecordDecl Implementation //===----------------------------------------------------------------------===// -RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, RecordDecl *PrevDecl) - : TagDecl(DK, TK, DC, IdLoc, Id, PrevDecl, StartLoc) { +RecordDecl::RecordDecl(Kind DK, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + RecordDecl *PrevDecl) + : TagDecl(DK, TK, C, DC, IdLoc, Id, PrevDecl, StartLoc) { HasFlexibleArrayMember = false; AnonymousStructOrUnion = false; HasObjectMember = false; @@ -3353,8 +3500,8 @@ RecordDecl::RecordDecl(Kind DK, TagKind TK, DeclContext *DC, RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, RecordDecl* PrevDecl) { - RecordDecl* R = new (C) RecordDecl(Record, TK, DC, StartLoc, IdLoc, Id, - PrevDecl); + RecordDecl *R = new (C, DC) RecordDecl(Record, TK, C, DC, + StartLoc, IdLoc, Id, PrevDecl); R->MayHaveOutOfDateDef = C.getLangOpts().Modules; C.getTypeDeclType(R, PrevDecl); @@ -3362,9 +3509,9 @@ RecordDecl *RecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, } RecordDecl *RecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(RecordDecl)); - RecordDecl *R = new (Mem) RecordDecl(Record, TTK_Struct, 0, SourceLocation(), - SourceLocation(), 0, 0); + RecordDecl *R = + new (C, ID) RecordDecl(Record, TTK_Struct, C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); R->MayHaveOutOfDateDef = C.getLangOpts().Modules; return R; } @@ -3427,7 +3574,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { if (Decls.empty()) return; - llvm::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, + std::tie(FirstDecl, LastDecl) = BuildDeclChain(Decls, /*FieldsAlreadyLoaded=*/false); } @@ -3436,7 +3583,7 @@ void RecordDecl::LoadFieldsFromExternalStorage() const { //===----------------------------------------------------------------------===// void BlockDecl::setParams(ArrayRef<ParmVarDecl *> NewParamInfo) { - assert(ParamInfo == 0 && "Already has param info!"); + assert(!ParamInfo && "Already has param info!"); // Zero params -> null pointer. if (!NewParamInfo.empty()) { @@ -3454,7 +3601,7 @@ void BlockDecl::setCaptures(ASTContext &Context, if (begin == end) { NumCaptures = 0; - Captures = 0; + Captures = nullptr; return; } @@ -3469,10 +3616,9 @@ void BlockDecl::setCaptures(ASTContext &Context, } bool BlockDecl::capturesVariable(const VarDecl *variable) const { - for (capture_const_iterator - i = capture_begin(), e = capture_end(); i != e; ++i) + for (const auto &I : captures()) // Only auto vars can be captured, so no redeclaration worries. - if (i->getVariable() == variable) + if (I.getVariable() == variable) return true; return false; @@ -3489,33 +3635,33 @@ SourceRange BlockDecl::getSourceRange() const { void TranslationUnitDecl::anchor() { } TranslationUnitDecl *TranslationUnitDecl::Create(ASTContext &C) { - return new (C) TranslationUnitDecl(C); + return new (C, (DeclContext *)nullptr) TranslationUnitDecl(C); } void LabelDecl::anchor() { } LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II) { - return new (C) LabelDecl(DC, IdentL, II, 0, IdentL); + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, IdentL); } LabelDecl *LabelDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, SourceLocation GnuLabelL) { assert(GnuLabelL != IdentL && "Use this only for GNU local labels"); - return new (C) LabelDecl(DC, IdentL, II, 0, GnuLabelL); + return new (C, DC) LabelDecl(DC, IdentL, II, nullptr, GnuLabelL); } LabelDecl *LabelDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(LabelDecl)); - return new (Mem) LabelDecl(0, SourceLocation(), 0, 0, SourceLocation()); + return new (C, ID) LabelDecl(nullptr, SourceLocation(), nullptr, nullptr, + SourceLocation()); } void ValueDecl::anchor() { } bool ValueDecl::isWeak() const { - for (attr_iterator I = attr_begin(), E = attr_end(); I != E; ++I) - if (isa<WeakAttr>(*I) || isa<WeakRefAttr>(*I)) + for (const auto *I : attrs()) + if (isa<WeakAttr>(I) || isa<WeakRefAttr>(I)) return true; return isWeakImported(); @@ -3527,13 +3673,13 @@ ImplicitParamDecl *ImplicitParamDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation IdLoc, IdentifierInfo *Id, QualType Type) { - return new (C) ImplicitParamDecl(DC, IdLoc, Id, Type); + return new (C, DC) ImplicitParamDecl(C, DC, IdLoc, Id, Type); } -ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, +ImplicitParamDecl *ImplicitParamDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(ImplicitParamDecl)); - return new (Mem) ImplicitParamDecl(0, SourceLocation(), 0, QualType()); + return new (C, ID) ImplicitParamDecl(C, nullptr, SourceLocation(), nullptr, + QualType()); } FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, @@ -3541,66 +3687,53 @@ FunctionDecl *FunctionDecl::Create(ASTContext &C, DeclContext *DC, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, StorageClass SC, - bool isInlineSpecified, + bool isInlineSpecified, bool hasWrittenPrototype, bool isConstexprSpecified) { - FunctionDecl *New = new (C) FunctionDecl(Function, DC, StartLoc, NameInfo, - T, TInfo, SC, - isInlineSpecified, - isConstexprSpecified); + FunctionDecl *New = + new (C, DC) FunctionDecl(Function, C, DC, StartLoc, NameInfo, T, TInfo, + SC, isInlineSpecified, isConstexprSpecified); New->HasWrittenPrototype = hasWrittenPrototype; return New; } FunctionDecl *FunctionDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FunctionDecl)); - return new (Mem) FunctionDecl(Function, 0, SourceLocation(), - DeclarationNameInfo(), QualType(), 0, - SC_None, false, false); + return new (C, ID) FunctionDecl(Function, C, nullptr, SourceLocation(), + DeclarationNameInfo(), QualType(), nullptr, + SC_None, false, false); } BlockDecl *BlockDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { - return new (C) BlockDecl(DC, L); + return new (C, DC) BlockDecl(DC, L); } BlockDecl *BlockDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(BlockDecl)); - return new (Mem) BlockDecl(0, SourceLocation()); -} - -MSPropertyDecl *MSPropertyDecl::CreateDeserialized(ASTContext &C, - unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(MSPropertyDecl)); - return new (Mem) MSPropertyDecl(0, SourceLocation(), DeclarationName(), - QualType(), 0, SourceLocation(), - 0, 0); + return new (C, ID) BlockDecl(nullptr, SourceLocation()); } CapturedDecl *CapturedDecl::Create(ASTContext &C, DeclContext *DC, unsigned NumParams) { - unsigned Size = sizeof(CapturedDecl) + NumParams * sizeof(ImplicitParamDecl*); - return new (C.Allocate(Size)) CapturedDecl(DC, NumParams); + return new (C, DC, NumParams * sizeof(ImplicitParamDecl *)) + CapturedDecl(DC, NumParams); } CapturedDecl *CapturedDecl::CreateDeserialized(ASTContext &C, unsigned ID, - unsigned NumParams) { - unsigned Size = sizeof(CapturedDecl) + NumParams * sizeof(ImplicitParamDecl*); - void *Mem = AllocateDeserializedDecl(C, ID, Size); - return new (Mem) CapturedDecl(0, NumParams); + unsigned NumParams) { + return new (C, ID, NumParams * sizeof(ImplicitParamDecl *)) + CapturedDecl(nullptr, NumParams); } EnumConstantDecl *EnumConstantDecl::Create(ASTContext &C, EnumDecl *CD, SourceLocation L, IdentifierInfo *Id, QualType T, Expr *E, const llvm::APSInt &V) { - return new (C) EnumConstantDecl(CD, L, Id, T, E, V); + return new (C, CD) EnumConstantDecl(CD, L, Id, T, E, V); } EnumConstantDecl * EnumConstantDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EnumConstantDecl)); - return new (Mem) EnumConstantDecl(0, SourceLocation(), 0, QualType(), 0, - llvm::APSInt()); + return new (C, ID) EnumConstantDecl(nullptr, SourceLocation(), nullptr, + QualType(), nullptr, llvm::APSInt()); } void IndirectFieldDecl::anchor() { } @@ -3609,14 +3742,14 @@ IndirectFieldDecl * IndirectFieldDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, QualType T, NamedDecl **CH, unsigned CHS) { - return new (C) IndirectFieldDecl(DC, L, Id, T, CH, CHS); + return new (C, DC) IndirectFieldDecl(DC, L, Id, T, CH, CHS); } IndirectFieldDecl *IndirectFieldDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(IndirectFieldDecl)); - return new (Mem) IndirectFieldDecl(0, SourceLocation(), DeclarationName(), - QualType(), 0, 0); + return new (C, ID) IndirectFieldDecl(nullptr, SourceLocation(), + DeclarationName(), QualType(), nullptr, + 0); } SourceRange EnumConstantDecl::getSourceRange() const { @@ -3631,26 +3764,26 @@ void TypeDecl::anchor() { } TypedefDecl *TypedefDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) { - return new (C) TypedefDecl(DC, StartLoc, IdLoc, Id, TInfo); + return new (C, DC) TypedefDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } void TypedefNameDecl::anchor() { } TypedefDecl *TypedefDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypedefDecl)); - return new (Mem) TypedefDecl(0, SourceLocation(), SourceLocation(), 0, 0); + return new (C, ID) TypedefDecl(C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr); } TypeAliasDecl *TypeAliasDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) { - return new (C) TypeAliasDecl(DC, StartLoc, IdLoc, Id, TInfo); + return new (C, DC) TypeAliasDecl(C, DC, StartLoc, IdLoc, Id, TInfo); } TypeAliasDecl *TypeAliasDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(TypeAliasDecl)); - return new (Mem) TypeAliasDecl(0, SourceLocation(), SourceLocation(), 0, 0); + return new (C, ID) TypeAliasDecl(C, nullptr, SourceLocation(), + SourceLocation(), nullptr, nullptr); } SourceRange TypedefDecl::getSourceRange() const { @@ -3675,24 +3808,23 @@ FileScopeAsmDecl *FileScopeAsmDecl::Create(ASTContext &C, DeclContext *DC, StringLiteral *Str, SourceLocation AsmLoc, SourceLocation RParenLoc) { - return new (C) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); + return new (C, DC) FileScopeAsmDecl(DC, Str, AsmLoc, RParenLoc); } -FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, +FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(FileScopeAsmDecl)); - return new (Mem) FileScopeAsmDecl(0, 0, SourceLocation(), SourceLocation()); + return new (C, ID) FileScopeAsmDecl(nullptr, nullptr, SourceLocation(), + SourceLocation()); } void EmptyDecl::anchor() {} EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { - return new (C) EmptyDecl(DC, L); + return new (C, DC) EmptyDecl(DC, L); } EmptyDecl *EmptyDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(EmptyDecl)); - return new (Mem) EmptyDecl(0, SourceLocation()); + return new (C, ID) EmptyDecl(nullptr, SourceLocation()); } //===----------------------------------------------------------------------===// @@ -3730,30 +3862,28 @@ ImportDecl::ImportDecl(DeclContext *DC, SourceLocation StartLoc, *reinterpret_cast<SourceLocation *>(this + 1) = EndLoc; } -ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, +ImportDecl *ImportDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs) { - void *Mem = C.Allocate(sizeof(ImportDecl) + - IdentifierLocs.size() * sizeof(SourceLocation)); - return new (Mem) ImportDecl(DC, StartLoc, Imported, IdentifierLocs); + return new (C, DC, IdentifierLocs.size() * sizeof(SourceLocation)) + ImportDecl(DC, StartLoc, Imported, IdentifierLocs); } -ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, +ImportDecl *ImportDecl::CreateImplicit(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, - Module *Imported, + Module *Imported, SourceLocation EndLoc) { - void *Mem = C.Allocate(sizeof(ImportDecl) + sizeof(SourceLocation)); - ImportDecl *Import = new (Mem) ImportDecl(DC, StartLoc, Imported, EndLoc); + ImportDecl *Import = + new (C, DC, sizeof(SourceLocation)) ImportDecl(DC, StartLoc, + Imported, EndLoc); Import->setImplicit(); return Import; } ImportDecl *ImportDecl::CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumLocations) { - void *Mem = AllocateDeserializedDecl(C, ID, - (sizeof(ImportDecl) + - NumLocations * sizeof(SourceLocation))); - return new (Mem) ImportDecl(EmptyShell()); + return new (C, ID, NumLocations * sizeof(SourceLocation)) + ImportDecl(EmptyShell()); } ArrayRef<SourceLocation> ImportDecl::getIdentifierLocs() const { diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 121c5a671a29..2b1506d191d1 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -45,25 +45,30 @@ void Decl::updateOutOfDate(IdentifierInfo &II) const { getASTContext().getExternalSource()->updateOutOfDateIdentifier(II); } -void *Decl::AllocateDeserializedDecl(const ASTContext &Context, - unsigned ID, - unsigned Size) { +void *Decl::operator new(std::size_t Size, const ASTContext &Context, + unsigned ID, std::size_t Extra) { // Allocate an extra 8 bytes worth of storage, which ensures that the // resulting pointer will still be 8-byte aligned. - void *Start = Context.Allocate(Size + 8); + void *Start = Context.Allocate(Size + Extra + 8); void *Result = (char*)Start + 8; - + unsigned *PrefixPtr = (unsigned *)Result - 2; - + // Zero out the first 4 bytes; this is used to store the owning module ID. PrefixPtr[0] = 0; - + // Store the global declaration ID in the second 4 bytes. PrefixPtr[1] = ID; - + return Result; } +void *Decl::operator new(std::size_t Size, const ASTContext &Ctx, + DeclContext *Parent, std::size_t Extra) { + assert(!Parent || &Parent->getParentASTContext() == &Ctx); + return ::operator new(Size + Extra, Ctx); +} + Module *Decl::getOwningModuleSlow() const { assert(isFromASTFile() && "Not from AST file?"); return getASTContext().getExternalSource()->getModule(getOwningModuleID()); @@ -80,6 +85,7 @@ const char *Decl::getDeclKindName() const { void Decl::setInvalidDecl(bool Invalid) { InvalidDecl = Invalid; + assert(!isa<TagDecl>(this) || !cast<TagDecl>(this)->isCompleteDefinition()); if (Invalid && !isa<ParmVarDecl>(this)) { // Defensive maneuver for ill-formed code: we're likely not to make it to // a point where we set the access specifier, so default it to "public" @@ -153,11 +159,12 @@ bool Decl::isParameterPack() const { return isTemplateParameterPack(); } -bool Decl::isFunctionOrFunctionTemplate() const { - if (const UsingShadowDecl *UD = dyn_cast<UsingShadowDecl>(this)) - return UD->getTargetDecl()->isFunctionOrFunctionTemplate(); - - return isa<FunctionDecl>(this) || isa<FunctionTemplateDecl>(this); +FunctionDecl *Decl::getAsFunction() { + if (FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) + return FD; + if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(this)) + return FTD->getTemplatedDecl(); + return nullptr; } bool Decl::isTemplateDecl() const { @@ -171,7 +178,7 @@ const DeclContext *Decl::getParentFunctionOrMethod() const { if (DC->isFunctionOrMethod()) return DC; - return 0; + return nullptr; } @@ -244,6 +251,10 @@ bool Decl::isInAnonymousNamespace() const { return false; } +bool Decl::isInStdNamespace() const { + return getDeclContext()->isStdNamespace(); +} + TranslationUnitDecl *Decl::getTranslationUnitDecl() { if (TranslationUnitDecl *TUD = dyn_cast<TranslationUnitDecl>(this)) return TUD; @@ -306,7 +317,7 @@ bool Decl::isReferenced() const { return true; // Check redeclarations. - for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) + for (auto I : redecls()) if (I->Referenced) return true; @@ -401,8 +412,8 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const { AvailabilityResult Result = AR_Available; std::string ResultMessage; - for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) { - if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) { + for (const auto *A : attrs()) { + if (const auto *Deprecated = dyn_cast<DeprecatedAttr>(A)) { if (Result >= AR_Deprecated) continue; @@ -413,13 +424,13 @@ AvailabilityResult Decl::getAvailability(std::string *Message) const { continue; } - if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) { + if (const auto *Unavailable = dyn_cast<UnavailableAttr>(A)) { if (Message) *Message = Unavailable->getMessage(); return AR_Unavailable; } - if (AvailabilityAttr *Availability = dyn_cast<AvailabilityAttr>(*A)) { + if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { AvailabilityResult AR = CheckAvailability(getASTContext(), Availability, Message); @@ -475,13 +486,13 @@ bool Decl::isWeakImported() const { if (!canBeWeakImported(IsDefinition)) return false; - for (attr_iterator A = attr_begin(), AEnd = attr_end(); A != AEnd; ++A) { - if (isa<WeakImportAttr>(*A)) + for (const auto *A : attrs()) { + if (isa<WeakImportAttr>(A)) return true; - if (AvailabilityAttr *Availability = dyn_cast<AvailabilityAttr>(*A)) { - if (CheckAvailability(getASTContext(), Availability, 0) - == AR_NotYetIntroduced) + if (const auto *Availability = dyn_cast<AvailabilityAttr>(A)) { + if (CheckAvailability(getASTContext(), Availability, + nullptr) == AR_NotYetIntroduced) return true; } } @@ -662,7 +673,7 @@ SourceLocation Decl::getBodyRBrace() const { return SourceLocation(); } -void Decl::CheckAccessDeclContext() const { +bool Decl::AccessDeclContextSanity() const { #ifndef NDEBUG // Suppress this check if any of the following hold: // 1. this is the translation unit (and thus has no parent) @@ -684,16 +695,35 @@ void Decl::CheckAccessDeclContext() const { // AS_none as access specifier. isa<CXXRecordDecl>(this) || isa<ClassScopeFunctionSpecializationDecl>(this)) - return; + return true; assert(Access != AS_none && "Access specifier is AS_none inside a record decl"); #endif + return true; } static Decl::Kind getKind(const Decl *D) { return D->getKind(); } static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } +const FunctionType *Decl::getFunctionType(bool BlocksToo) const { + QualType Ty; + if (const ValueDecl *D = dyn_cast<ValueDecl>(this)) + Ty = D->getType(); + else if (const TypedefNameDecl *D = dyn_cast<TypedefNameDecl>(this)) + Ty = D->getUnderlyingType(); + else + return nullptr; + + if (Ty->isFunctionPointerType()) + Ty = Ty->getAs<PointerType>()->getPointeeType(); + else if (BlocksToo && Ty->isBlockPointerType()) + Ty = Ty->getAs<BlockPointerType>()->getPointeeType(); + + return Ty->getAs<FunctionType>(); +} + + /// Starting at a given context (a Decl or DeclContext), look for a /// code context that is not a closure (a lambda, block, etc.). template <class T> static Decl *getNonClosureContext(T *D) { @@ -712,7 +742,7 @@ template <class T> static Decl *getNonClosureContext(T *D) { } else if (CapturedDecl *CD = dyn_cast<CapturedDecl>(D)) { return getNonClosureContext(CD->getParent()); } else { - return 0; + return nullptr; } } @@ -769,6 +799,22 @@ bool DeclContext::isInlineNamespace() const { cast<NamespaceDecl>(this)->isInline(); } +bool DeclContext::isStdNamespace() const { + if (!isNamespace()) + return false; + + const NamespaceDecl *ND = cast<NamespaceDecl>(this); + if (ND->isInline()) { + return ND->getParent()->isStdNamespace(); + } + + if (!getParent()->getRedeclContext()->isTranslationUnit()) + return false; + + const IdentifierInfo *II = ND->getIdentifier(); + return II && II->isStr("std"); +} + bool DeclContext::isDependentContext() const { if (isFileContext()) return false; @@ -811,7 +857,7 @@ static bool isLinkageSpecContext(const DeclContext *DC, while (DC->getDeclKind() != Decl::TranslationUnit) { if (DC->getDeclKind() == Decl::LinkageSpec) return cast<LinkageSpecDecl>(DC)->getLanguage() == ID; - DC = DC->getParent(); + DC = DC->getLexicalParent(); } return false; } @@ -874,18 +920,17 @@ DeclContext *DeclContext::getPrimaryContext() { // If this is a tag type that has a definition or is currently // being defined, that definition is our primary context. TagDecl *Tag = cast<TagDecl>(this); - assert(isa<TagType>(Tag->TypeForDecl) || - isa<InjectedClassNameType>(Tag->TypeForDecl)); if (TagDecl *Def = Tag->getDefinition()) return Def; - if (!isa<InjectedClassNameType>(Tag->TypeForDecl)) { - const TagType *TagTy = cast<TagType>(Tag->TypeForDecl); - if (TagTy->isBeingDefined()) - // FIXME: is it necessarily being defined in the decl - // that owns the type? - return TagTy->getDecl(); + if (const TagType *TagTy = dyn_cast<TagType>(Tag->getTypeForDecl())) { + // Note, TagType::getDecl returns the (partial) definition one exists. + TagDecl *PossiblePartialDef = TagTy->getDecl(); + if (PossiblePartialDef->isBeingDefined()) + return PossiblePartialDef; + } else { + assert(isa<InjectedClassNameType>(Tag->getTypeForDecl())); } return Tag; @@ -918,8 +963,8 @@ std::pair<Decl *, Decl *> DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, bool FieldsAlreadyLoaded) { // Build up a chain of declarations via the Decl::NextInContextAndBits field. - Decl *FirstNewDecl = 0; - Decl *PrevDecl = 0; + Decl *FirstNewDecl = nullptr; + Decl *PrevDecl = nullptr; for (unsigned I = 0, N = Decls.size(); I != N; ++I) { if (FieldsAlreadyLoaded && isa<FieldDecl>(Decls[I])) continue; @@ -939,13 +984,12 @@ DeclContext::BuildDeclChain(ArrayRef<Decl*> Decls, /// \brief We have just acquired external visible storage, and we already have /// built a lookup map. For every name in the map, pull in the new names from /// the external storage. -void DeclContext::reconcileExternalVisibleStorage() { +void DeclContext::reconcileExternalVisibleStorage() const { assert(NeedToReconcileExternalVisibleStorage && LookupPtr.getPointer()); NeedToReconcileExternalVisibleStorage = false; - StoredDeclsMap &Map = *LookupPtr.getPointer(); - for (StoredDeclsMap::iterator I = Map.begin(); I != Map.end(); ++I) - I->second.setHasExternalDecls(); + for (auto &Lookup : *LookupPtr.getPointer()) + Lookup.second.setHasExternalDecls(); } /// \brief Load the declarations within this lexical storage from an @@ -982,8 +1026,8 @@ DeclContext::LoadLexicalDeclsFromExternalStorage() const { // Splice the newly-read declarations into the beginning of the list // of declarations. Decl *ExternalFirst, *ExternalLast; - llvm::tie(ExternalFirst, ExternalLast) = BuildDeclChain(Decls, - FieldsAlreadyLoaded); + std::tie(ExternalFirst, ExternalLast) = + BuildDeclChain(Decls, FieldsAlreadyLoaded); ExternalLast->NextInContextAndBits.setPointer(FirstDecl); FirstDecl = ExternalFirst; if (!LastDecl) @@ -997,6 +1041,8 @@ ExternalASTSource::SetNoExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); + if (DC->NeedToReconcileExternalVisibleStorage) + DC->reconcileExternalVisibleStorage(); (*Map)[Name].removeExternalDecls(); @@ -1011,6 +1057,8 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, StoredDeclsMap *Map; if (!(Map = DC->LookupPtr.getPointer())) Map = DC->CreateStoredDeclsMap(Context); + if (DC->NeedToReconcileExternalVisibleStorage) + DC->reconcileExternalVisibleStorage(); StoredDeclsList &List = (*Map)[Name]; @@ -1050,14 +1098,9 @@ ExternalASTSource::SetExternalVisibleDeclsForName(const DeclContext *DC, return List.getLookupResult(); } -DeclContext::decl_iterator DeclContext::noload_decls_begin() const { - return decl_iterator(FirstDecl); -} - DeclContext::decl_iterator DeclContext::decls_begin() const { if (hasExternalLexicalStorage()) LoadLexicalDeclsFromExternalStorage(); - return decl_iterator(FirstDecl); } @@ -1082,7 +1125,7 @@ void DeclContext::removeDecl(Decl *D) { // Remove D from the decl chain. This is O(n) but hopefully rare. if (D == FirstDecl) { if (D == LastDecl) - FirstDecl = LastDecl = 0; + FirstDecl = LastDecl = nullptr; else FirstDecl = D->NextInContextAndBits.getPointer(); } else { @@ -1097,7 +1140,7 @@ void DeclContext::removeDecl(Decl *D) { } // Mark that D is no longer in the decl chain. - D->NextInContextAndBits.setPointer(0); + D->NextInContextAndBits.setPointer(nullptr); // Remove D from the lookup table if necessary. if (isa<NamedDecl>(D)) { @@ -1187,6 +1230,10 @@ static bool shouldBeHidden(NamedDecl *D) { /// buildLookup - Build the lookup data structure with all of the /// declarations in this DeclContext (and any other contexts linked /// to it or transparent contexts nested within it) and return it. +/// +/// Note that the produced map may miss out declarations from an +/// external source. If it does, those entries will be marked with +/// the 'hasExternalDecls' flag. StoredDeclsMap *DeclContext::buildLookup() { assert(this == getPrimaryContext() && "buildLookup called on non-primary DC"); @@ -1202,7 +1249,6 @@ StoredDeclsMap *DeclContext::buildLookup() { // We no longer have any lazy decls. LookupPtr.setInt(false); - NeedToReconcileExternalVisibleStorage = false; return LookupPtr.getPointer(); } @@ -1251,11 +1297,13 @@ DeclContext::lookup(DeclarationName Name) { return PrimaryContext->lookup(Name); if (hasExternalVisibleStorage()) { + if (NeedToReconcileExternalVisibleStorage) + reconcileExternalVisibleStorage(); + StoredDeclsMap *Map = LookupPtr.getPointer(); + if (LookupPtr.getInt()) Map = buildLookup(); - else if (NeedToReconcileExternalVisibleStorage) - reconcileExternalVisibleStorage(); if (!Map) Map = CreateStoredDeclsMap(getParentASTContext()); @@ -1267,7 +1315,7 @@ DeclContext::lookup(DeclarationName Name) { return R.first->second.getLookupResult(); ExternalASTSource *Source = getParentASTContext().getExternalSource(); - if (Source->FindExternalVisibleDeclsByName(this, Name) || R.second) { + if (Source->FindExternalVisibleDeclsByName(this, Name) || !R.second) { if (StoredDeclsMap *Map = LookupPtr.getPointer()) { StoredDeclsMap::iterator I = Map->find(Name); if (I != Map->end()) @@ -1275,7 +1323,7 @@ DeclContext::lookup(DeclarationName Name) { } } - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); } StoredDeclsMap *Map = LookupPtr.getPointer(); @@ -1283,11 +1331,11 @@ DeclContext::lookup(DeclarationName Name) { Map = buildLookup(); if (!Map) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); StoredDeclsMap::iterator I = Map->find(Name); if (I == Map->end()) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); return I->second.getLookupResult(); } @@ -1324,12 +1372,12 @@ DeclContext::noload_lookup(DeclarationName Name) { } if (!Map) - return lookup_result(lookup_iterator(0), lookup_iterator(0)); + return lookup_result(lookup_iterator(nullptr), lookup_iterator(nullptr)); StoredDeclsMap::iterator I = Map->find(Name); - return I != Map->end() - ? I->second.getLookupResult() - : lookup_result(lookup_iterator(0), lookup_iterator(0)); + return I != Map->end() ? I->second.getLookupResult() + : lookup_result(lookup_iterator(nullptr), + lookup_iterator(nullptr)); } void DeclContext::localUncachedLookup(DeclarationName Name, @@ -1502,13 +1550,13 @@ void DeclContext::makeDeclVisibleInContextImpl(NamedDecl *D, bool Internal) { /// Returns iterator range [First, Last) of UsingDirectiveDecls stored within /// this context. -DeclContext::udir_iterator_range -DeclContext::getUsingDirectives() const { +DeclContext::udir_range DeclContext::using_directives() const { // FIXME: Use something more efficient than normal lookup for using // directives. In C++, using directives are looked up more than anything else. lookup_const_result Result = lookup(UsingDirectiveDecl::getName()); - return udir_iterator_range(reinterpret_cast<udir_iterator>(Result.begin()), - reinterpret_cast<udir_iterator>(Result.end())); + return udir_range( + reinterpret_cast<UsingDirectiveDecl *const *>(Result.begin()), + reinterpret_cast<UsingDirectiveDecl *const *>(Result.end())); } //===----------------------------------------------------------------------===// @@ -1568,7 +1616,7 @@ DependentDiagnostic *DependentDiagnostic::Create(ASTContext &C, // Allocate the copy of the PartialDiagnostic via the ASTContext's // BumpPtrAllocator, rather than the ASTContext itself. - PartialDiagnostic::Storage *DiagStorage = 0; + PartialDiagnostic::Storage *DiagStorage = nullptr; if (PDiag.hasStorage()) DiagStorage = new (C) PartialDiagnostic::Storage; diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp index a17abdd0ae2a..ed26c5262a7b 100644 --- a/lib/AST/DeclCXX.cpp +++ b/lib/AST/DeclCXX.cpp @@ -31,8 +31,7 @@ using namespace clang; void AccessSpecDecl::anchor() { } AccessSpecDecl *AccessSpecDecl::CreateDeserialized(ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(AccessSpecDecl)); - return new (Mem) AccessSpecDecl(EmptyShell()); + return new (C, ID) AccessSpecDecl(EmptyShell()); } void LazyASTUnresolvedSet::getFromExternalSource(ASTContext &C) const { @@ -51,7 +50,7 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) Aggregate(true), PlainOldData(true), Empty(true), Polymorphic(false), Abstract(false), IsStandardLayout(true), HasNoNonEmptyBases(true), HasPrivateFields(false), HasProtectedFields(false), HasPublicFields(false), - HasMutableFields(false), HasOnlyCMembers(true), + HasMutableFields(false), HasVariantMembers(false), HasOnlyCMembers(true), HasInClassInitializer(false), HasUninitializedReferenceMember(false), NeedOverloadResolutionForMoveConstructor(false), NeedOverloadResolutionForMoveAssignment(false), @@ -71,7 +70,8 @@ CXXRecordDecl::DefinitionData::DefinitionData(CXXRecordDecl *D) ImplicitCopyAssignmentHasConstParam(true), HasDeclaredCopyConstructorWithConstParam(false), HasDeclaredCopyAssignmentWithConstParam(false), - IsLambda(false), NumBases(0), NumVBases(0), Bases(), VBases(), + IsLambda(false), IsParsingBaseSpecifiers(false), NumBases(0), NumVBases(0), + Bases(), VBases(), Definition(D), FirstFriend() { } @@ -83,20 +83,22 @@ CXXBaseSpecifier *CXXRecordDecl::DefinitionData::getVBasesSlowCase() const { return VBases.get(Definition->getASTContext().getExternalSource()); } -CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, - SourceLocation StartLoc, SourceLocation IdLoc, - IdentifierInfo *Id, CXXRecordDecl *PrevDecl) - : RecordDecl(K, TK, DC, StartLoc, IdLoc, Id, PrevDecl), - DefinitionData(PrevDecl ? PrevDecl->DefinitionData : 0), - TemplateOrInstantiation() { } +CXXRecordDecl::CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, + DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, IdentifierInfo *Id, + CXXRecordDecl *PrevDecl) + : RecordDecl(K, TK, C, DC, StartLoc, IdLoc, Id, PrevDecl), + DefinitionData(PrevDecl ? PrevDecl->DefinitionData + : DefinitionDataPtr(this)), + TemplateOrInstantiation() {} CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl* PrevDecl, bool DelayTypeCreation) { - CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TK, DC, StartLoc, IdLoc, - Id, PrevDecl); + CXXRecordDecl *R = new (C, DC) CXXRecordDecl(CXXRecord, TK, C, DC, StartLoc, + IdLoc, Id, PrevDecl); R->MayHaveOutOfDateDef = C.getLangOpts().Modules; // FIXME: DelayTypeCreation seems like such a hack @@ -105,29 +107,29 @@ CXXRecordDecl *CXXRecordDecl::Create(const ASTContext &C, TagKind TK, return R; } -CXXRecordDecl *CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, - TypeSourceInfo *Info, SourceLocation Loc, - bool Dependent, bool IsGeneric, - LambdaCaptureDefault CaptureDefault) { - CXXRecordDecl* R = new (C) CXXRecordDecl(CXXRecord, TTK_Class, DC, Loc, Loc, - 0, 0); +CXXRecordDecl * +CXXRecordDecl::CreateLambda(const ASTContext &C, DeclContext *DC, + TypeSourceInfo *Info, SourceLocation Loc, + bool Dependent, bool IsGeneric, + LambdaCaptureDefault CaptureDefault) { + CXXRecordDecl *R = + new (C, DC) CXXRecordDecl(CXXRecord, TTK_Class, C, DC, Loc, Loc, + nullptr, nullptr); R->IsBeingDefined = true; - R->DefinitionData = new (C) struct LambdaDefinitionData(R, Info, - Dependent, - IsGeneric, - CaptureDefault); + R->DefinitionData = + new (C) struct LambdaDefinitionData(R, Info, Dependent, IsGeneric, + CaptureDefault); R->MayHaveOutOfDateDef = false; R->setImplicit(true); - C.getTypeDeclType(R, /*PrevDecl=*/0); + C.getTypeDeclType(R, /*PrevDecl=*/nullptr); return R; } CXXRecordDecl * CXXRecordDecl::CreateDeserialized(const ASTContext &C, unsigned ID) { - void *Mem = AllocateDeserializedDecl(C, ID, sizeof(CXXRecordDecl)); - CXXRecordDecl *R = new (Mem) CXXRecordDecl(CXXRecord, TTK_Struct, 0, - SourceLocation(), SourceLocation(), - 0, 0); + CXXRecordDecl *R = new (C, ID) CXXRecordDecl( + CXXRecord, TTK_Struct, C, nullptr, SourceLocation(), SourceLocation(), + nullptr, nullptr); R->MayHaveOutOfDateDef = false; return R; } @@ -205,19 +207,17 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, data().HasNonLiteralTypeFieldsOrBases = true; // Now go through all virtual bases of this base and add them. - for (CXXRecordDecl::base_class_iterator VBase = - BaseClassDecl->vbases_begin(), - E = BaseClassDecl->vbases_end(); VBase != E; ++VBase) { + for (const auto &VBase : BaseClassDecl->vbases()) { // Add this base if it's not already in the list. - if (SeenVBaseTypes.insert(C.getCanonicalType(VBase->getType()))) { - VBases.push_back(VBase); + if (SeenVBaseTypes.insert(C.getCanonicalType(VBase.getType()))) { + VBases.push_back(&VBase); // C++11 [class.copy]p8: // The implicitly-declared copy constructor for a class X will have // the form 'X::X(const X&)' if each [...] virtual base class B of X // has a copy constructor whose first parameter is of type // 'const B&' or 'const volatile B&' [...] - if (CXXRecordDecl *VBaseDecl = VBase->getType()->getAsCXXRecordDecl()) + if (CXXRecordDecl *VBaseDecl = VBase.getType()->getAsCXXRecordDecl()) if (!VBaseDecl->hasCopyConstructorWithConstParam()) data().ImplicitCopyConstructorHasConstParam = false; } @@ -335,8 +335,10 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, addedClassSubobject(BaseClassDecl); } - if (VBases.empty()) + if (VBases.empty()) { + data().IsParsingBaseSpecifiers = false; return; + } // Create base specifier for any direct or indirect virtual bases. data().VBases = new (C) CXXBaseSpecifier[VBases.size()]; @@ -347,6 +349,8 @@ CXXRecordDecl::setBases(CXXBaseSpecifier const * const *Bases, addedClassSubobject(Type->getAsCXXRecordDecl()); data().getVBases()[I] = *VBases[I]; } + + data().IsParsingBaseSpecifiers = false; } void CXXRecordDecl::addedClassSubobject(CXXRecordDecl *Subobj) { @@ -391,7 +395,7 @@ bool CXXRecordDecl::hasAnyDependentBases() const { if (!isDependentContext()) return false; - return !forallBases(SawBase, 0); + return !forallBases(SawBase, nullptr); } bool CXXRecordDecl::isTriviallyCopyable() const { @@ -532,8 +536,11 @@ void CXXRecordDecl::addedMember(Decl *D) { if (CXXDestructorDecl *DD = dyn_cast<CXXDestructorDecl>(D)) { SMKind |= SMF_Destructor; - if (!DD->isImplicit()) + if (DD->isUserProvided()) data().HasIrrelevantDestructor = false; + // If the destructor is explicitly defaulted and not trivial or not public + // or if the destructor is deleted, we clear HasIrrelevantDestructor in + // finishedDefaultedOrDeletedMember. // C++11 [class.dtor]p5: // A destructor is trivial if [...] the destructor is not virtual. @@ -656,7 +663,13 @@ void CXXRecordDecl::addedMember(Decl *D) { // Keep track of the presence of mutable fields. if (Field->isMutable()) data().HasMutableFields = true; - + + // C++11 [class.union]p8, DR1460: + // If X is a union, a non-static data member of X that is not an anonymous + // union is a variant member of X. + if (isUnion() && !Field->isAnonymousStructOrUnion()) + data().HasVariantMembers = true; + // C++0x [class]p9: // A POD struct is a class that is both a trivial class and a // standard-layout class, and has no non-static data members of type @@ -692,7 +705,9 @@ void CXXRecordDecl::addedMember(Decl *D) { if (!T->isLiteralType(Context) || T.isVolatileQualified()) data().HasNonLiteralTypeFieldsOrBases = true; - if (Field->hasInClassInitializer()) { + if (Field->hasInClassInitializer() || + (Field->isAnonymousStructOrUnion() && + Field->getType()->getAsCXXRecordDecl()->hasInClassInitializer())) { data().HasInClassInitializer = true; // C++11 [class]p5: @@ -809,15 +824,13 @@ void CXXRecordDecl::addedMember(Decl *D) { // Virtual bases and virtual methods make a class non-empty, but they // also make it non-standard-layout so we needn't check here. // A non-empty base class may leave the class standard-layout, but not - // if we have arrived here, and have at least on non-static data + // if we have arrived here, and have at least one non-static data // member. If IsStandardLayout remains true, then the first non-static // data member must come through here with Empty still true, and Empty // will subsequently be set to false below. if (data().IsStandardLayout && data().Empty) { - for (CXXRecordDecl::base_class_const_iterator BI = bases_begin(), - BE = bases_end(); - BI != BE; ++BI) { - if (Context.hasSameUnqualifiedType(BI->getType(), T)) { + for (const auto &BI : bases()) { + if (Context.hasSameUnqualifiedType(BI.getType(), T)) { data().IsStandardLayout = false; break; } @@ -862,6 +875,13 @@ void CXXRecordDecl::addedMember(Decl *D) { if (FieldRec->hasUninitializedReferenceMember() && !Field->hasInClassInitializer()) data().HasUninitializedReferenceMember = true; + + // C++11 [class.union]p8, DR1460: + // a non-static data member of an anonymous union that is a member of + // X is also a variant member of X. + if (FieldRec->hasVariantMembers() && + Field->isAnonymousStructOrUnion()) + data().HasVariantMembers = true; } } else { // Base element type of field is a non-class type. @@ -928,9 +948,11 @@ void CXXRecordDecl::finishedDefaultedOrDeletedMember(CXXMethodDecl *D) { else if (Cons |