From bfef399519ca9b8a4b4c6b563253bad7e0eeffe0 Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sun, 22 Dec 2013 00:07:40 +0000 Subject: Vendor import of clang release_34 branch r197841 (effectively, 3.4 RC3): https://llvm.org/svn/llvm-project/cfe/branches/release_34@197841 --- include/clang-c/CXCompilationDatabase.h | 20 +- include/clang-c/CXString.h | 2 +- include/clang-c/Index.h | 72 +- include/clang/ARCMigrate/ARCMT.h | 2 + include/clang/ARCMigrate/ARCMTActions.h | 6 +- include/clang/ARCMigrate/FileRemapper.h | 1 - include/clang/AST/APValue.h | 7 + include/clang/AST/ASTConsumer.h | 21 + include/clang/AST/ASTContext.h | 310 +++--- include/clang/AST/ASTDiagnostic.h | 2 +- include/clang/AST/ASTFwd.h | 28 + include/clang/AST/ASTImporter.h | 8 + include/clang/AST/ASTLambda.h | 80 ++ include/clang/AST/ASTMutationListener.h | 17 + include/clang/AST/ASTTypeTraits.h | 387 +++++--- include/clang/AST/ASTUnresolvedSet.h | 42 +- include/clang/AST/ASTVector.h | 55 +- include/clang/AST/Attr.h | 3 +- include/clang/AST/CXXInheritance.h | 4 +- include/clang/AST/CanonicalType.h | 2 +- include/clang/AST/CharUnits.h | 21 +- include/clang/AST/Comment.h | 20 +- include/clang/AST/CommentCommandTraits.h | 5 + include/clang/AST/CommentCommands.td | 11 + include/clang/AST/CommentDiagnostic.h | 2 +- include/clang/AST/CommentParser.h | 6 +- include/clang/AST/CommentSema.h | 9 +- include/clang/AST/Decl.h | 367 ++++--- include/clang/AST/DeclAccessPair.h | 9 +- include/clang/AST/DeclBase.h | 163 +++- include/clang/AST/DeclCXX.h | 1014 +++++++++++--------- include/clang/AST/DeclContextInternals.h | 48 +- include/clang/AST/DeclFriend.h | 4 +- include/clang/AST/DeclLookups.h | 22 +- include/clang/AST/DeclObjC.h | 47 +- include/clang/AST/DeclOpenMP.h | 26 +- include/clang/AST/DeclTemplate.h | 691 +++++++++++-- include/clang/AST/DeclarationName.h | 12 +- include/clang/AST/EvaluatedExprVisitor.h | 2 +- include/clang/AST/Expr.h | 245 +++-- include/clang/AST/ExprCXX.h | 688 +++++++------ include/clang/AST/ExprObjC.h | 23 +- include/clang/AST/ExternalASTSource.h | 7 +- include/clang/AST/GlobalDecl.h | 1 + include/clang/AST/LambdaMangleContext.h | 38 - include/clang/AST/Mangle.h | 117 ++- include/clang/AST/MangleNumberingContext.h | 59 ++ include/clang/AST/NestedNameSpecifier.h | 6 +- include/clang/AST/ParentMap.h | 5 + include/clang/AST/PrettyPrinter.h | 13 +- include/clang/AST/RawCommentList.h | 31 +- include/clang/AST/RecordLayout.h | 55 +- include/clang/AST/RecursiveASTVisitor.h | 330 ++++--- include/clang/AST/Redeclarable.h | 52 +- include/clang/AST/Stmt.h | 104 +- include/clang/AST/StmtCXX.h | 4 +- include/clang/AST/StmtIterator.h | 32 +- include/clang/AST/StmtObjC.h | 9 +- include/clang/AST/StmtOpenMP.h | 528 ++++++++++ include/clang/AST/StmtVisitor.h | 36 + include/clang/AST/TemplateBase.h | 108 +-- include/clang/AST/Type.h | 113 ++- include/clang/AST/TypeLoc.h | 142 ++- include/clang/AST/TypeNodes.def | 3 +- include/clang/AST/TypeOrdering.h | 16 +- include/clang/AST/TypeVisitor.h | 44 +- include/clang/AST/UnresolvedSet.h | 15 +- include/clang/AST/VTTBuilder.h | 49 +- include/clang/AST/VTableBuilder.h | 301 ++++-- include/clang/ASTMatchers/ASTMatchFinder.h | 21 +- include/clang/ASTMatchers/ASTMatchers.h | 718 ++++++++------ include/clang/ASTMatchers/ASTMatchersInternal.h | 786 +++++++++++---- include/clang/ASTMatchers/ASTMatchersMacros.h | 189 ++-- include/clang/ASTMatchers/Dynamic/Diagnostics.h | 185 ++++ include/clang/ASTMatchers/Dynamic/Parser.h | 151 +++ include/clang/ASTMatchers/Dynamic/Registry.h | 75 ++ include/clang/ASTMatchers/Dynamic/VariantValue.h | 261 +++++ include/clang/Analysis/Analyses/Consumed.h | 264 +++++ include/clang/Analysis/Analyses/FormatString.h | 8 +- include/clang/Analysis/Analyses/ThreadSafety.h | 4 +- .../clang/Analysis/Analyses/UninitializedValues.h | 22 +- include/clang/Analysis/AnalysisContext.h | 6 +- include/clang/Analysis/AnalysisDiagnostic.h | 2 +- include/clang/Analysis/CFG.h | 90 +- include/clang/Analysis/CallGraph.h | 4 +- .../clang/Analysis/FlowSensitive/DataflowSolver.h | 3 +- .../clang/Analysis/Support/BlkExprDeclBitVector.h | 307 ------ .../Analysis/Visitors/CFGRecStmtDeclVisitor.h | 107 --- .../clang/Analysis/Visitors/CFGRecStmtVisitor.h | 59 -- include/clang/Analysis/Visitors/CFGStmtVisitor.h | 175 ---- include/clang/Basic/ABI.h | 142 ++- include/clang/Basic/Attr.td | 274 ++++-- include/clang/Basic/AttrKinds.h | 2 +- include/clang/Basic/Builtins.def | 471 ++++++--- include/clang/Basic/Builtins.h | 28 +- include/clang/Basic/BuiltinsAArch64.def | 9 +- include/clang/Basic/BuiltinsARM.def | 25 +- include/clang/Basic/BuiltinsMips.def | 712 ++++++++++++++ include/clang/Basic/BuiltinsNVPTX.def | 744 +++++++++----- include/clang/Basic/BuiltinsX86.def | 16 +- include/clang/Basic/BuiltinsXCore.def | 22 + include/clang/Basic/CapturedStmt.h | 3 +- include/clang/Basic/DeclNodes.td | 4 + include/clang/Basic/Diagnostic.h | 16 +- include/clang/Basic/Diagnostic.td | 43 +- include/clang/Basic/DiagnosticASTKinds.td | 16 + include/clang/Basic/DiagnosticCommentKinds.td | 4 + include/clang/Basic/DiagnosticCommonKinds.td | 20 +- include/clang/Basic/DiagnosticDriverKinds.td | 24 +- include/clang/Basic/DiagnosticFrontendKinds.td | 7 +- include/clang/Basic/DiagnosticGroups.td | 102 +- include/clang/Basic/DiagnosticIDs.h | 34 +- include/clang/Basic/DiagnosticLexKinds.td | 66 +- include/clang/Basic/DiagnosticOptions.def | 1 + include/clang/Basic/DiagnosticParseKinds.td | 81 +- include/clang/Basic/DiagnosticSemaKinds.td | 760 +++++++++++---- .../clang/Basic/DiagnosticSerializationKinds.td | 13 +- include/clang/Basic/FileManager.h | 36 +- include/clang/Basic/FileSystemStatCache.h | 47 +- include/clang/Basic/IdentifierTable.h | 82 +- include/clang/Basic/Lambda.h | 15 +- include/clang/Basic/LangOptions.def | 33 +- include/clang/Basic/LangOptions.h | 7 + include/clang/Basic/Linkage.h | 40 +- include/clang/Basic/Module.h | 57 +- include/clang/Basic/ObjCRuntime.h | 7 +- include/clang/Basic/OpenMPKinds.def | 31 +- include/clang/Basic/OpenMPKinds.h | 28 + include/clang/Basic/OperatorKinds.h | 2 +- include/clang/Basic/PartialDiagnostic.h | 21 + include/clang/Basic/Sanitizers.def | 23 +- include/clang/Basic/SourceLocation.h | 2 +- include/clang/Basic/SourceManager.h | 58 +- include/clang/Basic/Specifiers.h | 35 +- include/clang/Basic/StmtNodes.td | 6 + include/clang/Basic/TargetBuiltins.h | 14 +- include/clang/Basic/TargetCXXABI.h | 24 +- include/clang/Basic/TargetInfo.h | 47 +- include/clang/Basic/TargetOptions.h | 3 + include/clang/Basic/TemplateKinds.h | 3 + include/clang/Basic/TokenKinds.def | 17 +- include/clang/Basic/TypeTraits.h | 1 + include/clang/Basic/Visibility.h | 16 +- include/clang/Basic/arm_neon.td | 888 ++++++++++++++++- include/clang/CodeGen/CGFunctionInfo.h | 361 +++++++ include/clang/CodeGen/CodeGenABITypes.h | 80 ++ include/clang/Driver/Action.h | 14 +- include/clang/Driver/Arg.h | 133 --- include/clang/Driver/ArgList.h | 442 --------- include/clang/Driver/CC1AsOptions.h | 13 +- include/clang/Driver/CC1AsOptions.td | 11 +- include/clang/Driver/CC1Options.td | 43 +- include/clang/Driver/CLCompatOptions.td | 255 +++++ include/clang/Driver/CMakeLists.txt | 12 +- include/clang/Driver/Compilation.h | 55 +- include/clang/Driver/Driver.h | 77 +- include/clang/Driver/DriverDiagnostic.h | 2 +- include/clang/Driver/Job.h | 71 +- include/clang/Driver/Makefile | 8 +- include/clang/Driver/OptParser.td | 152 --- include/clang/Driver/OptSpecifier.h | 41 - include/clang/Driver/OptTable.h | 161 ---- include/clang/Driver/Option.h | 204 ---- include/clang/Driver/Options.h | 28 +- include/clang/Driver/Options.td | 535 ++++++++--- include/clang/Driver/SanitizerArgs.h | 147 +++ include/clang/Driver/Tool.h | 13 +- include/clang/Driver/ToolChain.h | 102 +- include/clang/Driver/Types.def | 2 +- include/clang/Driver/Types.h | 4 +- include/clang/Driver/Util.h | 5 +- include/clang/Edit/Commit.h | 16 +- include/clang/Edit/EditedSource.h | 9 +- include/clang/Edit/Rewriters.h | 8 +- include/clang/Format/Format.h | 286 +++++- include/clang/Frontend/ASTConsumers.h | 9 +- include/clang/Frontend/ASTUnit.h | 14 +- include/clang/Frontend/CodeGenOptions.def | 14 +- include/clang/Frontend/CodeGenOptions.h | 12 + include/clang/Frontend/CompilerInstance.h | 36 +- include/clang/Frontend/CompilerInvocation.h | 15 +- include/clang/Frontend/DependencyOutputOptions.h | 2 + include/clang/Frontend/FrontendAction.h | 10 +- include/clang/Frontend/FrontendActions.h | 10 +- include/clang/Frontend/FrontendDiagnostic.h | 2 +- include/clang/Frontend/FrontendOptions.h | 33 +- include/clang/Frontend/TextDiagnostic.h | 3 +- include/clang/Frontend/Utils.h | 23 +- include/clang/Index/CommentToXML.h | 50 + include/clang/Index/USRGeneration.h | 54 ++ include/clang/Lex/DirectoryLookup.h | 10 +- include/clang/Lex/HeaderSearch.h | 65 +- include/clang/Lex/HeaderSearchOptions.h | 8 +- include/clang/Lex/LexDiagnostic.h | 2 +- include/clang/Lex/Lexer.h | 69 +- include/clang/Lex/LiteralSupport.h | 20 +- include/clang/Lex/MacroInfo.h | 4 +- include/clang/Lex/ModuleLoader.h | 4 + include/clang/Lex/ModuleMap.h | 86 +- include/clang/Lex/MultipleIncludeOpt.h | 56 +- include/clang/Lex/PPCallbacks.h | 95 +- include/clang/Lex/PPConditionalDirectiveRecord.h | 5 +- include/clang/Lex/PTHLexer.h | 2 +- include/clang/Lex/PreprocessingRecord.h | 3 +- include/clang/Lex/Preprocessor.h | 79 +- include/clang/Lex/PreprocessorLexer.h | 6 +- include/clang/Lex/Token.h | 9 +- include/clang/Lex/TokenLexer.h | 4 +- include/clang/Parse/CMakeLists.txt | 9 +- include/clang/Parse/Makefile | 16 +- include/clang/Parse/ParseDiagnostic.h | 2 +- include/clang/Parse/Parser.h | 185 +++- include/clang/Rewrite/Core/HTMLRewrite.h | 2 +- include/clang/Rewrite/Core/Rewriter.h | 17 +- include/clang/Sema/AnalysisBasedWarnings.h | 1 + include/clang/Sema/AttributeList.h | 233 +++-- include/clang/Sema/CMakeLists.txt | 5 + include/clang/Sema/CodeCompleteConsumer.h | 20 +- include/clang/Sema/DeclSpec.h | 120 ++- include/clang/Sema/DelayedDiagnostic.h | 24 +- include/clang/Sema/ExternalSemaSource.h | 44 +- include/clang/Sema/IdentifierResolver.h | 10 - include/clang/Sema/Initialization.h | 117 ++- include/clang/Sema/Lookup.h | 119 ++- include/clang/Sema/Makefile | 7 +- include/clang/Sema/MultiplexExternalSemaSource.h | 30 + include/clang/Sema/Overload.h | 77 +- include/clang/Sema/Ownership.h | 24 +- include/clang/Sema/Scope.h | 23 +- include/clang/Sema/ScopeInfo.h | 269 +++++- include/clang/Sema/Sema.h | 970 ++++++++++++++----- include/clang/Sema/SemaDiagnostic.h | 2 +- include/clang/Sema/SemaInternal.h | 39 +- include/clang/Sema/SemaLambda.h | 39 + include/clang/Sema/Template.h | 123 ++- include/clang/Sema/TemplateDeduction.h | 122 ++- include/clang/Sema/TypoCorrection.h | 105 +- include/clang/Serialization/ASTBitCodes.h | 30 +- include/clang/Serialization/ASTReader.h | 61 +- include/clang/Serialization/ASTWriter.h | 23 +- include/clang/Serialization/GlobalModuleIndex.h | 1 + include/clang/Serialization/ModuleManager.h | 6 +- .../clang/Serialization/SerializationDiagnostic.h | 2 +- .../StaticAnalyzer/Checkers/CommonBugCategories.h | 24 - .../StaticAnalyzer/Checkers/ObjCRetainCount.h | 223 +++++ include/clang/StaticAnalyzer/Core/Analyses.def | 12 +- .../clang/StaticAnalyzer/Core/AnalyzerOptions.h | 25 +- .../StaticAnalyzer/Core/BugReporter/BugReporter.h | 19 +- .../StaticAnalyzer/Core/BugReporter/BugType.h | 11 +- .../Core/BugReporter/CommonBugCategories.h | 25 + .../Core/BugReporter/PathDiagnostic.h | 56 +- include/clang/StaticAnalyzer/Core/Checker.h | 63 +- include/clang/StaticAnalyzer/Core/CheckerManager.h | 64 +- .../clang/StaticAnalyzer/Core/CheckerRegistry.h | 7 +- .../StaticAnalyzer/Core/PathDiagnosticConsumers.h | 18 +- .../Core/PathSensitive/AnalysisManager.h | 4 + .../StaticAnalyzer/Core/PathSensitive/CallEvent.h | 33 +- .../Core/PathSensitive/ExplodedGraph.h | 2 +- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 6 +- .../StaticAnalyzer/Core/PathSensitive/MemRegion.h | 48 +- .../Core/PathSensitive/ProgramState.h | 22 +- .../Core/PathSensitive/SValBuilder.h | 3 +- .../StaticAnalyzer/Core/PathSensitive/SVals.h | 2 +- .../StaticAnalyzer/Core/PathSensitive/Store.h | 19 +- .../StaticAnalyzer/Core/PathSensitive/SubEngine.h | 2 +- include/clang/Tooling/ArgumentsAdjusters.h | 6 + include/clang/Tooling/CommonOptionsParser.h | 2 +- include/clang/Tooling/CompilationDatabase.h | 14 + include/clang/Tooling/Refactoring.h | 103 +- include/clang/Tooling/ReplacementsYaml.h | 88 ++ include/clang/Tooling/Tooling.h | 170 +++- 271 files changed, 16527 insertions(+), 6866 deletions(-) create mode 100644 include/clang/AST/ASTFwd.h create mode 100644 include/clang/AST/ASTLambda.h delete mode 100644 include/clang/AST/LambdaMangleContext.h create mode 100644 include/clang/AST/MangleNumberingContext.h create mode 100644 include/clang/AST/StmtOpenMP.h create mode 100644 include/clang/ASTMatchers/Dynamic/Diagnostics.h create mode 100644 include/clang/ASTMatchers/Dynamic/Parser.h create mode 100644 include/clang/ASTMatchers/Dynamic/Registry.h create mode 100644 include/clang/ASTMatchers/Dynamic/VariantValue.h create mode 100644 include/clang/Analysis/Analyses/Consumed.h delete mode 100644 include/clang/Analysis/Support/BlkExprDeclBitVector.h delete mode 100644 include/clang/Analysis/Visitors/CFGRecStmtDeclVisitor.h delete mode 100644 include/clang/Analysis/Visitors/CFGRecStmtVisitor.h delete mode 100644 include/clang/Analysis/Visitors/CFGStmtVisitor.h create mode 100644 include/clang/Basic/BuiltinsXCore.def create mode 100644 include/clang/CodeGen/CGFunctionInfo.h create mode 100644 include/clang/CodeGen/CodeGenABITypes.h delete mode 100644 include/clang/Driver/Arg.h delete mode 100644 include/clang/Driver/ArgList.h create mode 100644 include/clang/Driver/CLCompatOptions.td delete mode 100644 include/clang/Driver/OptParser.td delete mode 100644 include/clang/Driver/OptSpecifier.h delete mode 100644 include/clang/Driver/OptTable.h delete mode 100644 include/clang/Driver/Option.h create mode 100644 include/clang/Driver/SanitizerArgs.h create mode 100644 include/clang/Index/CommentToXML.h create mode 100644 include/clang/Index/USRGeneration.h create mode 100644 include/clang/Sema/SemaLambda.h delete mode 100644 include/clang/StaticAnalyzer/Checkers/CommonBugCategories.h create mode 100644 include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h create mode 100644 include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h create mode 100644 include/clang/Tooling/ReplacementsYaml.h (limited to 'include') diff --git a/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h index ff1ec63db057..fd65418f607c 100644 --- a/include/clang-c/CXCompilationDatabase.h +++ b/include/clang-c/CXCompilationDatabase.h @@ -58,7 +58,7 @@ typedef void * CXCompileCommand; */ typedef enum { /* - * \brief No error occured + * \brief No error occurred */ CXCompilationDatabase_NoError = 0, @@ -141,6 +141,24 @@ clang_CompileCommand_getNumArgs(CXCompileCommand); CINDEX_LINKAGE CXString clang_CompileCommand_getArg(CXCompileCommand, unsigned I); +/** + * \brief Get the number of source mappings for the compiler invocation. + */ +CINDEX_LINKAGE unsigned +clang_CompileCommand_getNumMappedSources(CXCompileCommand); + +/** + * \brief Get the I'th mapped source path for the compiler invocation. + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getMappedSourcePath(CXCompileCommand, unsigned I); + +/** + * \brief Get the I'th mapped source content for the compiler invocation. + */ +CINDEX_LINKAGE CXString +clang_CompileCommand_getMappedSourceContent(CXCompileCommand, unsigned I); + /** * @} */ diff --git a/include/clang-c/CXString.h b/include/clang-c/CXString.h index 34cab5e7bd8c..592c4dc44e30 100644 --- a/include/clang-c/CXString.h +++ b/include/clang-c/CXString.h @@ -46,7 +46,7 @@ typedef struct { CINDEX_LINKAGE const char *clang_getCString(CXString string); /** - * \brief Free the given string, + * \brief Free the given string. */ CINDEX_LINKAGE void clang_disposeString(CXString string); diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index d8c37ebd70f9..95d54c279f03 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -16,9 +16,7 @@ #ifndef CLANG_C_INDEX_H #define CLANG_C_INDEX_H -#include #include -#include #include "clang-c/Platform.h" #include "clang-c/CXString.h" @@ -32,7 +30,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 19 +#define CINDEX_VERSION_MINOR 20 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -413,6 +411,12 @@ CINDEX_LINKAGE CXSourceLocation clang_getLocationForOffset(CXTranslationUnit tu, */ CINDEX_LINKAGE int clang_Location_isInSystemHeader(CXSourceLocation location); +/** + * \brief Returns non-zero if the given source location is in the main file of + * the corresponding translation unit. + */ +CINDEX_LINKAGE int clang_Location_isFromMainFile(CXSourceLocation location); + /** * \brief Retrieve a NULL (invalid) source range. */ @@ -723,7 +727,7 @@ CINDEX_LINKAGE void clang_disposeDiagnosticSet(CXDiagnosticSet Diags); * \brief Retrieve the child diagnostics of a CXDiagnostic. * * This CXDiagnosticSet does not need to be released by - * clang_diposeDiagnosticSet. + * clang_disposeDiagnosticSet. */ CINDEX_LINKAGE CXDiagnosticSet clang_getChildDiagnostics(CXDiagnostic D); @@ -763,7 +767,7 @@ CINDEX_LINKAGE void clang_disposeDiagnostic(CXDiagnostic Diagnostic); * \brief Options to control the display of diagnostics. * * The values in this enum are meant to be combined to customize the - * behavior of \c clang_displayDiagnostic(). + * behavior of \c clang_formatDiagnostic(). */ enum CXDiagnosticDisplayOptions { /** @@ -850,7 +854,7 @@ CINDEX_LINKAGE CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, * default behavior of the clang compiler. * * \returns A set of display options suitable for use with \c - * clang_displayDiagnostic(). + * clang_formatDiagnostic(). */ CINDEX_LINKAGE unsigned clang_defaultDiagnosticDisplayOptions(void); @@ -1942,7 +1946,7 @@ enum CXCursorKind { */ CXCursor_CompoundStmt = 202, - /** \brief A case statment. + /** \brief A case statement. */ CXCursor_CaseStmt = 203, @@ -2062,7 +2066,11 @@ enum CXCursorKind { */ CXCursor_DeclStmt = 231, - CXCursor_LastStmt = CXCursor_DeclStmt, + /** \brief OpenMP parallel directive. + */ + CXCursor_OMPParallelDirective = 232, + + CXCursor_LastStmt = CXCursor_OMPParallelDirective, /** * \brief Cursor that represents the translation unit itself. @@ -2087,7 +2095,8 @@ enum CXCursorKind { CXCursor_CXXOverrideAttr = 405, CXCursor_AnnotateAttr = 406, CXCursor_AsmLabelAttr = 407, - CXCursor_LastAttr = CXCursor_AsmLabelAttr, + CXCursor_PackedAttr = 408, + CXCursor_LastAttr = CXCursor_PackedAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, @@ -2666,7 +2675,11 @@ enum CXTypeKind { CXType_FunctionNoProto = 110, CXType_FunctionProto = 111, CXType_ConstantArray = 112, - CXType_Vector = 113 + CXType_Vector = 113, + CXType_IncompleteArray = 114, + CXType_VariableArray = 115, + CXType_DependentSizedArray = 116, + CXType_MemberPointer = 117 }; /** @@ -2683,6 +2696,8 @@ enum CXCallingConv { CXCallingConv_AAPCS_VFP = 7, CXCallingConv_PnaclCall = 8, CXCallingConv_IntelOclBicc = 9, + CXCallingConv_X86_64Win64 = 10, + CXCallingConv_X86_64SysV = 11, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 @@ -2954,6 +2969,13 @@ enum CXTypeLayoutError { */ CINDEX_LINKAGE long long clang_Type_getAlignOf(CXType T); +/** + * \brief Return the class type of an member pointer type. + * + * If a non-member-pointer type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getClassType(CXType T); + /** * \brief Return the size of a type in bytes as per C++[expr.sizeof] standard. * @@ -2980,6 +3002,23 @@ CINDEX_LINKAGE long long clang_Type_getSizeOf(CXType T); */ CINDEX_LINKAGE long long clang_Type_getOffsetOf(CXType T, const char *S); +enum CXRefQualifierKind { + /** \brief No ref-qualifier was provided. */ + CXRefQualifier_None = 0, + /** \brief An lvalue ref-qualifier was provided (\c &). */ + CXRefQualifier_LValue, + /** \brief An rvalue ref-qualifier was provided (\c &&). */ + CXRefQualifier_RValue +}; + +/** + * \brief Retrieve the ref-qualifier kind of a function or method. + * + * The ref-qualifier is returned for C++ functions or methods. For other types + * or non-C++ declarations, CXRefQualifier_None is returned. + */ +CINDEX_LINKAGE enum CXRefQualifierKind clang_Type_getCXXRefQualifier(CXType T); + /** * \brief Returns non-zero if the cursor specifies a Record member that is a * bitfield. @@ -3413,6 +3452,13 @@ typedef enum { */ CINDEX_LINKAGE unsigned clang_Cursor_getObjCDeclQualifiers(CXCursor C); +/** + * \brief Given a cursor that represents an ObjC method or property declaration, + * return non-zero if the declaration was affected by "@optional". + * Returns zero if the cursor is not such a declaration or it is "@required". + */ +CINDEX_LINKAGE unsigned clang_Cursor_isObjCOptional(CXCursor C); + /** * \brief Returns non-zero if the given cursor is a variadic function or method. */ @@ -4034,6 +4080,12 @@ CINDEX_LINKAGE CXString clang_FullComment_getAsXML(CXComment Comment); * @{ */ +/** + * \brief Determine if a C++ member function or member function template is + * pure virtual. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isPureVirtual(CXCursor C); + /** * \brief Determine if a C++ member function or member function template is * declared 'static'. diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index c167d3c3192b..196f6c0b731f 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -97,6 +97,8 @@ class MigrationProcess { FileRemapper Remapper; public: + bool HadARCErrors; + MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient, StringRef outputDir = StringRef()); diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h index 2daaf73065c2..45c8b4ed1a39 100644 --- a/include/clang/ARCMigrate/ARCMTActions.h +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -57,14 +57,12 @@ public: /// \brief Migrates to modern ObjC syntax. class ObjCMigrateAction : public WrapperFrontendAction { std::string MigrateDir; - bool MigrateLiterals; - bool MigrateSubscripting; + unsigned ObjCMigAction; FileRemapper Remapper; CompilerInstance *CompInst; public: ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, - bool migrateLiterals, - bool migrateSubscripting); + unsigned migrateAction); protected: virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI,StringRef InFile); diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h index 94c9e8f31acb..f7677cc8620a 100644 --- a/include/clang/ARCMigrate/FileRemapper.h +++ b/include/clang/ARCMigrate/FileRemapper.h @@ -53,7 +53,6 @@ public: StringRef outputDir = StringRef()); void remap(StringRef filePath, llvm::MemoryBuffer *memBuf); - void remap(StringRef filePath, StringRef newPath); void applyMappings(PreprocessorOptions &PPOpts) const; diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index ec8faa4e3524..b4fd2affa653 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -168,6 +168,13 @@ public: MakeUninit(); } + /// \brief Returns whether the object performed allocations. + /// + /// If APValues are constructed via placement new, \c needsCleanup() + /// indicates whether the destructor must be called in order to correctly + /// free all allocated memory. + bool needsCleanup() const; + /// \brief Swaps the contents of this and the given APValue. void swap(APValue &RHS); diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index ae779436a9da..7b6fa94b2043 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -14,6 +14,8 @@ #ifndef LLVM_CLANG_AST_ASTCONSUMER_H #define LLVM_CLANG_AST_ASTCONSUMER_H +#include "llvm/ADT/StringRef.h" + namespace clang { class ASTContext; class CXXRecordDecl; @@ -70,6 +72,10 @@ public: /// can be defined in declspecs). virtual void HandleTagDeclDefinition(TagDecl *D) {} + /// \brief This callback is invoked the first time each TagDecl is required to + /// be complete. + virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {} + /// \brief Invoked when a function is implicitly instantiated. /// Note that at this point point it does not have a body, its body is /// instantiated at the end of the translation unit and passed to @@ -86,6 +92,21 @@ public: /// The default implementation passes it to HandleTopLevelDecl. virtual void HandleImplicitImportDecl(ImportDecl *D); + /// \brief Handle a pragma that appends to Linker Options. Currently this + /// only exists to support Microsoft's #pragma comment(linker, "/foo"). + virtual void HandleLinkerOptionPragma(llvm::StringRef Opts) {} + + /// \brief Handle a pragma that emits a mismatch identifier and value to the + /// object file for the linker to work with. Currently, this only exists to + /// support Microsoft's #pragma detect_mismatch. + virtual void HandleDetectMismatch(llvm::StringRef Name, + llvm::StringRef Value) {} + + /// \brief Handle a dependent library created by a pragma in the source. + /// Currently this only exists to support Microsoft's + /// #pragma comment(lib, "/foo"). + virtual void HandleDependentLibrary(llvm::StringRef Lib) {} + /// CompleteTentativeDefinition - Callback invoked at the end of a translation /// unit to notify the consumer that the given tentative definition should be /// completed. diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index c5d3337fd22d..f420e85ee146 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -19,11 +19,9 @@ #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/Decl.h" -#include "clang/AST/LambdaMangleContext.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/PrettyPrinter.h" #include "clang/AST/RawCommentList.h" -#include "clang/AST/RecursiveASTVisitor.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/Basic/AddressSpaces.h" @@ -47,6 +45,7 @@ namespace llvm { namespace clang { class FileManager; + class AtomicExpr; class ASTRecordLayout; class BlockExpr; class CharUnits; @@ -55,9 +54,11 @@ namespace clang { class ExternalASTSource; class ASTMutationListener; class IdentifierTable; + class MaterializeTemporaryExpr; class SelectorTable; class TargetInfo; class CXXABI; + class MangleNumberingContext; // Decls class MangleContext; class ObjCIvarDecl; @@ -81,6 +82,7 @@ class ASTContext : public RefCountedBase { mutable llvm::FoldingSet ExtQualNodes; mutable llvm::FoldingSet ComplexTypes; mutable llvm::FoldingSet PointerTypes; + mutable llvm::FoldingSet DecayedTypes; mutable llvm::FoldingSet BlockPointerTypes; mutable llvm::FoldingSet LValueReferenceTypes; mutable llvm::FoldingSet RValueReferenceTypes; @@ -146,7 +148,7 @@ class ASTContext : public RefCountedBase { mutable TypeInfoMap MemoizedTypeInfo; /// \brief A cache mapping from CXXRecordDecls to key functions. - llvm::DenseMap KeyFunctions; + llvm::DenseMap KeyFunctions; /// \brief Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap ObjCImpls; @@ -163,6 +165,11 @@ class ASTContext : public RefCountedBase { llvm::DenseMap ClassScopeSpecializationPattern; + /// \brief Mapping from materialized temporaries with static storage duration + /// that appear in constant initializers to their evaluated values. + llvm::DenseMap + MaterializedTemporaryValues; + /// \brief Representation of a "canonical" template template parameter that /// is used in canonical template names. class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { @@ -190,6 +197,9 @@ class ASTContext : public RefCountedBase { /// \brief The typedef for the __uint128_t type. mutable TypedefDecl *UInt128Decl; + + /// \brief The typedef for the __float128 stub type. + mutable TypeDecl *Float128StubDecl; /// \brief The typedef for the target specific predefined /// __builtin_va_list type. @@ -261,13 +271,30 @@ class ASTContext : public RefCountedBase { /// wasting space in the Decl class. llvm::DenseMap DeclAttrs; - /// \brief Keeps track of the static data member templates from which - /// static data members of class template specializations were instantiated. + /// \brief A mapping from non-redeclarable declarations in modules that were + /// merged with other declarations to the canonical declaration that they were + /// merged into. + llvm::DenseMap MergedDecls; + +public: + /// \brief A type synonym for the TemplateOrInstantiation mapping. + typedef llvm::PointerUnion + TemplateOrSpecializationInfo; + +private: + + /// \brief A mapping to contain the template or declaration that + /// a variable declaration describes or was instantiated from, + /// respectively. /// - /// This data structure stores the mapping from instantiations of static - /// data members to the static data member representations within the - /// class template from which they were instantiated along with the kind - /// of instantiation or specialization (a TemplateSpecializationKind - 1). + /// For non-templates, this value will be NULL. For variable + /// declarations that describe a variable template, this will be a + /// pointer to a VarTemplateDecl. For static data members + /// of class template specializations, this will be the + /// MemberSpecializationInfo referring to the member variable that was + /// instantiated or specialized. Thus, the mapping will keep track of + /// the static data member templates from which static data members of + /// class template specializations were instantiated. /// /// Given the following example: /// @@ -286,8 +313,8 @@ class ASTContext : public RefCountedBase { /// This mapping will contain an entry that maps from the VarDecl for /// X::value to the corresponding VarDecl for X::value (within the /// class template X) and will be marked TSK_ImplicitInstantiation. - llvm::DenseMap - InstantiatedFromStaticDataMember; + llvm::DenseMap + TemplateOrInstantiation; /// \brief Keeps track of the declaration from which a UsingDecl was /// created during instantiation. @@ -328,12 +355,15 @@ class ASTContext : public RefCountedBase { typedef llvm::TinyPtrVector CXXMethodVector; llvm::DenseMap OverriddenMethods; - /// \brief Mapping from each declaration context to its corresponding lambda - /// mangling context. - llvm::DenseMap LambdaMangleContexts; + /// \brief Mapping from each declaration context to its corresponding + /// mangling numbering context (used for constructs like lambdas which + /// need to be consistently numbered for the mangler). + llvm::DenseMap + MangleNumberingContexts; - llvm::DenseMap UnnamedMangleContexts; - llvm::DenseMap UnnamedMangleNumbers; + /// \brief Side-table of mangling numbers for declarations which rarely + /// need them (like static local vars). + llvm::DenseMap MangleNumbers; /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. @@ -368,6 +398,10 @@ class ASTContext : public RefCountedBase { /// \brief The logical -> physical address space map. const LangAS::Map *AddrSpaceMap; + /// \brief Address space map mangling must be used with language specific + /// address spaces (e.g. OpenCL/CUDA) + bool AddrSpaceMapMangling; + friend class ASTDeclReader; friend class ASTReader; friend class ASTWriter; @@ -419,22 +453,7 @@ public: return getParents(ast_type_traits::DynTypedNode::create(Node)); } - ParentVector getParents(const ast_type_traits::DynTypedNode &Node) { - assert(Node.getMemoizationData() && - "Invariant broken: only nodes that support memoization may be " - "used in the parent map."); - if (!AllParents) { - // We always need to run over the whole translation unit, as - // hasAncestor can escape any subtree. - AllParents.reset( - ParentMapASTVisitor::buildMap(*getTranslationUnitDecl())); - } - ParentMap::const_iterator I = AllParents->find(Node.getMemoizationData()); - if (I == AllParents->end()) { - return ParentVector(); - } - return I->second; - } + ParentVector getParents(const ast_type_traits::DynTypedNode &Node); const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; @@ -451,7 +470,7 @@ public: return BumpAlloc; } - void *Allocate(unsigned Size, unsigned Align = 8) const { + void *Allocate(size_t Size, unsigned Align = 8) const { return BumpAlloc.Allocate(Size, Align); } void Deallocate(void *Ptr) const { } @@ -470,6 +489,19 @@ public: const TargetInfo &getTargetInfo() const { return *Target; } + /// getIntTypeForBitwidth - + /// sets integer QualTy according to specified details: + /// bitwidth, signed/unsigned. + /// Returns empty type if there is no appropriate target types. + QualType getIntTypeForBitwidth(unsigned DestWidth, + unsigned Signed) const; + /// getRealTypeForBitwidth - + /// sets floating point QualTy according to specified bitwidth. + /// Returns empty type if there is no appropriate target types. + QualType getRealTypeForBitwidth(unsigned DestWidth) const; + + bool AtomicUsesUnsupportedLibcall(const AtomicExpr *E) const; + const LangOptions& getLangOpts() const { return LangOpts; } DiagnosticsEngine &getDiagnostics() const; @@ -580,7 +612,12 @@ public: /// preprocessor is not available. comments::FullComment *getCommentForDecl(const Decl *D, const Preprocessor *PP) const; - + + /// Return parsed documentation comment attached to a given declaration. + /// Returns NULL if no comment is attached. Does not look at any + /// redeclarations of the declaration. + comments::FullComment *getLocalCommentForDeclUncached(const Decl *D) const; + comments::FullComment *cloneFullComment(comments::FullComment *FC, const Decl *D) const; @@ -601,9 +638,13 @@ public: /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. + // FIXME: Remove ? MemberSpecializationInfo *getInstantiatedFromStaticDataMember( const VarDecl *Var); + TemplateOrSpecializationInfo + getTemplateOrSpecializationInfo(const VarDecl *Var); + FunctionDecl *getClassScopeSpecializationPattern(const FunctionDecl *FD); void setClassScopeSpecializationPattern(FunctionDecl *FD, @@ -615,6 +656,9 @@ public: TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); + void setTemplateOrSpecializationInfo(VarDecl *Inst, + TemplateOrSpecializationInfo TSI); + /// \brief If the given using decl \p Inst is an instantiation of a /// (possibly unresolved) using decl from a template instantiation, /// return it. @@ -632,31 +676,6 @@ public: void setInstantiatedFromUnnamedFieldDecl(FieldDecl *Inst, FieldDecl *Tmpl); - /// \brief Return \c true if \p FD is a zero-length bitfield which follows - /// the non-bitfield \p LastFD. - bool ZeroBitfieldFollowsNonBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const; - - /// \brief Return \c true if \p FD is a zero-length bitfield which follows - /// the bitfield \p LastFD. - bool ZeroBitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const; - - /// \brief Return \c true if \p FD is a bitfield which follows the bitfield - /// \p LastFD. - bool BitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const; - - /// \brief Return \c true if \p FD is not a bitfield which follows the - /// bitfield \p LastFD. - bool NonBitfieldFollowsBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const; - - /// \brief Return \c true if \p FD is a bitfield which follows the - /// non-bitfield \p LastFD. - bool BitfieldFollowsNonBitfield(const FieldDecl *FD, - const FieldDecl *LastFD) const; - // Access to the set of methods overridden by the given C++ method. typedef CXXMethodVector::const_iterator overridden_cxx_method_iterator; overridden_cxx_method_iterator @@ -732,7 +751,15 @@ public: return import_iterator(FirstLocalImport); } import_iterator local_import_end() const { return import_iterator(); } - + + Decl *getPrimaryMergedDecl(Decl *D) { + Decl *Result = MergedDecls.lookup(D); + return Result ? Result : D; + } + void setPrimaryMergedDecl(Decl *D, Decl *Primary) { + MergedDecls[D] = Primary; + } + TranslationUnitDecl *getTranslationUnitDecl() const { return TUDecl; } @@ -740,7 +767,8 @@ public: CanQualType VoidTy; CanQualType BoolTy; CanQualType CharTy; - CanQualType WCharTy; // [C++ 3.9.1p5], integer type in C99. + CanQualType WCharTy; // [C++ 3.9.1p5]. + CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99. CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions. CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. @@ -809,6 +837,9 @@ public: /// \brief Retrieve the declaration for the 128-bit unsigned integer type. TypedefDecl *getUInt128Decl() const; + + /// \brief Retrieve the declaration for a 128-bit float stub type. + TypeDecl *getFloat128StubType() const; //===--------------------------------------------------------------------===// // Type Constructors @@ -884,6 +915,14 @@ public: return CanQualType::CreateUnsafe(getPointerType((QualType) T)); } + /// \brief Return the uniqued reference to the decayed version of the given + /// type. Can only be called on array and function types which decay to + /// pointer types. + QualType getDecayedType(QualType T) const; + CanQualType getDecayedType(CanQualType T) const { + return CanQualType::CreateUnsafe(getDecayedType((QualType) T)); + } + /// \brief Return the uniqued reference to the atomic type for the specified /// type. QualType getAtomicType(QualType T) const; @@ -1104,7 +1143,7 @@ public: /// \brief C++11 deduced auto type. QualType getAutoType(QualType DeducedType, bool IsDecltypeAuto, - bool IsDependent = false) const; + bool IsDependent) const; /// \brief C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; @@ -1130,11 +1169,15 @@ public: /// . CanQualType getUIntMaxType() const; - /// \brief In C++, this returns the unique wchar_t type. In C99, this - /// returns a type compatible with the type defined in as defined - /// by the target. + /// \brief Return the unique wchar_t type available in C++ (and available as + /// __wchar_t as a Microsoft extension). QualType getWCharType() const { return WCharTy; } + /// \brief Return the type of wide characters. In C++, this returns the + /// unique wchar_t type. In C99, this returns a type compatible with the type + /// defined in as defined by the target. + QualType getWideCharType() const { return WideCharTy; } + /// \brief Return the type of "signed wchar_t". /// /// Used when in C++, as a GCC extension. @@ -1607,14 +1650,17 @@ public: /// \pre \p D must not be a bitfield type, as bitfields do not have a valid /// alignment. /// - /// If \p RefAsPointee, references are treated like their underlying type - /// (for alignof), else they're treated like pointers (for CodeGen). - CharUnits getDeclAlign(const Decl *D, bool RefAsPointee = false) const; + /// If \p ForAlignof, references are treated like their underlying type + /// and large arrays don't get any special treatment. If not \p ForAlignof + /// it computes the value expected by CodeGen: references are treated like + /// pointers and large arrays get extra alignment. + CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const; /// \brief Get or compute information about the layout of the specified /// record (struct/union/class) \p D, which indicates its size and field /// position information. const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; + const ASTRecordLayout *BuildMicrosoftASTRecordLayout(const RecordDecl *D) const; /// \brief Get or compute information about the layout of the specified /// Objective-C interface. @@ -1721,6 +1767,9 @@ public: getCanonicalType(T2).getTypePtr(); } + bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, + const ObjCMethodDecl *MethodImp); + bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); /// \brief Retrieves the "canonical" nested name specifier for a @@ -1749,19 +1798,9 @@ public: NestedNameSpecifier * getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const; - /// \brief Retrieves the default calling convention to use for - /// C++ instance methods. - CallingConv getDefaultCXXMethodCallConv(bool isVariadic); - - /// \brief Retrieves the canonical representation of the given - /// calling convention. - CallingConv getCanonicalCallConv(CallingConv CC) const; - - /// \brief Determines whether two calling conventions name the same - /// calling convention. - bool isSameCallConv(CallingConv lcc, CallingConv rcc) { - return (getCanonicalCallConv(lcc) == getCanonicalCallConv(rcc)); - } + /// \brief Retrieves the default calling convention for the current target. + CallingConv getDefaultCallingConvention(bool isVariadic, + bool IsCXXMethod) const; /// \brief Retrieves the "canonical" template name that refers to a /// given template. @@ -1899,6 +1938,12 @@ public: return (*AddrSpaceMap)[AS - LangAS::Offset]; } + bool addressSpaceMapManglingFor(unsigned AS) const { + return AddrSpaceMapMangling || + AS < LangAS::Offset || + AS >= LangAS::Offset + LangAS::Count; + } + private: // Helper for integer ordering unsigned getIntegerRank(const Type *T) const; @@ -1925,7 +1970,6 @@ public: bool isObjCSelType(QualType T) const { return T == getObjCSelType(); } - bool QualifiedIdConformsQualifiedId(QualType LHS, QualType RHS); bool ObjCQualifiedIdTypesAreCompatible(QualType LHS, QualType RHS, bool ForCompare); @@ -2092,12 +2136,15 @@ public: /// it is not used. bool DeclMustBeEmitted(const Decl *D); - void addUnnamedTag(const TagDecl *Tag); - int getUnnamedTagManglingNumber(const TagDecl *Tag) const; + void setManglingNumber(const NamedDecl *ND, unsigned Number); + unsigned getManglingNumber(const NamedDecl *ND) const; + + /// \brief Retrieve the context for computing mangling numbers in the given + /// DeclContext. + MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); + + MangleNumberingContext *createMangleNumberingContext() const; - /// \brief Retrieve the lambda mangling number for a lambda expression. - unsigned getLambdaManglingNumber(CXXMethodDecl *CallOperator); - /// \brief Used by ParmVarDecl to store on the side the /// index of the parameter when it exceeds the size of the normal bitfield. void setParameterIndex(const ParmVarDecl *D, unsigned index); @@ -2105,7 +2152,12 @@ public: /// \brief Used by ParmVarDecl to retrieve on the side the /// index of the parameter when it exceeds the size of the normal bitfield. unsigned getParameterIndex(const ParmVarDecl *D) const; - + + /// \brief Get the storage for the constant value of a materialized temporary + /// of static storage duration. + APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, + bool MayCreate); + //===--------------------------------------------------------------------===// // Statistics //===--------------------------------------------------------------------===// @@ -2197,93 +2249,21 @@ private: const ObjCImplementationDecl *Impl) const; private: - /// \brief A set of deallocations that should be performed when the + /// \brief A set of deallocations that should be performed when the /// ASTContext is destroyed. - SmallVector, 16> Deallocations; - + typedef llvm::SmallDenseMap > + DeallocationMap; + DeallocationMap Deallocations; + // FIXME: This currently contains the set of StoredDeclMaps used // by DeclContext objects. This probably should not be in ASTContext, // but we include it here so that ASTContext can quickly deallocate them. llvm::PointerIntPair LastSDM; - /// \brief A counter used to uniquely identify "blocks". - mutable unsigned int UniqueBlockByRefTypeID; - friend class DeclContext; friend class DeclarationNameTable; void ReleaseDeclContextMaps(); - /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their - /// parents as defined by the \c RecursiveASTVisitor. - /// - /// Note that the relationship described here is purely in terms of AST - /// traversal - there are other relationships (for example declaration context) - /// in the AST that are better modeled by special matchers. - /// - /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. - class ParentMapASTVisitor : public RecursiveASTVisitor { - public: - /// \brief Builds and returns the translation unit's parent map. - /// - /// The caller takes ownership of the returned \c ParentMap. - static ParentMap *buildMap(TranslationUnitDecl &TU) { - ParentMapASTVisitor Visitor(new ParentMap); - Visitor.TraverseDecl(&TU); - return Visitor.Parents; - } - - private: - typedef RecursiveASTVisitor VisitorBase; - - ParentMapASTVisitor(ParentMap *Parents) : Parents(Parents) { - } - - bool shouldVisitTemplateInstantiations() const { - return true; - } - bool shouldVisitImplicitCode() const { - return true; - } - // Disables data recursion. We intercept Traverse* methods in the RAV, which - // are not triggered during data recursion. - bool shouldUseDataRecursionFor(clang::Stmt *S) const { - return false; - } - - template - bool TraverseNode(T *Node, bool(VisitorBase:: *traverse) (T *)) { - if (Node == NULL) - 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. - // 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()); - ParentStack.push_back(ast_type_traits::DynTypedNode::create(*Node)); - bool Result = (this ->* traverse) (Node); - ParentStack.pop_back(); - return Result; - } - - bool TraverseDecl(Decl *DeclNode) { - return TraverseNode(DeclNode, &VisitorBase::TraverseDecl); - } - - bool TraverseStmt(Stmt *StmtNode) { - return TraverseNode(StmtNode, &VisitorBase::TraverseStmt); - } - - ParentMap *Parents; - llvm::SmallVector ParentStack; - - friend class RecursiveASTVisitor; - }; - llvm::OwningPtr AllParents; }; diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 64e955ea1472..1635511984dc 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, + SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define ASTSTART #include "clang/Basic/DiagnosticASTKinds.inc" #undef DIAG diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h new file mode 100644 index 000000000000..4f3279874b16 --- /dev/null +++ b/include/clang/AST/ASTFwd.h @@ -0,0 +1,28 @@ +//===--- ASTFwd.h ----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===--------------------------------------------------------------===// +/// +/// \file +/// \brief Forward declaration of all AST node types. +/// +//===-------------------------------------------------------------===// + +namespace clang { + +class Decl; +#define DECL(DERIVED, BASE) class DERIVED##Decl; +#include "clang/AST/DeclNodes.inc" +class Stmt; +#define STMT(DERIVED, BASE) class DERIVED; +#include "clang/AST/StmtNodes.inc" +class Type; +#define TYPE(DERIVED, BASE) class DERIVED##Type; +#include "clang/AST/TypeNodes.def" +class CXXCtorInitializer; + +} // end namespace clang diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 1672ab22a3de..b74c8ee1bf47 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -271,6 +271,14 @@ namespace clang { /// Subclasses can override this function to observe all of the \c From -> /// \c To declaration mappings as they are imported. virtual Decl *Imported(Decl *From, Decl *To); + + /// \brief Called by StructuralEquivalenceContext. If a RecordDecl is + /// being compared to another RecordDecl as part of import, completing the + /// other RecordDecl may trigger importation of the first RecordDecl. This + /// happens especially for anonymous structs. If the original of the second + /// RecordDecl can be found, we can complete it without the need for + /// importation, eliminating this loop. + virtual Decl *GetOriginalDecl(Decl *To) { return NULL; } /// \brief Determine whether the given types are structurally /// equivalent. diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h new file mode 100644 index 000000000000..358ac7131e40 --- /dev/null +++ b/include/clang/AST/ASTLambda.h @@ -0,0 +1,80 @@ +//===--- ASTLambda.h - Lambda Helper Functions --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file provides some common utility functions for processing +/// Lambda related AST Constructs. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_LAMBDA_H +#define LLVM_CLANG_AST_LAMBDA_H + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclTemplate.h" + +namespace clang { +inline StringRef getLambdaStaticInvokerName() { + return "__invoke"; +} +// This function returns true if M is a specialization, a template, +// or a non-generic lambda call operator. +inline bool isLambdaCallOperator(const CXXMethodDecl *MD) { + const CXXRecordDecl *LambdaClass = MD->getParent(); + if (!LambdaClass || !LambdaClass->isLambda()) return false; + return MD->getOverloadedOperator() == OO_Call; +} + +inline bool isLambdaCallOperator(const DeclContext *DC) { + if (!DC || !isa(DC)) return false; + return isLambdaCallOperator(cast(DC)); +} + +inline bool isGenericLambdaCallOperatorSpecialization(CXXMethodDecl *MD) { + if (!MD) return false; + CXXRecordDecl *LambdaClass = MD->getParent(); + if (LambdaClass && LambdaClass->isGenericLambda()) + return isLambdaCallOperator(MD) && + MD->isFunctionTemplateSpecialization(); + return false; +} + +inline bool isLambdaConversionOperator(CXXConversionDecl *C) { + return C ? C->getParent()->isLambda() : false; +} + +inline bool isLambdaConversionOperator(Decl *D) { + if (!D) return false; + if (CXXConversionDecl *Conv = dyn_cast(D)) + return isLambdaConversionOperator(Conv); + if (FunctionTemplateDecl *F = dyn_cast(D)) + if (CXXConversionDecl *Conv = + dyn_cast_or_null(F->getTemplatedDecl())) + return isLambdaConversionOperator(Conv); + return false; +} + +inline bool isGenericLambdaCallOperatorSpecialization(DeclContext *DC) { + return isGenericLambdaCallOperatorSpecialization( + dyn_cast(DC)); +} + + +// This returns the parent DeclContext ensuring that the correct +// parent DeclContext is returned for Lambdas +inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { + if (isLambdaCallOperator(DC)) + return DC->getParent()->getParent(); + else + return DC->getParent(); +} + +} // clang + +#endif // LLVM_CLANG_AST_LAMBDA_H diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 6b70285e3ad8..6d12a92c61bf 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -27,8 +27,11 @@ namespace clang { class ObjCContainerDecl; class ObjCInterfaceDecl; class ObjCPropertyDecl; + class QualType; class TagDecl; class VarDecl; + class VarTemplateDecl; + class VarTemplateSpecializationDecl; /// \brief An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its @@ -51,11 +54,20 @@ public: virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {} + /// \brief A template specialization (or partial one) was added to the + /// template declaration. + virtual void + AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, + const VarTemplateSpecializationDecl *D) {} + /// \brief A template specialization (or partial one) was added to the /// template declaration. virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) {} + /// \brief A function's return type has been deduced. + virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType); + /// \brief An implicit member got a definition. virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} @@ -78,6 +90,11 @@ public: const ObjCPropertyDecl *OrigProp, const ObjCCategoryDecl *ClassExt) {} + /// \brief A declaration is marked used which was not previously marked used. + /// + /// \param D the declaration marked used + virtual void DeclarationMarkedUsed(const Decl *D) {} + // NOTE: If new methods are added they should also be added to // MultiplexASTMutationListener. }; diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 4688b12de701..087ad5609001 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -7,22 +7,132 @@ // //===----------------------------------------------------------------------===// // -// Provides a dynamically typed node container that can be used to store -// an AST base node at runtime in the same storage in a type safe way. +// Provides a dynamic type identifier and a dynamically typed node container +// that can be used to store an AST base node at runtime in the same storage in +// a type safe way. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H #define LLVM_CLANG_AST_AST_TYPE_TRAITS_H +#include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" +#include "clang/Basic/LLVM.h" #include "llvm/Support/AlignOf.h" +namespace llvm { + +class raw_ostream; + +} + namespace clang { + +struct PrintingPolicy; + namespace ast_type_traits { +/// \brief Kind identifier. +/// +/// It can be constructed from any node kind and allows for runtime type +/// hierarchy checks. +/// Use getFromNodeKind() to construct them. +class ASTNodeKind { +public: + /// \brief Empty identifier. It matches nothing. + ASTNodeKind() : KindId(NKI_None) {} + + /// \brief Construct an identifier for T. + template + static ASTNodeKind getFromNodeKind() { + return ASTNodeKind(KindToKindId::Id); + } + + /// \brief Returns \c true if \c this and \c Other represent the same kind. + bool isSame(ASTNodeKind Other) const; + + /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. + bool isBaseOf(ASTNodeKind Other) const; + + /// \brief String representation of the kind. + StringRef asStringRef() const; + +private: + /// \brief Kind ids. + /// + /// Includes all possible base and derived kinds. + enum NodeKindId { + NKI_None, + NKI_CXXCtorInitializer, + NKI_TemplateArgument, + NKI_NestedNameSpecifier, + NKI_NestedNameSpecifierLoc, + NKI_QualType, + NKI_TypeLoc, + NKI_Decl, +#define DECL(DERIVED, BASE) NKI_##DERIVED##Decl, +#include "clang/AST/DeclNodes.inc" + NKI_Stmt, +#define STMT(DERIVED, BASE) NKI_##DERIVED, +#include "clang/AST/StmtNodes.inc" + NKI_Type, +#define TYPE(DERIVED, BASE) NKI_##DERIVED##Type, +#include "clang/AST/TypeNodes.def" + NKI_NumberOfKinds + }; + + /// \brief Use getFromNodeKind() to construct the kind. + ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} + + /// \brief Returns \c true if \c Base is a base kind of (or same as) \c + /// Derived. + static bool isBaseOf(NodeKindId Base, NodeKindId Derived); + + /// \brief Helper meta-function to convert a kind T to its enum value. + /// + /// This struct is specialized below for all known kinds. + template struct KindToKindId { + static const NodeKindId Id = NKI_None; + }; + + /// \brief Per kind info. + struct KindInfo { + /// \brief The id of the parent kind, or None if it has no parent. + NodeKindId ParentId; + /// \brief Name of the kind. + const char *Name; + }; + static const KindInfo AllKindInfo[NKI_NumberOfKinds]; + + NodeKindId KindId; +}; + +#define KIND_TO_KIND_ID(Class) \ + template <> struct ASTNodeKind::KindToKindId { \ + static const NodeKindId Id = NKI_##Class; \ + }; +KIND_TO_KIND_ID(CXXCtorInitializer) +KIND_TO_KIND_ID(TemplateArgument) +KIND_TO_KIND_ID(NestedNameSpecifier) +KIND_TO_KIND_ID(NestedNameSpecifierLoc) +KIND_TO_KIND_ID(QualType) +KIND_TO_KIND_ID(TypeLoc) +KIND_TO_KIND_ID(Decl) +KIND_TO_KIND_ID(Stmt) +KIND_TO_KIND_ID(Type) +#define DECL(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Decl) +#include "clang/AST/DeclNodes.inc" +#define STMT(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED) +#include "clang/AST/StmtNodes.inc" +#define TYPE(DERIVED, BASE) KIND_TO_KIND_ID(DERIVED##Type) +#include "clang/AST/TypeNodes.def" +#undef KIND_TO_KIND_ID + /// \brief A dynamically typed AST node container. /// /// Stores an AST node in a type safe way. This allows writing code that @@ -32,7 +142,7 @@ namespace ast_type_traits { /// Use \c create(Node) to create a \c DynTypedNode from an AST node, /// and \c get() to retrieve the node as type T if the types match. /// -/// See \c NodeTypeTag for which node base types are currently supported; +/// See \c ASTNodeKind for which node base types are currently supported; /// You can create DynTypedNodes for all nodes in the inheritance hierarchy of /// the supported base types. class DynTypedNode { @@ -49,15 +159,15 @@ public: /// convertible to \c T. /// /// For types that have identity via their pointer in the AST - /// (like \c Stmt and \c Decl) the returned pointer points to the - /// referenced AST node. + /// (like \c Stmt, \c Decl, \c Type and \c NestedNameSpecifier) the returned + /// pointer points to the referenced AST node. /// For other types (like \c QualType) the value is stored directly /// in the \c DynTypedNode, and the returned pointer points at /// the storage inside DynTypedNode. For those nodes, do not /// use the pointer outside the scope of the DynTypedNode. template const T *get() const { - return BaseConverter::get(Tag, Storage.buffer); + return BaseConverter::get(NodeKind, Storage.buffer); } /// \brief Returns a pointer that identifies the stored AST node. @@ -67,142 +177,171 @@ public: /// method returns NULL. const void *getMemoizationData() const; + /// \brief Prints the node to the given output stream. + void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; + + /// \brief Dumps the node to the given output stream. + void dump(llvm::raw_ostream &OS, SourceManager &SM) const; + + /// \brief For nodes which represent textual entities in the source code, + /// return their SourceRange. For all other nodes, return SourceRange(). + SourceRange getSourceRange() const; + + /// @{ + /// \brief Imposes an order on \c DynTypedNode. + /// + /// Supports comparison of nodes that support memoization. + /// FIXME: Implement comparsion for other node types (currently + /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). + bool operator<(const DynTypedNode &Other) const { + assert(getMemoizationData() && Other.getMemoizationData()); + return getMemoizationData() < Other.getMemoizationData(); + } + bool operator==(const DynTypedNode &Other) const { + // Nodes with different types cannot be equal. + if (!NodeKind.isSame(Other.NodeKind)) + return false; + + // FIXME: Implement for other types. + if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) { + return *get() == *Other.get(); + } + assert(getMemoizationData() && Other.getMemoizationData()); + return getMemoizationData() == Other.getMemoizationData(); + } + bool operator!=(const DynTypedNode &Other) const { + return !operator==(Other); + } + /// @} + private: /// \brief Takes care of converting from and to \c T. template struct BaseConverter; - /// \brief Supported base node types. - enum NodeTypeTag { - NT_Decl, - NT_Stmt, - NT_NestedNameSpecifier, - NT_NestedNameSpecifierLoc, - NT_QualType, - NT_Type, - NT_TypeLoc - } Tag; + /// \brief Converter that uses dyn_cast from a stored BaseT*. + template struct DynCastPtrConverter { + static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) + return dyn_cast(*reinterpret_cast(Storage)); + return NULL; + } + static DynTypedNode create(const BaseT &Node) { + DynTypedNode Result; + Result.NodeKind = ASTNodeKind::getFromNodeKind(); + new (Result.Storage.buffer) const BaseT * (&Node); + return Result; + } + }; + + /// \brief Converter that stores T* (by pointer). + template struct PtrConverter { + static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) + return *reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const T &Node) { + DynTypedNode Result; + Result.NodeKind = ASTNodeKind::getFromNodeKind(); + new (Result.Storage.buffer) const T * (&Node); + return Result; + } + }; + + /// \brief Converter that stores T (by value). + template struct ValueConverter { + static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + if (ASTNodeKind::getFromNodeKind().isSame(NodeKind)) + return reinterpret_cast(Storage); + return NULL; + } + static DynTypedNode create(const T &Node) { + DynTypedNode Result; + Result.NodeKind = ASTNodeKind::getFromNodeKind(); + new (Result.Storage.buffer) T(Node); + return Result; + } + }; + + ASTNodeKind NodeKind; /// \brief Stores the data of the node. /// - /// Note that we can store \c Decls and \c Stmts by pointer as they are - /// guaranteed to be unique pointers pointing to dedicated storage in the - /// AST. \c QualTypes on the other hand do not have storage or unique + /// Note that we can store \c Decls, \c Stmts, \c Types, + /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are + /// guaranteed to be unique pointers pointing to dedicated storage in the AST. + /// \c QualTypes, \c NestedNameSpecifierLocs, \c TypeLocs and + /// \c TemplateArguments on the other hand do not have storage or unique /// pointers and thus need to be stored by value. - llvm::AlignedCharArrayUnion Storage; + typedef llvm::AlignedCharArrayUnion< + Decl *, Stmt *, Type *, NestedNameSpecifier *, CXXCtorInitializer *> + KindsByPointer; + llvm::AlignedCharArrayUnion + Storage; }; -// FIXME: Pull out abstraction for the following. -template struct DynTypedNode::BaseConverter >::type> { - static const T *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_Decl) - return dyn_cast(*reinterpret_cast(Storage)); - return NULL; - } - static DynTypedNode create(const Decl &Node) { - DynTypedNode Result; - Result.Tag = NT_Decl; - new (Result.Storage.buffer) const Decl*(&Node); - return Result; - } -}; -template struct DynTypedNode::BaseConverter >::type> { - static const T *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_Stmt) - return dyn_cast(*reinterpret_cast(Storage)); - return NULL; - } - static DynTypedNode create(const Stmt &Node) { - DynTypedNode Result; - Result.Tag = NT_Stmt; - new (Result.Storage.buffer) const Stmt*(&Node); - return Result; - } -}; -template struct DynTypedNode::BaseConverter >::type> { - static const T *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_Type) - return dyn_cast(*reinterpret_cast(Storage)); - return NULL; - } - static DynTypedNode create(const Type &Node) { - DynTypedNode Result; - Result.Tag = NT_Type; - new (Result.Storage.buffer) const Type*(&Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter { - static const NestedNameSpecifier *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_NestedNameSpecifier) - return *reinterpret_cast(Storage); - return NULL; - } - static DynTypedNode create(const NestedNameSpecifier &Node) { - DynTypedNode Result; - Result.Tag = NT_NestedNameSpecifier; - new (Result.Storage.buffer) const NestedNameSpecifier*(&Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter { - static const NestedNameSpecifierLoc *get(NodeTypeTag Tag, - const char Storage[]) { - if (Tag == NT_NestedNameSpecifierLoc) - return reinterpret_cast(Storage); - return NULL; - } - static DynTypedNode create(const NestedNameSpecifierLoc &Node) { - DynTypedNode Result; - Result.Tag = NT_NestedNameSpecifierLoc; - new (Result.Storage.buffer) NestedNameSpecifierLoc(Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter { - static const QualType *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_QualType) - return reinterpret_cast(Storage); - return NULL; - } - static DynTypedNode create(const QualType &Node) { - DynTypedNode Result; - Result.Tag = NT_QualType; - new (Result.Storage.buffer) QualType(Node); - return Result; - } -}; -template<> struct DynTypedNode::BaseConverter { - static const TypeLoc *get(NodeTypeTag Tag, const char Storage[]) { - if (Tag == NT_TypeLoc) - return reinterpret_cast(Storage); - return NULL; - } - static DynTypedNode create(const TypeLoc &Node) { - DynTypedNode Result; - Result.Tag = NT_TypeLoc; - new (Result.Storage.buffer) TypeLoc(Node); - return Result; - } -}; +template +struct DynTypedNode::BaseConverter< + T, typename llvm::enable_if >::type> : public DynCastPtrConverter {}; + +template +struct DynTypedNode::BaseConverter< + T, typename llvm::enable_if >::type> : public DynCastPtrConverter {}; + +template +struct DynTypedNode::BaseConverter< + T, typename llvm::enable_if >::type> : public DynCastPtrConverter {}; + +template <> +struct DynTypedNode::BaseConverter< + NestedNameSpecifier, void> : public PtrConverter {}; + +template <> +struct DynTypedNode::BaseConverter< + CXXCtorInitializer, void> : public PtrConverter {}; + +template <> +struct DynTypedNode::BaseConverter< + TemplateArgument, void> : public ValueConverter {}; + +template <> +struct DynTypedNode::BaseConverter< + NestedNameSpecifierLoc, + void> : public ValueConverter {}; + +template <> +struct DynTypedNode::BaseConverter : public ValueConverter {}; + +template <> +struct DynTypedNode::BaseConverter< + TypeLoc, void> : public ValueConverter {}; + // The only operation we allow on unsupported types is \c get. // This allows to conveniently use \c DynTypedNode when having an arbitrary // AST node that is not supported, but prevents misuse - a user cannot create // a DynTypedNode from arbitrary types. template struct DynTypedNode::BaseConverter { - static const T *get(NodeTypeTag Tag, const char Storage[]) { return NULL; } + static const T *get(ASTNodeKind NodeKind, const char Storage[]) { + return NULL; + } }; inline const void *DynTypedNode::getMemoizationData() const { - switch (Tag) { - case NT_Decl: return BaseConverter::get(Tag, Storage.buffer); - case NT_Stmt: return BaseConverter::get(Tag, Storage.buffer); - default: return NULL; - }; + if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) { + return BaseConverter::get(NodeKind, Storage.buffer); + } else if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) { + return BaseConverter::get(NodeKind, Storage.buffer); + } else if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) { + return BaseConverter::get(NodeKind, Storage.buffer); + } else if (ASTNodeKind::getFromNodeKind().isBaseOf(NodeKind)) { + return BaseConverter::get(NodeKind, Storage.buffer); + } + return NULL; } } // end namespace ast_type_traits diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h index 5a56b4d2b46d..e8be67006c5b 100644 --- a/include/clang/AST/ASTUnresolvedSet.h +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -22,12 +22,21 @@ namespace clang { /// \brief An UnresolvedSet-like class which uses the ASTContext's allocator. class ASTUnresolvedSet { - typedef ASTVector DeclsTy; + struct DeclsTy : ASTVector { + DeclsTy() {} + DeclsTy(ASTContext &C, unsigned N) : ASTVector(C, N) {} + + bool isLazy() const { return getTag(); } + void setLazy(bool Lazy) { setTag(Lazy); } + }; + DeclsTy Decls; ASTUnresolvedSet(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; void operator=(const ASTUnresolvedSet &) LLVM_DELETED_FUNCTION; + friend class LazyASTUnresolvedSet; + public: ASTUnresolvedSet() {} ASTUnresolvedSet(ASTContext &C, unsigned N) : Decls(C, N) {} @@ -48,7 +57,7 @@ public: /// Replaces the given declaration with the new one, once. /// /// \return true if the set changed - bool replace(const NamedDecl* Old, NamedDecl *New, AccessSpecifier AS) { + bool replace(const NamedDecl *Old, NamedDecl *New, AccessSpecifier AS) { for (DeclsTy::iterator I = Decls.begin(), E = Decls.end(); I != E; ++I) { if (I->getDecl() == Old) { I->set(New, AS); @@ -58,10 +67,7 @@ public: return false; } - void erase(unsigned I) { - Decls[I] = Decls.back(); - Decls.pop_back(); - } + void erase(unsigned I) { Decls[I] = Decls.pop_back_val(); } void clear() { Decls.clear(); } @@ -79,7 +85,29 @@ public: DeclAccessPair &operator[](unsigned I) { return Decls[I]; } const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; } }; - + +/// \brief An UnresolvedSet-like class that might not have been loaded from the +/// external AST source yet. +class LazyASTUnresolvedSet { + mutable ASTUnresolvedSet Impl; + + void getFromExternalSource(ASTContext &C) const; + +public: + ASTUnresolvedSet &get(ASTContext &C) const { + if (Impl.Decls.isLazy()) + getFromExternalSource(C); + return Impl; + } + + void reserve(ASTContext &C, unsigned N) { Impl.reserve(C, N); } + void addLazyDecl(ASTContext &C, uintptr_t ID, AccessSpecifier AS) { + assert(Impl.empty() || Impl.Decls.isLazy()); + Impl.Decls.setLazy(true); + Impl.addDecl(C, reinterpret_cast(ID << 2), AS); + } +}; + } // namespace clang #endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index 669e50dbeb87..6db918eaa631 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -55,16 +55,24 @@ namespace clang { template class ASTVector { - T *Begin, *End, *Capacity; +private: + T *Begin, *End; + llvm::PointerIntPair Capacity; void setEnd(T *P) { this->End = P; } +protected: + // Make a tag bit available to users of this class. + // FIXME: This is a horrible hack. + bool getTag() const { return Capacity.getInt(); } + void setTag(bool B) { Capacity.setInt(B); } + public: // Default ctor - Initialize to empty. - ASTVector() : Begin(NULL), End(NULL), Capacity(NULL) { } + ASTVector() : Begin(0), End(0), Capacity(0, false) {} - ASTVector(ASTContext &C, unsigned N) - : Begin(NULL), End(NULL), Capacity(NULL) { + ASTVector(const ASTContext &C, unsigned N) + : Begin(0), End(0), Capacity(0, false) { reserve(C, N); } @@ -155,8 +163,8 @@ public: return const_pointer(Begin); } - void push_back(const_reference Elt, ASTContext &C) { - if (End < Capacity) { + void push_back(const_reference Elt, const ASTContext &C) { + if (End < this->capacity_ptr()) { Retry: new (End) T(Elt); ++End; @@ -166,19 +174,19 @@ public: goto Retry; } - void reserve(ASTContext &C, unsigned N) { - if (unsigned(Capacity-Begin) < N) + void reserve(const ASTContext &C, unsigned N) { + if (unsigned(this->capacity_ptr()-Begin) < N) grow(C, N); } /// capacity - Return the total number of elements in the currently allocated /// buffer. - size_t capacity() const { return Capacity - Begin; } + size_t capacity() const { return this->capacity_ptr() - Begin; } /// append - Add the specified range to the end of the SmallVector. /// template - void append(ASTContext &C, in_iter in_start, in_iter in_end) { + void append(const ASTContext &C, in_iter in_start, in_iter in_end) { size_type NumInputs = std::distance(in_start, in_end); if (NumInputs == 0) @@ -197,7 +205,7 @@ public: /// append - Add the specified range to the end of the SmallVector. /// - void append(ASTContext &C, size_type NumInputs, const T &Elt) { + void append(const ASTContext &C, size_type NumInputs, const T &Elt) { // Grow allocated space if needed. if (NumInputs > size_type(this->capacity_ptr()-this->end())) this->grow(C, this->size()+NumInputs); @@ -214,13 +222,13 @@ public: std::uninitialized_copy(I, E, Dest); } - iterator insert(ASTContext &C, iterator I, const T &Elt) { + iterator insert(const ASTContext &C, iterator I, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. - push_back(Elt); + push_back(Elt, C); return this->end()-1; } - if (this->EndX < this->CapacityX) { + if (this->End < this->capacity_ptr()) { Retry: new (this->end()) T(this->back()); this->setEnd(this->end()+1); @@ -235,7 +243,7 @@ public: goto Retry; } - iterator insert(ASTContext &C, iterator I, size_type NumToInsert, + iterator insert(const ASTContext &C, iterator I, size_type NumToInsert, const T &Elt) { if (I == this->end()) { // Important special case for empty vector. append(C, NumToInsert, Elt); @@ -284,7 +292,7 @@ public: } template - iterator insert(ASTContext &C, iterator I, ItTy From, ItTy To) { + iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) { if (I == this->end()) { // Important special case for empty vector. append(C, From, To); return this->end()-1; @@ -335,7 +343,7 @@ public: return I; } - void resize(ASTContext &C, unsigned N, const T &NV) { + void resize(const ASTContext &C, unsigned N, const T &NV) { if (N < this->size()) { this->destroy_range(this->begin()+N, this->end()); this->setEnd(this->begin()+N); @@ -350,7 +358,7 @@ public: private: /// grow - double the size of the allocated memory, guaranteeing space for at /// least one more element or MinSize if specified. - void grow(ASTContext &C, size_type MinSize = 1); + void grow(const ASTContext &C, size_type MinSize = 1); void construct_range(T *S, T *E, const T &Elt) { for (; S != E; ++S) @@ -365,13 +373,16 @@ private: } protected: - iterator capacity_ptr() { return (iterator)this->Capacity; } + const_iterator capacity_ptr() const { + return (iterator) Capacity.getPointer(); + } + iterator capacity_ptr() { return (iterator)Capacity.getPointer(); } }; // Define this out-of-line to dissuade the C++ compiler from inlining it. template -void ASTVector::grow(ASTContext &C, size_t MinSize) { - size_t CurCapacity = Capacity-Begin; +void ASTVector::grow(const ASTContext &C, size_t MinSize) { + size_t CurCapacity = this->capacity(); size_t CurSize = size(); size_t NewCapacity = 2*CurCapacity; if (NewCapacity < MinSize) @@ -394,7 +405,7 @@ void ASTVector::grow(ASTContext &C, size_t MinSize) { // ASTContext never frees any memory. Begin = NewElts; End = NewElts+CurSize; - Capacity = Begin+NewCapacity; + Capacity.setPointer(Begin+NewCapacity); } } // end: clang namespace diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 27dcef2a1e98..7dbf41350a0f 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_ATTR_H #include "clang/AST/AttrIterator.h" +#include "clang/AST/Decl.h" #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" @@ -145,7 +146,7 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { // Relies on relative order of enum emission with respect to param attrs. - return (A->getKind() <= attr::LAST_MS_INHERITABLE && + return (A->getKind() <= attr::LAST_MS_INHERITANCE && A->getKind() > attr::LAST_INHERITABLE_PARAM); } }; diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 2983e04cda34..dbe4ad0f5a1d 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -287,9 +287,9 @@ public: // Iterate over the set of overriding virtual methods in a given // subobject. - typedef SmallVector::iterator + typedef SmallVectorImpl::iterator overriding_iterator; - typedef SmallVector::const_iterator + typedef SmallVectorImpl::const_iterator overriding_const_iterator; // Add a new overriding method for a particular subobject. diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 946075739d06..9c699b7e0ae2 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -81,7 +81,7 @@ public: operator QualType() const { return Stored; } /// \brief Implicit conversion to bool. - operator bool() const { return !isNull(); } + LLVM_EXPLICIT operator bool() const { return !isNull(); } bool isNull() const { return Stored.isNull(); diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 082c672c2191..09ff6828ef5c 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -19,21 +19,20 @@ #include "llvm/Support/MathExtras.h" namespace clang { - + /// CharUnits - This is an opaque type for sizes expressed in character units. - /// Instances of this type represent a quantity as a multiple of the size + /// Instances of this type represent a quantity as a multiple of the size /// of the standard C type, char, on the target architecture. As an opaque /// type, CharUnits protects you from accidentally combining operations on - /// quantities in bit units and character units. + /// quantities in bit units and character units. + /// + /// In both C and C++, an object of type 'char', 'signed char', or 'unsigned + /// char' occupies exactly one byte, so 'character unit' and 'byte' refer to + /// the same quantity of storage. However, we use the term 'character unit' + /// rather than 'byte' to avoid an implication that a character unit is + /// exactly 8 bits. /// - /// It should be noted that characters and bytes are distinct concepts. Bytes - /// refer to addressable units of data storage on the target machine, and - /// characters are members of a set of elements used for the organization, - /// control, or representation of data. According to C99, bytes are allowed - /// to exceed characters in size, although currently, clang only supports - /// architectures where the two are the same size. - /// - /// For portability, never assume that a target character is 8 bits wide. Use + /// For portability, never assume that a target character is 8 bits wide. Use /// CharUnit values wherever you calculate sizes, offsets, or alignments /// in character units. class CharUnits { diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index c02a82f0fa55..28849f58a8ec 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -699,7 +699,10 @@ private: unsigned ParamIndex; public: - enum { InvalidParamIndex = ~0U }; + enum LLVM_ENUM_INT_TYPE(unsigned) { + InvalidParamIndex = ~0U, + VarArgParamIndex = ~0U/*InvalidParamIndex*/ - 1U + }; ParamCommandComment(SourceLocation LocBegin, SourceLocation LocEnd, @@ -755,14 +758,25 @@ public: return ParamIndex != InvalidParamIndex; } + bool isVarArgParam() const LLVM_READONLY { + return ParamIndex == VarArgParamIndex; + } + + void setIsVarArgParam() { + ParamIndex = VarArgParamIndex; + assert(isParamIndexValid()); + } + unsigned getParamIndex() const LLVM_READONLY { assert(isParamIndexValid()); + assert(!isVarArgParam()); return ParamIndex; } void setParamIndex(unsigned Index) { ParamIndex = Index; assert(isParamIndexValid()); + assert(!isVarArgParam()); } }; @@ -1097,10 +1111,6 @@ public: return ThisDeclInfo; } - DeclInfo *getThisDeclInfo() const LLVM_READONLY { - return ThisDeclInfo; - } - ArrayRef getBlocks() const { return Blocks; } }; diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index d1f5209d1eef..dde7a1442fe1 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -67,6 +67,9 @@ struct CommandInfo { /// a template parameter (\\tparam or an alias). unsigned IsTParamCommand : 1; + /// True if this command is \\throws or an alias. + unsigned IsThrowsCommand : 1; + /// True if this command is \\deprecated or an alias. unsigned IsDeprecatedCommand : 1; @@ -142,6 +145,8 @@ public: llvm_unreachable("the command should be known"); } + const CommandInfo *getTypoCorrectCommandInfo(StringRef Typo) const; + const CommandInfo *getCommandInfo(unsigned CommandID) const; const CommandInfo *registerUnknownCommand(StringRef CommandName); diff --git a/include/clang/AST/CommentCommands.td b/include/clang/AST/CommentCommands.td index 8c88494e9ae4..ed323daa9f8b 100644 --- a/include/clang/AST/CommentCommands.td +++ b/include/clang/AST/CommentCommands.td @@ -15,6 +15,7 @@ class Command { bit IsReturnsCommand = 0; bit IsParamCommand = 0; bit IsTParamCommand = 0; + bit IsThrowsCommand = 0; bit IsDeprecatedCommand = 0; bit IsHeaderfileCommand = 0; @@ -109,6 +110,10 @@ def Tparam : BlockCommand<"tparam"> { let IsTParamCommand = 1; } // HeaderDoc command for template parameter documentation. def Templatefield : BlockCommand<"templatefield"> { let IsTParamCommand = 1; } +def Throws : BlockCommand<"throws"> { let IsThrowsCommand = 1; } +def Throw : BlockCommand<"throw"> { let IsThrowsCommand = 1; } +def Exception : BlockCommand<"exception"> { let IsThrowsCommand = 1; } + def Deprecated : BlockCommand<"deprecated"> { let IsEmptyParagraphAllowed = 1; let IsDeprecatedCommand = 1; @@ -200,11 +205,17 @@ def Mainpage : VerbatimLineCommand<"mainpage">; def Subpage : VerbatimLineCommand<"subpage">; def Ref : VerbatimLineCommand<"ref">; +def Relates : VerbatimLineCommand<"relates">; +def Related : VerbatimLineCommand<"related">; +def RelatesAlso : VerbatimLineCommand<"relatesalso">; +def RelatedAlso : VerbatimLineCommand<"relatedalso">; + //===----------------------------------------------------------------------===// // DeclarationVerbatimLineCommand //===----------------------------------------------------------------------===// // Doxygen commands. +def Def : DeclarationVerbatimLineCommand<"def">; def Fn : DeclarationVerbatimLineCommand<"fn">; def Namespace : DeclarationVerbatimLineCommand<"namespace">; def Overload : DeclarationVerbatimLineCommand<"overload">; diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h index 6e8941057994..312da065ff59 100644 --- a/include/clang/AST/CommentDiagnostic.h +++ b/include/clang/AST/CommentDiagnostic.h @@ -16,7 +16,7 @@ namespace clang { namespace diag { enum { #define DIAG(ENUM,FLAGS,DEFAULT_MAPPING,DESC,GROUP,\ - SFINAE,ACCESS,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, + SFINAE,NOWERROR,SHOWINSYSHEADER,CATEGORY) ENUM, #define COMMENTSTART #include "clang/Basic/DiagnosticCommentKinds.inc" #undef DIAG diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index d6a1072786ed..7e008131d205 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -61,10 +61,8 @@ class Parser { void consumeToken() { if (MoreLATokens.empty()) L.lex(Tok); - else { - Tok = MoreLATokens.back(); - MoreLATokens.pop_back(); - } + else + Tok = MoreLATokens.pop_back_val(); } void putBack(const Token &OldTok) { diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 15e454dcc389..39109602b148 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -58,9 +58,6 @@ class Sema { /// AST node for the \\brief command and its aliases. const BlockCommandComment *BriefCommand; - /// AST node for the \\returns command and its aliases. - const BlockCommandComment *ReturnsCommand; - /// AST node for the \\headerfile command. const BlockCommandComment *HeaderfileCommand; @@ -211,7 +208,11 @@ public: bool isFunctionDecl(); bool isAnyFunctionDecl(); + + /// \returns \c true if declaration that this comment is attached to declares + /// a function pointer. bool isFunctionPointerVarDecl(); + bool isFunctionOrMethodVariadic(); bool isObjCMethodDecl(); bool isObjCPropertyDecl(); bool isTemplateOrSpecialization(); @@ -220,6 +221,8 @@ public: bool isUnionDecl(); bool isObjCInterfaceDecl(); bool isObjCProtocolDecl(); + bool isClassTemplateDecl(); + bool isFunctionTemplateDecl(); ArrayRef getParamVars(); diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index a0c76c069b86..244a7b8d400c 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -24,6 +24,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/raw_ostream.h" namespace clang { struct ASTTemplateArgumentListInfo; @@ -43,6 +44,7 @@ class TemplateArgumentList; class TemplateParameterList; class TypeLoc; class UnresolvedSetImpl; +class VarTemplateDecl; /// \brief A container of type source information. /// @@ -109,7 +111,6 @@ class NamedDecl : public Decl { private: NamedDecl *getUnderlyingDeclImpl(); - void verifyLinkage() const; protected: NamedDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName N) @@ -142,7 +143,7 @@ public: // FIXME: Deprecated, move clients to getName(). std::string getNameAsString() const { return Name.getAsString(); } - void printName(raw_ostream &os) const { return Name.printName(os); } + void printName(raw_ostream &os) const { os << Name; } /// getDeclName - Get the actual, stored name of the declaration, /// which may be a special name. @@ -189,10 +190,13 @@ public: using Decl::isModulePrivate; using Decl::setModulePrivate; - + /// \brief Determine whether this declaration is hidden from name lookup. bool isHidden() const { return Hidden; } - + + /// \brief Set whether this declaration is hidden from name lookup. + void setHidden(bool Hide) { Hidden = Hide; } + /// \brief Determine whether this declaration is a C++ class member. bool isCXXClassMember() const { const DeclContext *DC = getDeclContext(); @@ -212,11 +216,24 @@ public: bool isCXXInstanceMember() const; /// \brief Determine what kind of linkage this entity has. - Linkage getLinkage() const; + /// This is not the linkage as defined by the standard or the codegen notion + /// of linkage. It is just an implementation detail that is used to compute + /// those. + Linkage getLinkageInternal() const; + + /// \brief Get the linkage from a semantic point of view. Entities in + /// anonymous namespaces are external (in c++98). + Linkage getFormalLinkage() const { + return clang::getFormalLinkage(getLinkageInternal()); + } /// \brief True if this decl has external linkage. - bool hasExternalLinkage() const { - return getLinkage() == ExternalLinkage; + bool hasExternalFormalLinkage() const { + return isExternalFormalLinkage(getLinkageInternal()); + } + + bool isExternallyVisible() const { + return clang::isExternallyVisible(getLinkageInternal()); } /// \brief Determines the visibility of this entity. @@ -256,6 +273,13 @@ public: return const_cast(this)->getUnderlyingDecl(); } + NamedDecl *getMostRecentDecl() { + return cast(static_cast(this)->getMostRecentDecl()); + } + const NamedDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; } }; @@ -351,6 +375,7 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; /// \brief Returns true if this is an anonymous namespace declaration. /// @@ -377,7 +402,7 @@ public: /// \brief Get the original (first) namespace declaration. NamespaceDecl *getOriginalNamespace() { - if (isFirstDeclaration()) + if (isFirstDecl()) return this; return AnonOrFirstNamespaceAndInline.getPointer(); @@ -385,7 +410,7 @@ public: /// \brief Get the original (first) namespace declaration. const NamespaceDecl *getOriginalNamespace() const { - if (isFirstDeclaration()) + if (isFirstDecl()) return this; return AnonOrFirstNamespaceAndInline.getPointer(); @@ -394,9 +419,7 @@ public: /// \brief Return true if this declaration is an original (first) declaration /// of the namespace. This is false for non-original (subsequent) namespace /// declarations and anonymous namespaces. - bool isOriginalNamespace() const { - return isFirstDeclaration(); - } + bool isOriginalNamespace() const { return isFirstDecl(); } /// \brief Retrieve the anonymous namespace nested inside this namespace, /// if any. @@ -689,11 +712,21 @@ private: /// \brief Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; + + /// \brief Whether this variable is the implicit variable for a lambda + /// init-capture. + unsigned IsInitCapture : 1; + + /// \brief Whether this local extern variable's previous declaration was + /// declared in the same block scope. This controls whether we should merge + /// the type of this declaration with its previous declaration. + unsigned PreviousDeclInSameBlockScope : 1; }; - enum { NumVarDeclBits = 12 }; + enum { NumVarDeclBits = 14 }; friend class ASTDeclReader; friend class StmtIteratorBase; + friend class ASTNodeImporter; protected: enum { NumParameterIndexBits = 8 }; @@ -732,15 +765,8 @@ protected: }; 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)); - AllBits = 0; - VarDeclBits.SClass = SC; - // Everything else is implicitly initialized to false. - } + SourceLocation IdLoc, IdentifierInfo *Id, QualType T, + TypeSourceInfo *TInfo, StorageClass SC); typedef Redeclarable redeclarable_base; virtual VarDecl *getNextRedeclaration() { return RedeclLink.getNext(); } @@ -757,6 +783,7 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; static VarDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -797,7 +824,8 @@ public: /// is a non-static local variable. bool hasLocalStorage() const { if (getStorageClass() == SC_None) - return !isFileVarDecl(); + // Second check is for C++11 [dcl.stc]p4. + return !isFileVarDecl() && getTSCSpec() == TSCS_unspecified; // Return true for: Auto, Register. // Return false for: Extern, Static, PrivateExtern, OpenCLWorkGroupLocal. @@ -808,7 +836,10 @@ public: /// isStaticLocal - Returns true if a variable with function scope is a /// static local variable. bool isStaticLocal() const { - return getStorageClass() == SC_Static && !isFileVarDecl(); + return (getStorageClass() == SC_Static || + // C++11 [dcl.stc]p4 + (getStorageClass() == SC_None && getTSCSpec() == TSCS_thread_local)) + && !isFileVarDecl(); } /// \brief Returns true if a variable has extern or __private_extern__ @@ -818,12 +849,19 @@ public: getStorageClass() == SC_PrivateExtern; } - /// hasGlobalStorage - Returns true for all variables that do not - /// have local storage. This includs all global variables as well - /// as static variables declared within a function. + /// \brief Returns true for all variables that do not have local storage. + /// + /// This includes all global variables as well as static variables declared + /// within a function. bool hasGlobalStorage() const { return !hasLocalStorage(); } - /// Compute the language linkage. + /// \brief Get the storage duration of this variable, per C++ [basic.stc]. + StorageDuration getStorageDuration() const { + return hasLocalStorage() ? SD_Automatic : + getTSCSpec() ? SD_Thread : SD_Static; + } + + /// \brief Compute the language linkage. LanguageLinkage getLanguageLinkage() const; /// \brief Determines whether this variable is a variable with @@ -847,7 +885,7 @@ public: bool isLocalVarDecl() const { if (getKind() != Decl::Var) return false; - if (const DeclContext *DC = getDeclContext()) + if (const DeclContext *DC = getLexicalDeclContext()) return DC->getRedeclContext()->isFunctionOrMethod(); return false; } @@ -857,7 +895,7 @@ public: bool isFunctionOrMethodVarDecl() const { if (getKind() != Decl::Var) return false; - const DeclContext *DC = getDeclContext()->getRedeclContext(); + const DeclContext *DC = getLexicalDeclContext()->getRedeclContext(); return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block; } @@ -908,10 +946,6 @@ public: return const_cast(this)->getActingDefinition(); } - /// \brief Determine whether this is a tentative definition of a - /// variable in C. - bool isTentativeDefinitionNow() const; - /// \brief Get the real (not just tentative) definition for this declaration. VarDecl *getDefinition(ASTContext &); const VarDecl *getDefinition(ASTContext &C) const { @@ -933,10 +967,11 @@ public: /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { - if (getKind() != Decl::Var) + Kind K = getKind(); + if (K == ParmVar || K == ImplicitParam) return false; - if (getDeclContext()->getRedeclContext()->isFileContext()) + if (getLexicalDeclContext()->getRedeclContext()->isFileContext()) return true; if (isStaticDataMember()) @@ -1000,20 +1035,6 @@ public: void setInit(Expr *I); - /// \brief Determine whether this variable is a reference that - /// extends the lifetime of its temporary initializer. - /// - /// A reference extends the lifetime of its temporary initializer if - /// it's initializer is an rvalue that would normally go out of scope - /// at the end of the initializer (a full expression). In such cases, - /// the reference itself takes ownership of the temporary, which will - /// be destroyed when the reference goes out of scope. For example: - /// - /// \code - /// const int &r = 1.0; // creates a temporary of type 'int' - /// \endcode - bool extendsLifetimeOfTemporary() const; - /// \brief Determine whether this variable's value can be used in a /// constant expression, according to the relevant language standard. /// This only checks properties of the declaration, and does not check @@ -1123,15 +1144,34 @@ public: bool isConstexpr() const { return VarDeclBits.IsConstexpr; } void setConstexpr(bool IC) { VarDeclBits.IsConstexpr = IC; } + /// Whether this variable is the implicit variable for a lambda init-capture. + bool isInitCapture() const { return VarDeclBits.IsInitCapture; } + void setInitCapture(bool IC) { VarDeclBits.IsInitCapture = IC; } + + /// Whether this local extern variable declaration's previous declaration + /// was declared in the same block scope. Only correct in C++. + bool isPreviousDeclInSameBlockScope() const { + return VarDeclBits.PreviousDeclInSameBlockScope; + } + void setPreviousDeclInSameBlockScope(bool Same) { + VarDeclBits.PreviousDeclInSameBlockScope = Same; + } + /// \brief If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. VarDecl *getInstantiatedFromStaticDataMember() const; - /// \brief If this variable is a static data member, determine what kind of + /// \brief If this variable is an instantiation of a variable template or a + /// static data member of a class template, determine what kind of /// template specialization or instantiation this is. TemplateSpecializationKind getTemplateSpecializationKind() const; + /// \brief If this variable is an instantiation of a variable template or a + /// static data member of a class template, determine its point of + /// instantiation. + SourceLocation getPointOfInstantiation() const; + /// \brief If this variable is an instantiation of a static data member of a /// class template specialization, retrieves the member specialization /// information. @@ -1142,6 +1182,26 @@ public: void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); + /// \brief Specify that this variable is an instantiation of the + /// static data member VD. + void setInstantiationOfStaticDataMember(VarDecl *VD, + TemplateSpecializationKind TSK); + + /// \brief Retrieves the variable template that is described by this + /// variable declaration. + /// + /// Every variable template is represented as a VarTemplateDecl and a + /// VarDecl. The former contains template properties (such as + /// the template parameter lists) while the latter contains the + /// actual description of the template's + /// contents. VarTemplateDecl::getTemplatedDecl() retrieves the + /// VarDecl that from a VarTemplateDecl, while + /// getDescribedVarTemplate() retrieves the VarTemplateDecl from + /// a VarDecl. + VarTemplateDecl *getDescribedVarTemplate() const; + + void setDescribedVarTemplate(VarTemplateDecl *Template); + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } @@ -1314,11 +1374,7 @@ public: ParmVarDeclBits.HasInheritedDefaultArg = I; } - QualType getOriginalType() const { - if (getTypeSourceInfo()) - return getTypeSourceInfo()->getType(); - return getType(); - } + QualType getOriginalType() const; /// \brief Determine whether this parameter is actually a function /// parameter pack. @@ -1517,6 +1573,7 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; static FunctionDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation NLoc, @@ -1701,6 +1758,10 @@ public: /// entry point into an executable program. bool isMain() const; + /// \brief Determines whether this function is a MSVCRT user defined entry + /// point. + bool isMSVCRTEntryPoint() const; + /// \brief Determines whether this operator new or delete is one /// of the reserved global placement operators: /// void *operator new(size_t, void *); @@ -1716,6 +1777,28 @@ public: /// This function must be an allocation or deallocation function. bool isReservedGlobalPlacementOperator() const; + /// \brief Determines whether this function is one of the replaceable + /// global allocation functions: + /// void *operator new(size_t); + /// void *operator new(size_t, const std::nothrow_t &) noexcept; + /// void *operator new[](size_t); + /// void *operator new[](size_t, const std::nothrow_t &) noexcept; + /// void operator delete(void *) noexcept; + /// void operator delete(void *, std::size_t) noexcept; [C++1y] + /// void operator delete(void *, const std::nothrow_t &) noexcept; + /// void operator delete[](void *) noexcept; + /// void operator delete[](void *, std::size_t) noexcept; [C++1y] + /// void operator delete[](void *, const std::nothrow_t &) noexcept; + /// These functions have special behavior under C++1y [expr.new]: + /// An implementation is allowed to omit a call to a replaceable global + /// allocation function. [...] + bool isReplaceableGlobalAllocationFunction() const; + + /// \brief Determine whether this function is a sized global deallocation + /// function in C++1y. If so, find and return the corresponding unsized + /// deallocation function. + FunctionDecl *getCorrespondingUnsizedGlobalDeallocationFunction() const; + /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; @@ -2039,7 +2122,7 @@ public: /// FieldDecl - An instance of this class is created by Sema::ActOnField to /// represent a member of a struct/union/class. -class FieldDecl : public DeclaratorDecl { +class FieldDecl : public DeclaratorDecl, public Mergeable { // FIXME: This can be packed into the bitfields in Decl. bool Mutable : 1; mutable unsigned CachedFieldIndex : 31; @@ -2153,6 +2236,10 @@ public: SourceRange getSourceRange() const LLVM_READONLY; + /// Retrieves the canonical declaration of this field. + FieldDecl *getCanonicalDecl() { return getFirstDecl(); } + const FieldDecl *getCanonicalDecl() const { return getFirstDecl(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } @@ -2165,7 +2252,7 @@ public: /// that is defined. For example, in "enum X {a,b}", each of a/b are /// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a /// TagType for the X EnumDecl. -class EnumConstantDecl : public ValueDecl { +class EnumConstantDecl : public ValueDecl, public Mergeable { Stmt *Init; // an integer constant expression llvm::APSInt Val; // The value. protected: @@ -2191,6 +2278,10 @@ public: SourceRange getSourceRange() const LLVM_READONLY; + /// Retrieves the canonical declaration of this enumerator. + EnumConstantDecl *getCanonicalDecl() { return getFirstDecl(); } + const EnumConstantDecl *getCanonicalDecl() const { return getFirstDecl(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == EnumConstant; } @@ -2289,14 +2380,14 @@ public: /// Base class for declarations which introduce a typedef-name. class TypedefNameDecl : public TypeDecl, public Redeclarable { virtual void anchor(); - /// UnderlyingType - This is the type the typedef is set to. - TypeSourceInfo *TInfo; + typedef std::pair ModedTInfo; + llvm::PointerUnion MaybeModedTInfo; protected: TypedefNameDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypeDecl(DK, DC, IdLoc, Id, StartLoc), TInfo(TInfo) {} + : TypeDecl(DK, DC, IdLoc, Id, StartLoc), MaybeModedTInfo(TInfo) {} typedef Redeclarable redeclarable_base; virtual TypedefNameDecl *getNextRedeclaration() { @@ -2315,26 +2406,31 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; - TypeSourceInfo *getTypeSourceInfo() const { - return TInfo; - } + bool isModed() const { return MaybeModedTInfo.is(); } - /// Retrieves the canonical declaration of this typedef-name. - TypedefNameDecl *getCanonicalDecl() { - return getFirstDeclaration(); - } - const TypedefNameDecl *getCanonicalDecl() const { - return getFirstDeclaration(); + TypeSourceInfo *getTypeSourceInfo() const { + return isModed() + ? MaybeModedTInfo.get()->first + : MaybeModedTInfo.get(); } - QualType getUnderlyingType() const { - return TInfo->getType(); + return isModed() + ? MaybeModedTInfo.get()->second + : MaybeModedTInfo.get()->getType(); } void setTypeSourceInfo(TypeSourceInfo *newType) { - TInfo = newType; + MaybeModedTInfo = newType; + } + void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) { + MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy); } + /// Retrieves the canonical declaration of this typedef-name. + TypedefNameDecl *getCanonicalDecl() { return getFirstDecl(); } + const TypedefNameDecl *getCanonicalDecl() const { return getFirstDecl(); } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { @@ -2436,6 +2532,9 @@ protected: /// This option is only enabled when modules are enabled. bool MayHaveOutOfDateDef : 1; + /// Has the full definition of this type been required by a use somewhere in + /// the TU. + bool IsCompleteDefinitionRequired : 1; private: SourceLocation RBraceLoc; @@ -2443,33 +2542,33 @@ private: // to be used for the (uncommon) case of out-of-line declarations. typedef QualifierInfo ExtInfo; - /// TypedefNameDeclOrQualifier - If the (out-of-line) tag declaration name + /// \brief If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); /// otherwise, if the tag declaration is anonymous and it is part of /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); + /// otherwise, if the tag declaration is anonymous and it is used as a + /// declaration specifier for variables, it points to the first VarDecl (used + /// for mangling); /// otherwise, it is a null (TypedefNameDecl) pointer. - llvm::PointerUnion TypedefNameDeclOrQualifier; + llvm::PointerUnion NamedDeclOrQualifier; - bool hasExtInfo() const { return TypedefNameDeclOrQualifier.is(); } - ExtInfo *getExtInfo() { return TypedefNameDeclOrQualifier.get(); } + bool hasExtInfo() const { return NamedDeclOrQualifier.is(); } + ExtInfo *getExtInfo() { return NamedDeclOrQualifier.get(); } const ExtInfo *getExtInfo() const { - return TypedefNameDeclOrQualifier.get(); + return NamedDeclOrQualifier.get(); } protected: - TagDecl(Kind DK, TagKind TK, DeclContext *DC, - SourceLocation L, IdentifierInfo *Id, - TagDecl *PrevDecl, SourceLocation StartL) - : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), - TypedefNameDeclOrQualifier((TypedefNameDecl*) 0) { + TagDecl(Kind DK, TagKind TK, DeclContext *DC, SourceLocation L, + IdentifierInfo *Id, TagDecl *PrevDecl, SourceLocation StartL) + : TypeDecl(DK, DC, L, Id, StartL), DeclContext(DK), TagDeclKind(TK), + IsCompleteDefinition(false), IsBeingDefined(false), + IsEmbeddedInDeclarator(false), IsFreeStanding(false), + IsCompleteDefinitionRequired(false), + NamedDeclOrQualifier((NamedDecl *)0) { assert((DK != Enum || TK == TTK_Enum) && "EnumDecl not matched with TTK_Enum"); - TagDeclKind = TK; - IsCompleteDefinition = false; - IsBeingDefined = false; - IsEmbeddedInDeclarator = false; - IsFreeStanding = false; - setPreviousDeclaration(PrevDecl); + setPreviousDecl(PrevDecl); } typedef Redeclarable redeclarable_base; @@ -2492,6 +2591,7 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; SourceLocation getRBraceLoc() const { return RBraceLoc; } void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } @@ -2522,6 +2622,12 @@ public: return IsCompleteDefinition; } + /// \brief Return true if this complete decl is + /// required to be complete for some existing use. + bool isCompleteDefinitionRequired() const { + return IsCompleteDefinitionRequired; + } + /// isBeingDefined - Return true if this decl is currently being defined. bool isBeingDefined() const { return IsBeingDefined; @@ -2563,6 +2669,10 @@ public: void setCompleteDefinition(bool V) { IsCompleteDefinition = V; } + void setCompleteDefinitionRequired(bool V = true) { + IsCompleteDefinitionRequired = V; + } + // FIXME: Return StringRef; const char *getKindName() const { return TypeWithKeyword::getTagTypeKindName(getTagKind()); @@ -2599,11 +2709,22 @@ public: return (getDeclName() || getTypedefNameForAnonDecl()); } + bool hasDeclaratorForAnonDecl() const { + return dyn_cast_or_null( + NamedDeclOrQualifier.get()); + } + DeclaratorDecl *getDeclaratorForAnonDecl() const { + return hasExtInfo() ? 0 : dyn_cast_or_null( + NamedDeclOrQualifier.get()); + } + TypedefNameDecl *getTypedefNameForAnonDecl() const { - return hasExtInfo() ? 0 : - TypedefNameDeclOrQualifier.get(); + return hasExtInfo() ? 0 : dyn_cast_or_null( + NamedDeclOrQualifier.get()); } + void setDeclaratorForAnonDecl(DeclaratorDecl *DD) { NamedDeclOrQualifier = DD; } + void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); /// \brief Retrieve the nested-name-specifier that qualifies the name of this @@ -2702,21 +2823,22 @@ public: return cast(TagDecl::getCanonicalDecl()); } const EnumDecl *getCanonicalDecl() const { - return cast(TagDecl::getCanonicalDecl()); + return const_cast(this)->getCanonicalDecl(); } - const EnumDecl *getPreviousDecl() const { - return cast_or_null(TagDecl::getPreviousDecl()); - } EnumDecl *getPreviousDecl() { - return cast_or_null(TagDecl::getPreviousDecl()); + return cast_or_null( + static_cast(this)->getPreviousDecl()); } - - const EnumDecl *getMostRecentDecl() const { - return cast(TagDecl::getMostRecentDecl()); + const EnumDecl *getPreviousDecl() const { + return const_cast(this)->getPreviousDecl(); } + EnumDecl *getMostRecentDecl() { - return cast(TagDecl::getMostRecentDecl()); + return cast(static_cast(this)->getMostRecentDecl()); + } + const EnumDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); } EnumDecl *getDefinition() const { @@ -2912,18 +3034,19 @@ public: IdentifierInfo *Id, RecordDecl* PrevDecl = 0); static RecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - const RecordDecl *getPreviousDecl() const { - return cast_or_null(TagDecl::getPreviousDecl()); - } RecordDecl *getPreviousDecl() { - return cast_or_null(TagDecl::getPreviousDecl()); + return cast_or_null( + static_cast(this)->getPreviousDecl()); } - - const RecordDecl *getMostRecentDecl() const { - return cast(TagDecl::getMostRecentDecl()); + const RecordDecl *getPreviousDecl() const { + return const_cast(this)->getPreviousDecl(); } + RecordDecl *getMostRecentDecl() { - return cast(TagDecl::getMostRecentDecl()); + return cast(static_cast(this)->getMostRecentDecl()); + } + const RecordDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); } bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } @@ -3106,13 +3229,17 @@ private: Capture *Captures; unsigned NumCaptures; + unsigned ManglingNumber; + Decl *ManglingContextDecl; + protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false), CapturesCXXThis(false), BlockMissingReturnType(true), IsConversionFromLambda(false), ParamInfo(0), NumParams(0), Body(0), - SignatureAsWritten(0), Captures(0), NumCaptures(0) {} + SignatureAsWritten(0), Captures(0), NumCaptures(0), + ManglingNumber(0), ManglingContextDecl(0) {} public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); @@ -3182,6 +3309,18 @@ public: const Capture *end, bool capturesCXXThis); + unsigned getBlockManglingNumber() const { + return ManglingNumber; + } + Decl *getBlockManglingContextDecl() const { + return ManglingContextDecl; + } + + void setBlockMangling(unsigned Number, Decl *Ctx) { + ManglingNumber = Number; + ManglingContextDecl = Ctx; + } + virtual SourceRange getSourceRange() const LLVM_READONLY; // Implement isa/cast/dyncast/etc. @@ -3354,7 +3493,7 @@ inline const PartialDiagnostic &operator<<(const PartialDiagnostic &PD, } template -void Redeclarable::setPreviousDeclaration(decl_type *PrevDecl) { +void Redeclarable::setPreviousDecl(decl_type *PrevDecl) { // Note: This routine is implemented here because we need both NamedDecl // and Redeclarable to be defined. @@ -3364,10 +3503,16 @@ void Redeclarable::setPreviousDeclaration(decl_type *PrevDecl) { // Point to previous. Make sure that this is actually the most recent // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. - First = PrevDecl->getFirstDeclaration(); + First = PrevDecl->getFirstDecl(); assert(First->RedeclLink.NextIsLatest() && "Expected first"); decl_type *MostRecent = First->RedeclLink.getNext(); RedeclLink = PreviousDeclLink(cast(MostRecent)); + + // If the declaration was previously visible, a redeclaration of it remains + // visible even if it wouldn't be visible by itself. + static_cast(this)->IdentifierNamespace |= + MostRecent->getIdentifierNamespace() & + (Decl::IDNS_Ordinary | Decl::IDNS_Tag | Decl::IDNS_Type); } else { // Make this first. First = static_cast(this); diff --git a/include/clang/AST/DeclAccessPair.h b/include/clang/AST/DeclAccessPair.h index 5731308f55e6..3c5056c6e55b 100644 --- a/include/clang/AST/DeclAccessPair.h +++ b/include/clang/AST/DeclAccessPair.h @@ -28,7 +28,7 @@ class NamedDecl; /// A POD class for pairing a NamedDecl* with an access specifier. /// Can be put into unions. class DeclAccessPair { - NamedDecl *Ptr; // we'd use llvm::PointerUnion, but it isn't trivial + uintptr_t Ptr; // we'd use llvm::PointerUnion, but it isn't trivial enum { Mask = 0x3 }; @@ -40,10 +40,10 @@ public: } NamedDecl *getDecl() const { - return (NamedDecl*) (~Mask & (uintptr_t) Ptr); + return reinterpret_cast(~Mask & Ptr); } AccessSpecifier getAccess() const { - return AccessSpecifier(Mask & (uintptr_t) Ptr); + return AccessSpecifier(Mask & Ptr); } void setDecl(NamedDecl *D) { @@ -53,8 +53,7 @@ public: set(getDecl(), AS); } void set(NamedDecl *D, AccessSpecifier AS) { - Ptr = reinterpret_cast(uintptr_t(AS) | - reinterpret_cast(D)); + Ptr = uintptr_t(AS) | reinterpret_cast(D); } operator NamedDecl*() const { return getDecl(); } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 754facfb591d..26eea64f9d34 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -16,6 +16,7 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/DeclarationName.h" +#include "clang/Basic/Linkage.h" #include "clang/Basic/Specifiers.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/Support/Compiler.h" @@ -31,6 +32,7 @@ class DeclarationName; class DependentDiagnostic; class EnumDecl; class FunctionDecl; +class LinkageComputer; class LinkageSpecDecl; class Module; class NamedDecl; @@ -157,7 +159,12 @@ public: /// This declaration is a C++ operator declared in a non-class /// context. All such operators are also in IDNS_Ordinary. /// C++ lexical operator lookup looks for these. - IDNS_NonMemberOperator = 0x0400 + IDNS_NonMemberOperator = 0x0400, + + /// This declaration is a function-local extern declaration of a + /// variable or function. This may also be IDNS_Ordinary if it + /// has been declared outside any function. + IDNS_LocalExtern = 0x0800 }; /// ObjCDeclQualifier - 'Qualifiers' written next to the return and @@ -284,19 +291,16 @@ protected: /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 12; - /// \brief Whether the \c CachedLinkage field is active. - /// - /// This field is only valid for NamedDecls subclasses. - mutable unsigned HasCachedLinkage : 1; - - /// \brief If \c HasCachedLinkage, the linkage of this declaration. - /// - /// This field is only valid for NamedDecls subclasses. - mutable unsigned CachedLinkage : 2; + /// \brief If 0, we have not computed the linkage of this declaration. + /// Otherwise, it is the linkage + 1. + mutable unsigned CacheValidAndLinkage : 3; friend class ASTDeclWriter; friend class ASTDeclReader; friend class ASTReader; + friend class LinkageComputer; + + template friend class Redeclarable; private: void CheckAccessDeclContext() const; @@ -309,7 +313,7 @@ protected: HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } @@ -319,7 +323,7 @@ protected: HasAttrs(false), Implicit(false), Used(false), Referenced(false), Access(AS_none), FromASTFile(0), Hidden(0), IdentifierNamespace(getIdentifierNamespaceForKind(DK)), - HasCachedLinkage(0) + CacheValidAndLinkage(0) { if (StatisticsEnabled) add(DK); } @@ -341,6 +345,18 @@ protected: /// \brief Update a potentially out-of-date declaration. void updateOutOfDate(IdentifierInfo &II) const; + Linkage getCachedLinkage() const { + return Linkage(CacheValidAndLinkage - 1); + } + + void setCachedLinkage(Linkage L) const { + CacheValidAndLinkage = L + 1; + } + + bool hasCachedLinkage() const { + return CacheValidAndLinkage; + } + public: /// \brief Source range that this declaration covers. @@ -419,7 +435,6 @@ public: return const_cast(const_cast(this)->getAttrs()); } const AttrVec &getAttrs() const; - void swapAttrs(Decl *D); void dropAttrs(); void addAttr(Attr *A) { @@ -490,7 +505,16 @@ public: /// whether the function is used. bool isUsed(bool CheckUsedAttr = true) const; - void setUsed(bool U = true) { Used = U; } + /// \brief Set whether the declaration is used, in the sense of odr-use. + /// + /// This should only be used immediately after creating a declaration. + void setIsUsed() { Used = true; } + + /// \brief Mark the declaration used, in the sense of odr-use. + /// + /// This notifies any mutation listeners in addition to setting a bit + /// indicating the declaration is used. + void markUsed(ASTContext &C); /// \brief Whether this declaration was referenced. bool isReferenced() const; @@ -513,13 +537,13 @@ public: NextInContextAndBits.setInt(Bits); } -protected: /// \brief Whether this declaration was marked as being private to the /// module in which it was defined. - bool isModulePrivate() const { + bool isModulePrivate() const { return NextInContextAndBits.getInt() & ModulePrivateFlag; } - + +protected: /// \brief Specify whether this declaration was marked as being private /// to the module in which it was defined. void setModulePrivate(bool MP = true) { @@ -761,7 +785,12 @@ public: const Decl *getPreviousDecl() const { return const_cast(this)->getPreviousDeclImpl(); } - + + /// \brief True if this is the first declaration in its redeclaration chain. + bool isFirstDecl() const { + return getPreviousDecl() == 0; + } + /// \brief Retrieve the most recent declaration that declares the same entity /// as this declaration (which may be this declaration). Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); } @@ -777,8 +806,10 @@ public: /// top-level Stmt* of that body. Otherwise this method returns null. virtual Stmt* getBody() const { return 0; } - /// \brief Returns true if this Decl represents a declaration for a body of + /// \brief Returns true if this \c Decl represents a declaration for a body of /// code, such as a function or method definition. + /// Note that \c hasBody can also return true if any redeclaration of this + /// \c Decl represents a declaration for a body of code. virtual bool hasBody() const { return getBody() != 0; } /// getBodyRBrace - Gets the right brace of the body, if a body exists. @@ -807,6 +838,32 @@ public: /// \brief Whether this declaration is a function or function template. bool isFunctionOrFunctionTemplate() const; + /// \brief Changes the namespace of this declaration to reflect that it's + /// a function-local extern declaration. + /// + /// These declarations appear in the lexical context of the extern + /// declaration, but in the semantic context of the enclosing namespace + /// scope. + void setLocalExternDecl() { + assert((IdentifierNamespace == IDNS_Ordinary || + IdentifierNamespace == IDNS_OrdinaryFriend) && + "namespace is not ordinary"); + + Decl *Prev = getPreviousDecl(); + IdentifierNamespace &= ~IDNS_Ordinary; + + IdentifierNamespace |= IDNS_LocalExtern; + if (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary) + IdentifierNamespace |= IDNS_Ordinary; + } + + /// \brief Determine whether this is a block-scope declaration with linkage. + /// This will either be a local variable declaration declared 'extern', or a + /// local function declaration. + bool isLocalExternDecl() { + return IdentifierNamespace & IDNS_LocalExtern; + } + /// \brief Changes the namespace of this declaration to reflect that it's /// the object of a friend declaration. /// @@ -814,31 +871,39 @@ public: /// class, but in the semantic context of the actual entity. This property /// applies only to a specific decl object; other redeclarations of the /// same entity may not (and probably don't) share this property. - void setObjectOfFriendDecl(bool PreviouslyDeclared) { + void setObjectOfFriendDecl(bool PerformFriendInjection = false) { unsigned OldNS = IdentifierNamespace; assert((OldNS & (IDNS_Tag | IDNS_Ordinary | - IDNS_TagFriend | IDNS_OrdinaryFriend)) && + IDNS_TagFriend | IDNS_OrdinaryFriend | + IDNS_LocalExtern)) && "namespace includes neither ordinary nor tag"); assert(!(OldNS & ~(IDNS_Tag | IDNS_Ordinary | IDNS_Type | - IDNS_TagFriend | IDNS_OrdinaryFriend)) && + IDNS_TagFriend | IDNS_OrdinaryFriend | + IDNS_LocalExtern)) && "namespace includes other than ordinary or tag"); - IdentifierNamespace = 0; + Decl *Prev = getPreviousDecl(); + IdentifierNamespace &= ~(IDNS_Ordinary | IDNS_Tag | IDNS_Type); + if (OldNS & (IDNS_Tag | IDNS_TagFriend)) { IdentifierNamespace |= IDNS_TagFriend; - if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Tag | IDNS_Type; + if (PerformFriendInjection || + (Prev && Prev->getIdentifierNamespace() & IDNS_Tag)) + IdentifierNamespace |= IDNS_Tag | IDNS_Type; } - if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend)) { + if (OldNS & (IDNS_Ordinary | IDNS_OrdinaryFriend | IDNS_LocalExtern)) { IdentifierNamespace |= IDNS_OrdinaryFriend; - if (PreviouslyDeclared) IdentifierNamespace |= IDNS_Ordinary; + if (PerformFriendInjection || + (Prev && Prev->getIdentifierNamespace() & IDNS_Ordinary)) + IdentifierNamespace |= IDNS_Ordinary; } } enum FriendObjectKind { - FOK_None, // not a friend object - FOK_Declared, // a friend of a previously-declared entity - FOK_Undeclared // a friend of a previously-undeclared entity + FOK_None, ///< Not a friend object. + FOK_Declared, ///< A friend of a previously-declared entity. + FOK_Undeclared ///< A friend of a previously-undeclared entity. }; /// \brief Determines whether this declaration is the object of a @@ -846,11 +911,11 @@ public: /// /// There is currently no direct way to find the associated FriendDecl. FriendObjectKind getFriendObjectKind() const { - unsigned mask - = (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); + unsigned mask = + (IdentifierNamespace & (IDNS_TagFriend | IDNS_OrdinaryFriend)); if (!mask) return FOK_None; - return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? - FOK_Declared : FOK_Undeclared); + return (IdentifierNamespace & (IDNS_Tag | IDNS_Ordinary) ? FOK_Declared + : FOK_Undeclared); } /// Specifies that this declaration is a C++ overloaded non-member. @@ -877,9 +942,6 @@ public: // Same as dump(), but forces color printing. LLVM_ATTRIBUTE_USED void dumpColor() const; void dump(raw_ostream &Out) const; - // Debuggers don't usually respect default arguments. - LLVM_ATTRIBUTE_USED void dumpXML() const; - void dumpXML(raw_ostream &OS) const; private: void setAttrsImpl(const AttrVec& Attrs, ASTContext &Ctx); @@ -974,6 +1036,7 @@ protected: mutable Decl *LastDecl; friend class ExternalASTSource; + friend class ASTDeclReader; friend class ASTWriter; /// \brief Build up a chain of declarations. @@ -1096,6 +1159,14 @@ public: /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; + /// \brief Determines whether this context or some of its ancestors is a + /// linkage specification context that specifies C linkage. + bool isExternCContext() const; + + /// \brief Determines whether this context or some of its ancestors is a + /// linkage specification context that specifies C++ linkage. + bool isExternCXXContext() const; + /// \brief Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { @@ -1429,12 +1500,20 @@ public: return const_cast(this)->lookup(Name); } + /// \brief Find the declarations with the given name that are visible + /// within this context; don't attempt to retrieve anything from an + /// external source. + lookup_result noload_lookup(DeclarationName Name); + /// \brief A simplistic name lookup mechanism that performs name lookup /// into this declaration context without consulting the external source. /// /// This function should almost never be used, because it subverts the /// usual relationship between a DeclContext and the external source. /// See the ASTImporter for the (few, but important) use cases. + /// + /// FIXME: This is very inefficient; replace uses of it with uses of + /// noload_lookup. void localUncachedLookup(DeclarationName Name, SmallVectorImpl &Results); @@ -1458,10 +1537,16 @@ public: /// of looking up every possible name. class all_lookups_iterator; + /// \brief Iterators over all possible lookups within this context. all_lookups_iterator lookups_begin() const; - all_lookups_iterator lookups_end() const; + /// \brief Iterators over all possible lookups within this context that are + /// currently loaded; don't attempt to retrieve anything from an external + /// source. + all_lookups_iterator noload_lookups_begin() const; + all_lookups_iterator noload_lookups_end() const; + /// udir_iterator - Iterates through the using-directives stored /// within this context. typedef UsingDirectiveDecl * const * udir_iterator; @@ -1532,6 +1617,8 @@ public: static bool classof(const DeclContext *D) { return true; } LLVM_ATTRIBUTE_USED void dumpDeclContext() const; + LLVM_ATTRIBUTE_USED void dumpLookups() const; + LLVM_ATTRIBUTE_USED void dumpLookups(llvm::raw_ostream &OS) const; private: void reconcileExternalVisibleStorage(); @@ -1548,6 +1635,8 @@ private: friend class DependentDiagnostic; StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; + template void buildLookupImpl(DeclContext *DCtx); void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Rediscoverable); diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index c483dde1f518..dbc41320bd72 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -6,10 +6,11 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the C++ Decl subclasses, other than those for -// templates (in DeclTemplate.h) and friends (in DeclFriend.h). -// +/// +/// \file +/// \brief Defines the C++ Decl subclasses, other than those for templates +/// (found in DeclTemplate.h) and friends (in DeclFriend.h). +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_DECLCXX_H @@ -88,7 +89,7 @@ namespace llvm { namespace clang { -/// @brief Represents an access specifier followed by colon ':'. +/// \brief Represents an access specifier followed by colon ':'. /// /// An objects of this class represents sugar for the syntactic occurrence /// of an access specifier followed by a colon in the list of member @@ -146,16 +147,16 @@ public: /// level of access (public, protected, private) is used for the /// derivation. For example: /// -/// @code +/// \code /// class A { }; /// class B { }; /// class C : public virtual A, protected B { }; -/// @endcode +/// \endcode /// /// In this code, C will have two CXXBaseSpecifiers, one for "public /// virtual A" and the other for "protected B". class CXXBaseSpecifier { - /// Range - The source code range that covers the full base + /// \brief The source code range that covers the full base /// specifier, including the "virtual" (if present) and access /// specifier (if present). SourceRange Range; @@ -167,25 +168,26 @@ class CXXBaseSpecifier { /// \brief Whether this is a virtual base class or not. bool Virtual : 1; - /// BaseOfClass - Whether this is the base of a class (true) or of a - /// struct (false). This determines the mapping from the access - /// specifier as written in the source code to the access specifier - /// used for semantic analysis. + /// \brief Whether this is the base of a class (true) or of a struct (false). + /// + /// This determines the mapping from the access specifier as written in the + /// source code to the access specifier used for semantic analysis. bool BaseOfClass : 1; - /// Access - Access specifier as written in the source code (which - /// may be AS_none). The actual type of data stored here is an - /// AccessSpecifier, but we use "unsigned" here to work around a - /// VC++ bug. + /// \brief Access specifier as written in the source code (may be AS_none). + /// + /// The actual type of data stored here is an AccessSpecifier, but we use + /// "unsigned" here to work around a VC++ bug. unsigned Access : 2; - /// InheritConstructors - Whether the class contains a using declaration + /// \brief Whether the class contains a using declaration /// to inherit the named class's constructors. bool InheritConstructors : 1; - /// BaseTypeInfo - The type of the base class. This will be a class or struct - /// (or a typedef of such). The source code range does not include the - /// "virtual" or access specifier. + /// \brief The type of the base class. + /// + /// This will be a class or struct (or a typedef of such). The source code + /// range does not include the \c virtual or the access specifier. TypeSourceInfo *BaseTypeInfo; public: @@ -196,14 +198,12 @@ public: : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) { } - /// getSourceRange - Retrieves the source range that contains the - /// entire base specifier. + /// \brief Retrieves the source range that contains the entire base specifier. SourceRange getSourceRange() const LLVM_READONLY { return Range; } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - /// isVirtual - Determines whether the base class is a virtual base - /// class (or not). + /// \brief Determines whether the base class is a virtual base class (or not). bool isVirtual() const { return Virtual; } /// \brief Determine whether this base class is a base of a class declared @@ -226,11 +226,11 @@ public: return EllipsisLoc; } - /// getAccessSpecifier - Returns the access specifier for this base - /// specifier. This is the actual base specifier as used for - /// semantic analysis, so the result can never be AS_none. To - /// retrieve the access specifier as written in the source code, use - /// getAccessSpecifierAsWritten(). + /// \brief Returns the access specifier for this base specifier. + /// + /// This is the actual base specifier as used for semantic analysis, so + /// the result can never be AS_none. To retrieve the access specifier as + /// written in the source code, use getAccessSpecifierAsWritten(). AccessSpecifier getAccessSpecifier() const { if ((AccessSpecifier)Access == AS_none) return BaseOfClass? AS_private : AS_public; @@ -238,19 +238,23 @@ public: return (AccessSpecifier)Access; } - /// getAccessSpecifierAsWritten - Retrieves the access specifier as - /// written in the source code (which may mean that no access - /// specifier was explicitly written). Use getAccessSpecifier() to - /// retrieve the access specifier for use in semantic analysis. + /// \brief Retrieves the access specifier as written in the source code + /// (which may mean that no access specifier was explicitly written). + /// + /// Use getAccessSpecifier() to retrieve the access specifier for use in + /// semantic analysis. AccessSpecifier getAccessSpecifierAsWritten() const { return (AccessSpecifier)Access; } - /// getType - Retrieves the type of the base class. This type will - /// always be an unqualified class type. - QualType getType() const { return BaseTypeInfo->getType(); } + /// \brief Retrieves the type of the base class. + /// + /// This type will always be an unqualified class type. + QualType getType() const { + return BaseTypeInfo->getType().getUnqualifiedType(); + } - /// getTypeLoc - Retrieves the type and source location of the base class. + /// \brief Retrieves the type and source location of the base class. TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; @@ -264,7 +268,8 @@ enum MSInheritanceModel { MSIM_Unspecified }; -/// CXXRecordDecl - Represents a C++ struct/union/class. +/// \brief Represents a C++ struct/union/class. +/// /// FIXME: This class will disappear once we've properly taught RecordDecl /// to deal with C++-specific things. class CXXRecordDecl : public RecordDecl { @@ -288,32 +293,32 @@ class CXXRecordDecl : public RecordDecl { /// \brief True if this class has any user-declared constructors. bool UserDeclaredConstructor : 1; - /// The user-declared special members which this class has. + /// \brief The user-declared special members which this class has. unsigned UserDeclaredSpecialMembers : 6; - /// Aggregate - True when this class is an aggregate. + /// \brief True when this class is an aggregate. bool Aggregate : 1; - /// PlainOldData - True when this class is a POD-type. + /// \brief True when this class is a POD-type. bool PlainOldData : 1; - /// Empty - true when this class is empty for traits purposes, + /// true when this class is empty for traits purposes, /// i.e. has no data members other than 0-width bit-fields, has no /// virtual function/base, and doesn't inherit from a non-empty /// class. Doesn't take union-ness into account. bool Empty : 1; - /// Polymorphic - True when this class is polymorphic, i.e. has at + /// \brief True when this class is polymorphic, i.e., has at /// least one virtual member or derives from a polymorphic class. bool Polymorphic : 1; - /// Abstract - True when this class is abstract, i.e. has at least + /// \brief True when this class is abstract, i.e., has at least /// one pure virtual function, (that can come from a base class). bool Abstract : 1; - /// IsStandardLayout - True when this class has standard layout. + /// \brief True when this class has standard layout. /// - /// C++0x [class]p7. A standard-layout class is a class that: + /// C++11 [class]p7. A standard-layout class is a class that: /// * has no non-static data members of type non-standard-layout class (or /// array of such types) or reference, /// * has no virtual functions (10.3) and no virtual base classes (10.1), @@ -327,20 +332,19 @@ class CXXRecordDecl : public RecordDecl { /// member. bool IsStandardLayout : 1; - /// HasNoNonEmptyBases - True when there are no non-empty base classes. + /// \brief True when there are no non-empty base classes. /// /// This is a helper bit of state used to implement IsStandardLayout more /// efficiently. bool HasNoNonEmptyBases : 1; - /// HasPrivateFields - True when there are private non-static data members. + /// \brief True when there are private non-static data members. bool HasPrivateFields : 1; - /// HasProtectedFields - True when there are protected non-static data - /// members. + /// \brief True when there are protected non-static data members. bool HasProtectedFields : 1; - /// HasPublicFields - True when there are private non-static data members. + /// \brief True when there are private non-static data members. bool HasPublicFields : 1; /// \brief True if this class (or any subobject) has mutable fields. @@ -353,8 +357,10 @@ class CXXRecordDecl : public RecordDecl { bool HasInClassInitializer : 1; /// \brief True if any field is of reference type, and does not have an - /// in-class initializer. In this case, value-initialization of this class - /// is illegal in C++98 even if the class has a trivial default constructor. + /// in-class initializer. + /// + /// In this case, value-initialization of this class is illegal in C++98 + /// even if the class has a trivial default constructor. bool HasUninitializedReferenceMember : 1; /// \brief These flags are \c true if a defaulted corresponding special @@ -389,30 +395,29 @@ class CXXRecordDecl : public RecordDecl { /// members which have not yet been declared. unsigned DeclaredNonTrivialSpecialMembers : 6; - /// HasIrrelevantDestructor - True when this class has a destructor with no - /// semantic effect. + /// \brief True when this class has a destructor with no semantic effect. bool HasIrrelevantDestructor : 1; - /// HasConstexprNonCopyMoveConstructor - True when this class has at least - /// one user-declared constexpr constructor which is neither the copy nor - /// move constructor. + /// \brief True when this class has at least one user-declared constexpr + /// constructor which is neither the copy nor move constructor. bool HasConstexprNonCopyMoveConstructor : 1; - /// DefaultedDefaultConstructorIsConstexpr - True if a defaulted default - /// constructor for this class would be constexpr. + /// \brief True if a defaulted default constructor for this class would + /// be constexpr. bool DefaultedDefaultConstructorIsConstexpr : 1; - /// HasConstexprDefaultConstructor - True if this class has a constexpr - /// default constructor (either user-declared or implicitly declared). + /// \brief True if this class has a constexpr default constructor. + /// + /// This is true for either a user-declared constexpr default constructor + /// or an implicitly declared constexpr default constructor.. bool HasConstexprDefaultConstructor : 1; - /// HasNonLiteralTypeFieldsOrBases - True when this class contains at least - /// one non-static data member or base class of non-literal or volatile - /// type. + /// \brief True when this class contains at least one non-static data + /// member or base class of non-literal or volatile type. bool HasNonLiteralTypeFieldsOrBases : 1; - /// ComputedVisibleConversions - True when visible conversion functions are - /// already computed and are available. + /// \brief True when visible conversion functions are already computed + /// and are available. bool ComputedVisibleConversions : 1; /// \brief Whether we have a C++11 user-provided default constructor (not @@ -439,50 +444,44 @@ class CXXRecordDecl : public RecordDecl { /// const-qualified reference parameter or a non-reference parameter. bool HasDeclaredCopyAssignmentWithConstParam : 1; - /// \brief Whether an implicit move constructor was attempted to be declared - /// but would have been deleted. - bool FailedImplicitMoveConstructor : 1; - - /// \brief Whether an implicit move assignment operator was attempted to be - /// declared but would have been deleted. - bool FailedImplicitMoveAssignment : 1; - /// \brief Whether this class describes a C++ lambda. bool IsLambda : 1; - /// NumBases - The number of base class specifiers in Bases. + /// \brief The number of base class specifiers in Bases. unsigned NumBases; - /// NumVBases - The number of virtual base class specifiers in VBases. + /// \brief The number of virtual base class specifiers in VBases. unsigned NumVBases; - /// Bases - Base classes of this class. + /// \brief Base classes of this class. + /// /// FIXME: This is wasted space for a union. LazyCXXBaseSpecifiersPtr Bases; - /// VBases - direct and indirect virtual base classes of this class. + /// \brief direct and indirect virtual base classes of this class. LazyCXXBaseSpecifiersPtr VBases; - /// Conversions - Overload set containing the conversion functions - /// of this C++ class (but not its inherited conversion - /// functions). Each of the entries in this overload set is a - /// CXXConversionDecl. - ASTUnresolvedSet Conversions; + /// \brief The conversion functions of this C++ class (but not its + /// inherited conversion functions). + /// + /// Each of the entries in this overload set is a CXXConversionDecl. + LazyASTUnresolvedSet Conversions; - /// VisibleConversions - Overload set containing the conversion - /// functions of this C++ class and all those inherited conversion - /// functions that are visible in this class. Each of the entries - /// in this overload set is a CXXConversionDecl or a + /// \brief The conversion functions of this C++ class and all those + /// inherited conversion functions that are visible in this class. + /// + /// Each of the entries in this overload set is a CXXConversionDecl or a /// FunctionTemplateDecl. - ASTUnresolvedSet VisibleConversions; + LazyASTUnresolvedSet VisibleConversions; - /// Definition - The declaration which defines this record. + /// \brief The declaration which defines this record. CXXRecordDecl *Definition; - /// FirstFriend - The first friend declaration in this class, or - /// null if there aren't any. This is actually currently stored - /// in reverse order. - FriendDecl *FirstFriend; + /// \brief The first friend declaration in this class, or null if there + /// aren't any. + /// + /// This is actually currently stored in reverse order. + LazyDeclPtr FirstFriend; /// \brief Retrieve the set of direct base classes. CXXBaseSpecifier *getBases() const { @@ -507,10 +506,12 @@ class CXXRecordDecl : public RecordDecl { struct LambdaDefinitionData : public DefinitionData { typedef LambdaExpr::Capture Capture; - LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, bool Dependent) - : DefinitionData(D), Dependent(Dependent), NumCaptures(0), - NumExplicitCaptures(0), ManglingNumber(0), ContextDecl(0), Captures(0), - MethodTyInfo(Info) + LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, + bool Dependent, bool IsGeneric, + LambdaCaptureDefault CaptureDefault) + : DefinitionData(D), Dependent(Dependent), IsGenericLambda(IsGeneric), + CaptureDefault(CaptureDefault), NumCaptures(0), NumExplicitCaptures(0), + ManglingNumber(0), ContextDecl(0), Captures(0), MethodTyInfo(Info) { IsLambda = true; } @@ -522,14 +523,20 @@ class CXXRecordDecl : public RecordDecl { /// within the default argument of a function template, because the /// lambda will have been created with the enclosing context as its /// declaration context, rather than function. This is an unfortunate - /// artifact of having to parse the default arguments before + /// artifact of having to parse the default arguments before. unsigned Dependent : 1; - /// \brief The number of captures in this lambda. - unsigned NumCaptures : 16; + /// \brief Whether this lambda is a generic lambda. + unsigned IsGenericLambda : 1; + + /// \brief The Default Capture. + unsigned CaptureDefault : 2; + + /// \brief The number of captures in this lambda is limited 2^NumCaptures. + unsigned NumCaptures : 15; /// \brief The number of explicit captures in this lambda. - unsigned NumExplicitCaptures : 15; + unsigned NumExplicitCaptures : 13; /// \brief The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. @@ -547,6 +554,7 @@ class CXXRecordDecl : public RecordDecl { /// \brief The type of the call method. TypeSourceInfo *MethodTyInfo; + }; struct DefinitionData &data() { @@ -569,7 +577,7 @@ class CXXRecordDecl : public RecordDecl { /// \brief The template or declaration that this declaration /// describes or was instantiated from, respectively. /// - /// For non-templates, this value will be NULL. For record + /// For non-templates, this value will be null. For record /// declarations that describe a class template, this will be a /// pointer to a ClassTemplateDecl. For member /// classes of class template specializations, this will be the @@ -597,27 +605,29 @@ class CXXRecordDecl : public RecordDecl { friend class ASTNodeImporter; + /// \brief Get the head of our list of friend declarations, possibly + /// deserializing the friends from an external AST source. + FriendDecl *getFirstFriend() const; + protected: CXXRecordDecl(Kind K, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl); public: - /// base_class_iterator - Iterator that traverses the base classes - /// of a class. + /// \brief Iterator that traverses the base classes of a class. typedef CXXBaseSpecifier* base_class_iterator; - /// base_class_const_iterator - Iterator that traverses the base - /// classes of a class. + /// \brief Iterator that traverses the base classes of a class. typedef const CXXBaseSpecifier* base_class_const_iterator; - /// reverse_base_class_iterator = Iterator that traverses the base classes - /// of a class in reverse order. + /// \brief Iterator that traverses the base classes of a class in reverse + /// order. typedef std::reverse_iterator reverse_base_class_iterator; - /// reverse_base_class_iterator = Iterator that traverses the base classes - /// of a class in reverse order. + /// \brief Iterator that traverses the base classes of a class in reverse + /// order. typedef std::reverse_iterator reverse_base_class_const_iterator; @@ -628,18 +638,21 @@ public: return cast(RecordDecl::getCanonicalDecl()); } + CXXRecordDecl *getPreviousDecl() { + return cast_or_null( + static_cast(this)->getPreviousDecl()); + } const CXXRecordDecl *getPreviousDecl() const { - return cast_or_null(RecordDecl::getPreviousDecl()); + return const_cast(this)->getPreviousDecl(); } - CXXRecordDecl *getPreviousDecl() { - return cast_or_null(RecordDecl::getPreviousDecl()); + + CXXRecordDecl *getMostRecentDecl() { + return cast( + static_cast(this)->getMostRecentDecl()); } const CXXRecordDecl *getMostRecentDecl() const { - return cast_or_null(RecordDecl::getMostRecentDecl()); - } - CXXRecordDecl *getMostRecentDecl() { - return cast_or_null(RecordDecl::getMostRecentDecl()); + return const_cast(this)->getMostRecentDecl(); } CXXRecordDecl *getDefinition() const { @@ -655,18 +668,18 @@ public: bool DelayTypeCreation = false); static CXXRecordDecl *CreateLambda(const ASTContext &C, DeclContext *DC, TypeSourceInfo *Info, SourceLocation Loc, - bool DependentLambda); + bool DependentLambda, bool IsGeneric, + LambdaCaptureDefault CaptureDefault); static CXXRecordDecl *CreateDeserialized(const ASTContext &C, unsigned ID); bool isDynamicClass() const { return data().Polymorphic || data().NumVBases != 0; } - /// setBases - Sets the base classes of this struct or class. + /// \brief Sets the base classes of this struct or class. void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); - /// getNumBases - Retrieves the number of base classes of this - /// class. + /// \brief Retrieves the number of base classes of this class. unsigned getNumBases() const { return data().NumBases; } base_class_iterator bases_begin() { return data().getBases(); } @@ -688,8 +701,7 @@ public: return reverse_base_class_const_iterator(bases_begin()); } - /// getNumVBases - Retrieves the number of virtual base classes of this - /// class. + /// \brief Retrieves the number of virtual base classes of this class. unsigned getNumVBases() const { return data().NumVBases; } base_class_iterator vbases_begin() { return data().getVBases(); } @@ -720,12 +732,12 @@ public: /// special methods, etc. typedef specific_decl_iterator method_iterator; - /// method_begin - Method begin iterator. Iterates in the order the methods + /// \brief Method begin iterator. Iterates in the order the methods /// were declared. method_iterator method_begin() const { return method_iterator(decls_begin()); } - /// method_end - Method end iterator. + /// \brief Method past-the-end iterator. method_iterator method_end() const { return method_iterator(decls_end()); } @@ -749,18 +761,20 @@ public: /// Determines whether this record has any friends. bool hasFriends() const { - return data().FirstFriend != 0; + return data().FirstFriend.isValid(); } /// \brief \c true if we know for sure that this class has a single, /// accessible, unambiguous move constructor that is not deleted. bool hasSimpleMoveConstructor() const { - return !hasUserDeclaredMoveConstructor() && hasMoveConstructor(); + return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() && + !data().DefaultedMoveConstructorIsDeleted; } /// \brief \c true if we know for sure that this class has a single, /// accessible, unambiguous move assignment operator that is not deleted. bool hasSimpleMoveAssignment() const { - return !hasUserDeclaredMoveAssignment() && hasMoveAssignment(); + return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() && + !data().DefaultedMoveAssignmentIsDeleted; } /// \brief \c true if we know for sure that this class has an accessible /// destructor that is not deleted. @@ -784,22 +798,22 @@ public: !(data().DeclaredSpecialMembers & SMF_DefaultConstructor); } - /// hasUserDeclaredConstructor - Whether this class has any - /// user-declared constructors. When true, a default constructor - /// will not be implicitly declared. + /// \brief Determine whether this class has any user-declared constructors. + /// + /// When true, a default constructor will not be implicitly declared. bool hasUserDeclaredConstructor() const { return data().UserDeclaredConstructor; } - /// hasUserProvidedDefaultconstructor - Whether this class has a - /// user-provided default constructor per C++0x. + /// \brief Whether this class has a user-provided default constructor + /// per C++11. bool hasUserProvidedDefaultConstructor() const { return data().UserProvidedDefaultConstructor; } - /// hasUserDeclaredCopyConstructor - Whether this class has a - /// user-declared copy constructor. When false, a copy constructor - /// will be implicitly declared. + /// \brief Determine whether this class has a user-declared copy constructor. + /// + /// When false, a copy constructor will be implicitly declared. bool hasUserDeclaredCopyConstructor() const { return data().UserDeclaredSpecialMembers & SMF_CopyConstructor; } @@ -830,9 +844,11 @@ public: implicitCopyConstructorHasConstParam()); } - /// hasUserDeclaredMoveOperation - Whether this class has a user- - /// declared move constructor or assignment operator. When false, a - /// move constructor and assignment operator may be implicitly declared. + /// \brief Whether this class has a user-declared move constructor or + /// assignment operator. + /// + /// When false, a move constructor and assignment operator may be + /// implicitly declared. bool hasUserDeclaredMoveOperation() const { return data().UserDeclaredSpecialMembers & (SMF_MoveConstructor | SMF_MoveAssignment); @@ -850,28 +866,23 @@ public: needsImplicitMoveConstructor(); } - /// \brief Determine whether implicit move constructor generation for this - /// class has failed before. - bool hasFailedImplicitMoveConstructor() const { - return data().FailedImplicitMoveConstructor; - } - - /// \brief Set whether implicit move constructor generation for this class - /// has failed before. - void setFailedImplicitMoveConstructor(bool Failed = true) { - data().FailedImplicitMoveConstructor = Failed; + /// \brief Set that we attempted to declare an implicitly move + /// constructor, but overload resolution failed so we deleted it. + void setImplicitMoveConstructorIsDeleted() { + assert((data().DefaultedMoveConstructorIsDeleted || + needsOverloadResolutionForMoveConstructor()) && + "move constructor should not be deleted"); + data().DefaultedMoveConstructorIsDeleted = true; } /// \brief Determine whether this class should get an implicit move /// constructor or if any existing special member function inhibits this. bool needsImplicitMoveConstructor() const { - return !hasFailedImplicitMoveConstructor() && - !(data().DeclaredSpecialMembers & SMF_MoveConstructor) && + return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) && !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveAssignment() && - !hasUserDeclaredDestructor() && - !data().DefaultedMoveConstructorIsDeleted; + !hasUserDeclaredDestructor(); } /// \brief Determine whether we need to eagerly declare a defaulted move @@ -880,9 +891,10 @@ public: return data().NeedOverloadResolutionForMoveConstructor; } - /// hasUserDeclaredCopyAssignment - Whether this class has a - /// user-declared copy assignment operator. When false, a copy - /// assigment operator will be implicitly declared. + /// \brief Determine whether this class has a user-declared copy assignment + /// operator. + /// + /// When false, a copy assigment operator will be implicitly declared. bool hasUserDeclaredCopyAssignment() const { return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; } @@ -907,7 +919,7 @@ public: /// \brief Determine whether this class has a copy assignment operator with /// a parameter type which is a reference to a const-qualified type or is not - /// a reference.. + /// a reference. bool hasCopyAssignmentWithConstParam() const { return data().HasDeclaredCopyAssignmentWithConstParam || (needsImplicitCopyAssignment() && @@ -926,29 +938,24 @@ public: needsImplicitMoveAssignment(); } - /// \brief Determine whether implicit move assignment generation for this - /// class has failed before. - bool hasFailedImplicitMoveAssignment() const { - return data().FailedImplicitMoveAssignment; - } - - /// \brief Set whether implicit move assignment generation for this class - /// has failed before. - void setFailedImplicitMoveAssignment(bool Failed = true) { - data().FailedImplicitMoveAssignment = Failed; + /// \brief Set that we attempted to declare an implicit move assignment + /// operator, but overload resolution failed so we deleted it. + void setImplicitMoveAssignmentIsDeleted() { + assert((data().DefaultedMoveAssignmentIsDeleted || + needsOverloadResolutionForMoveAssignment()) && + "move assignment should not be deleted"); + data().DefaultedMoveAssignmentIsDeleted = true; } /// \brief Determine whether this class should get an implicit move /// assignment operator or if any existing special member function inhibits /// this. bool needsImplicitMoveAssignment() const { - return !hasFailedImplicitMoveAssignment() && - !(data().DeclaredSpecialMembers & SMF_MoveAssignment) && + return !(data().DeclaredSpecialMembers & SMF_MoveAssignment) && !hasUserDeclaredCopyConstructor() && !hasUserDeclaredCopyAssignment() && !hasUserDeclaredMoveConstructor() && - !hasUserDeclaredDestructor() && - !data().DefaultedMoveAssignmentIsDeleted; + !hasUserDeclaredDestructor(); } /// \brief Determine whether we need to eagerly declare a move assignment @@ -957,9 +964,9 @@ public: return data().NeedOverloadResolutionForMoveAssignment; } - /// hasUserDeclaredDestructor - Whether this class has a - /// user-declared destructor. When false, a destructor will be - /// implicitly declared. + /// \brief Determine whether this class has a user-declared destructor. + /// + /// When false, a destructor will be implicitly declared. bool hasUserDeclaredDestructor() const { return data().UserDeclaredSpecialMembers & SMF_Destructor; } @@ -979,15 +986,42 @@ public: /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { return hasDefinition() && data().IsLambda; } + /// \brief Determine whether this class describes a generic + /// lambda function object (i.e. function call operator is + /// a template). + bool isGenericLambda() const; + + /// \brief Retrieve the lambda call operator of the closure type + /// if this is a closure type. + CXXMethodDecl *getLambdaCallOperator() const; + + /// \brief Retrieve the lambda static invoker, the address of which + /// is returned by the conversion operator, and the body of which + /// is forwarded to the lambda call operator. + CXXMethodDecl *getLambdaStaticInvoker() const; + + /// \brief Retrieve the generic lambda's template parameter list. + /// Returns null if the class does not represent a lambda or a generic + /// lambda. + TemplateParameterList *getGenericLambdaTemplateParameterList() const; + + LambdaCaptureDefault getLambdaCaptureDefault() const { + assert(isLambda()); + return static_cast(getLambdaData().CaptureDefault); + } + /// \brief For a closure type, retrieve the mapping from captured - /// variables and this to the non-static data members that store the + /// variables and \c this to the non-static data members that store the /// values or references of the captures. /// /// \param Captures Will be populated with the mapping from captured /// variables to the corresponding fields. /// /// \param ThisCapture Will be set to the field declaration for the - /// 'this' capture. + /// \c this capture. + /// + /// \note No entries will be added for init-captures, as they do not capture + /// variables. void getCaptureFields(llvm::DenseMap &Captures, FieldDecl *&ThisCapture) const; @@ -1001,10 +1035,10 @@ public: typedef UnresolvedSetIterator conversion_iterator; conversion_iterator conversion_begin() const { - return data().Conversions.begin(); + return data().Conversions.get(getASTContext()).begin(); } conversion_iterator conversion_end() const { - return data().Conversions.end(); + return data().Conversions.get(getASTContext()).end(); } /// Removes a conversion function from this class. The conversion @@ -1012,38 +1046,39 @@ public: /// this class must currently be in the process of being defined. void removeConversion(const NamedDecl *Old); - /// getVisibleConversionFunctions - get all conversion functions visible - /// in current class; including conversion function templates. + /// \brief Get all conversion functions visible in current class, + /// including conversion function templates. std::pair getVisibleConversionFunctions(); - /// isAggregate - Whether this class is an aggregate (C++ - /// [dcl.init.aggr]), which is a class with no user-declared - /// constructors, no private or protected non-static data members, - /// no base classes, and no virtual functions (C++ [dcl.init.aggr]p1). + /// Determine whether this class is an aggregate (C++ [dcl.init.aggr]), + /// which is a class with no user-declared constructors, no private + /// or protected non-static data members, no base classes, and no virtual + /// functions (C++ [dcl.init.aggr]p1). bool isAggregate() const { return data().Aggregate; } - /// hasInClassInitializer - Whether this class has any in-class initializers + /// \brief Whether this class has any in-class initializers /// for non-static data members. bool hasInClassInitializer() const { return data().HasInClassInitializer; } /// \brief Whether this class or any of its subobjects has any members of - /// reference type which would make value-initialization ill-formed, per - /// C++03 [dcl.init]p5: - /// -- if T is a non-union class type without a user-declared constructor, - /// then every non-static data member and base-class component of T is - /// value-initialized - /// [...] - /// A program that calls for [...] value-initialization of an entity of - /// reference type is ill-formed. + /// reference type which would make value-initialization ill-formed. + /// + /// Per C++03 [dcl.init]p5: + /// - if T is a non-union class type without a user-declared constructor, + /// then every non-static data member and base-class component of T is + /// value-initialized [...] A program that calls for [...] + /// value-initialization of an entity of reference type is ill-formed. bool hasUninitializedReferenceMember() const { return !isUnion() && !hasUserDeclaredConstructor() && data().HasUninitializedReferenceMember; } - /// isPOD - Whether this class is a POD-type (C++ [class]p4), which is a class - /// that is an aggregate that has no non-static non-POD data members, no - /// reference data members, no user-defined copy assignment operator and no + /// \brief Whether this class is a POD-type (C++ [class]p4) + /// + /// For purposes of this function a class is POD if it is an aggregate + /// that has no non-static non-POD data members, no reference data + /// members, no user-defined copy assignment operator and no /// user-defined destructor. /// /// Note that this is the C++ TR1 definition of POD. @@ -1053,26 +1088,33 @@ public: /// it contains only public fields, no bases, tag kind is not 'class', etc. bool isCLike() const; - /// isEmpty - Whether this class is empty (C++0x [meta.unary.prop]), which - /// means it has a virtual function, virtual base, data member (other than - /// 0-width bit-field) or inherits from a non-empty class. Does NOT include - /// a check for union-ness. + /// \brief Determine whether this is an empty class in the sense of + /// (C++11 [meta.unary.prop]). + /// + /// A non-union class is empty iff it has a virtual function, virtual base, + /// data member (other than 0-width bit-field) or inherits from a non-empty + /// class. + /// + /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } - /// isPolymorphic - Whether this class is polymorphic (C++ [class.virtual]), + /// Whether this class is polymorphic (C++ [class.virtual]), /// which means that the class contains or inherits a virtual function. bool isPolymorphic() const { return data().Polymorphic; } - /// isAbstract - Whether this class is abstract (C++ [class.abstract]), - /// which means that the class contains or inherits a pure virtual function. + /// \brief Determine whether this class has a pure virtual function. + /// + /// The class is is abstract per (C++ [class.abstract]p2) if it declares + /// a pure virtual function or inherits a pure virtual function that is + /// not overridden. bool isAbstract() const { return data().Abstract; } - /// isStandardLayout - Whether this class has standard layout + /// \brief Determine whether this class has standard layout per /// (C++ [class]p7) bool isStandardLayout() const { return data().IsStandardLayout; } - /// \brief Whether this class, or any of its class subobjects, contains a - /// mutable field. + /// \brief Determine whether this class, or any of its class subobjects, + /// contains a mutable field. bool hasMutableFields() const { return data().HasMutableFields; } /// \brief Determine whether this class has a trivial default constructor @@ -1180,47 +1222,49 @@ public: return !(data().HasTrivialSpecialMembers & SMF_Destructor); } - // hasIrrelevantDestructor - Whether this class has a destructor which has no - // semantic effect. Any such destructor will be trivial, public, defaulted - // and not deleted, and will call only irrelevant destructors. + /// \brief Determine whether this class has a destructor which has no + /// semantic effect. + /// + /// Any such destructor will be trivial, public, defaulted and not deleted, + /// and will call only irrelevant destructors. bool hasIrrelevantDestructor() const { return data().HasIrrelevantDestructor; } - // hasNonLiteralTypeFieldsOrBases - Whether this class has a non-literal or - // volatile type non-static data member or base class. + /// \brief Determine whether this class has a non-literal or/ volatile type + /// non-static data member or base class. bool hasNonLiteralTypeFieldsOrBases() const { return data().HasNonLiteralTypeFieldsOrBases; } - // isTriviallyCopyable - Whether this class is considered trivially copyable - // (C++0x [class]p6). + /// \brief Determine whether this class is considered trivially copyable per + /// (C++11 [class]p6). bool isTriviallyCopyable() const; - // isTrivial - Whether this class is considered trivial - // - // C++0x [class]p6 - // A trivial class is a class that has a trivial default constructor and - // is trivially copiable. + /// \brief Determine whether this class is considered trivial. + /// + /// C++11 [class]p6: + /// "A trivial class is a class that has a trivial default constructor and + /// is trivially copiable." bool isTrivial() const { return isTriviallyCopyable() && hasTrivialDefaultConstructor(); } - // isLiteral - Whether this class is a literal type. - // - // C++11 [basic.types]p10 - // A class type that has all the following properties: - // -- it has a trivial destructor - // -- every constructor call and full-expression in the - // brace-or-equal-intializers for non-static data members (if any) is - // a constant expression. - // -- it is an aggregate type or has at least one constexpr constructor or - // constructor template that is not a copy or move constructor, and - // -- all of its non-static data members and base classes are of literal - // types - // - // We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by - // treating types with trivial default constructors as literal types. + /// \brief Determine whether this class is a literal type. + /// + /// C++11 [basic.types]p10: + /// A class type that has all the following properties: + /// - it has a trivial destructor + /// - every constructor call and full-expression in the + /// brace-or-equal-intializers for non-static data members (if any) is + /// a constant expression. + /// - it is an aggregate type or has at least one constexpr constructor + /// or constructor template that is not a copy or move constructor, and + /// - all of its non-static data members and base classes are of literal + /// types + /// + /// We resolve DR1361 by ignoring the second bullet. We resolve DR1452 by + /// treating types with trivial default constructors as literal types. bool isLiteral() const { return hasTrivialDestructor() && (isAggregate() || hasConstexprNonCopyMoveConstructor() || @@ -1231,15 +1275,15 @@ public: /// \brief If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// - /// This routine will return non-NULL for (non-templated) member + /// This routine will return non-null for (non-templated) member /// classes of class templates. For example, given: /// - /// @code + /// \code /// template /// struct X { /// struct A { }; /// }; - /// @endcode + /// \endcode /// /// The declaration for X::A is a (non-templated) CXXRecordDecl /// whose parent is the class template specialization X. For @@ -1257,7 +1301,7 @@ public: } /// \brief Specify that this record is an instantiation of the - /// member class RD. + /// member class \p RD. void setInstantiationOfMemberClass(CXXRecordDecl *RD, TemplateSpecializationKind TSK); @@ -1288,10 +1332,10 @@ public: /// \brief Set the kind of specialization or template instantiation this is. void setTemplateSpecializationKind(TemplateSpecializationKind TSK); - /// getDestructor - Returns the destructor decl for this class. + /// \brief Returns the destructor decl for this class. CXXDestructorDecl *getDestructor() const; - /// isLocalClass - If the class is a local class [class.local], returns + /// \brief If the class is a local class [class.local], returns /// the enclosing function declaration. const FunctionDecl *isLocalClass() const { if (const CXXRecordDecl *RD = dyn_cast(getDeclContext())) @@ -1300,6 +1344,11 @@ public: return dyn_cast(getDeclContext()); } + FunctionDecl *isLocalClass() { + return const_cast( + const_cast(this)->isLocalClass()); + } + /// \brief Determine whether this dependent class is a current instantiation, /// when viewed from within the given context. bool isCurrentInstantiation(const DeclContext *CurContext) const; @@ -1328,7 +1377,7 @@ public: /// \param Paths will contain the paths taken from the current class to the /// given \p Base class. /// - /// \returns true if this class is derived from Base, false otherwise. + /// \returns true if this class is derived from \p Base, false otherwise. /// /// \todo add a separate paramaeter to configure IsDerivedFrom, rather than /// tangling input and output in \p Paths @@ -1367,6 +1416,13 @@ public: /// The class itself does not count as a base class. This routine /// returns false if the class has non-computable base classes. /// + /// \param BaseMatches Callback invoked for each (direct or indirect) base + /// class of this type, or if \p AllowShortCircuit is true then until a call + /// returns false. + /// + /// \param UserData Passed as the second argument of every call to + /// \p BaseMatches. + /// /// \param AllowShortCircuit if false, forces the callback to be called /// for every base class, even if a dependent or non-matching base was /// found. @@ -1471,12 +1527,12 @@ public: /// \brief Get the indirect primary bases for this class. void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const; - /// viewInheritance - Renders and displays an inheritance diagram + /// Renders and displays an inheritance diagram /// for this C++ class and all of its base classes (transitively) using /// GraphViz. void viewInheritance(ASTContext& Context) const; - /// MergeAccess - Calculates the access of a decl that is reached + /// \brief Calculates the access of a decl that is reached /// along a path. static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess) { @@ -1575,8 +1631,10 @@ public: friend class ASTWriter; }; -/// CXXMethodDecl - Represents a static or instance method of a -/// struct/union/class. +/// \brief Represents a static or instance method of a struct/union/class. +/// +/// In the terminology of the C++ Standard, these are the (static and +/// non-static) member functions, whether virtual or not. class CXXMethodDecl : public FunctionDecl { virtual void anchor(); protected: @@ -1606,6 +1664,18 @@ public: bool isStatic() const; bool isInstance() const { return !isStatic(); } + /// Returns true if the given operator is implicitly static in a record + /// context. + static bool isStaticOverloadedOperator(OverloadedOperatorKind OOK) { + // [class.free]p1: + // Any allocation function for a class T is a static member + // (even if not explicitly declared static). + // [class.free]p6 Any deallocation function for a class X is a static member + // (even if not explicitly declared static). + return OOK == OO_New || OOK == OO_Array_New || OOK == OO_Delete || + OOK == OO_Array_Delete; + } + bool isConst() const { return getType()->castAs()->isConst(); } bool isVolatile() const { return getType()->castAs()->isVolatile(); } @@ -1633,14 +1703,22 @@ public: /// \brief Determine whether this is a move assignment operator. bool isMoveAssignmentOperator() const; - const CXXMethodDecl *getCanonicalDecl() const { - return cast(FunctionDecl::getCanonicalDecl()); - } CXXMethodDecl *getCanonicalDecl() { return cast(FunctionDecl::getCanonicalDecl()); } + const CXXMethodDecl *getCanonicalDecl() const { + return const_cast(this)->getCanonicalDecl(); + } + + CXXMethodDecl *getMostRecentDecl() { + return cast( + static_cast(this)->getMostRecentDecl()); + } + const CXXMethodDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); + } - /// isUserProvided - True if this method is user-declared and was not + /// True if this method is user-declared and was not /// deleted or defaulted on its first declaration. bool isUserProvided() const { return !(isDeleted() || getCanonicalDecl()->isDefaulted()); @@ -1655,21 +1733,22 @@ public: method_iterator end_overridden_methods() const; unsigned size_overridden_methods() const; - /// getParent - Returns the parent of this method declaration, which + /// Returns the parent of this method declaration, which /// is the class in which this method is defined. const CXXRecordDecl *getParent() const { return cast(FunctionDecl::getParent()); } - /// getParent - Returns the parent of this method declaration, which + /// Returns the parent of this method declaration, which /// is the class in which this method is defined. CXXRecordDecl *getParent() { return const_cast( cast(FunctionDecl::getParent())); } - /// getThisType - Returns the type of 'this' pointer. - /// Should only be called for instance methods. + /// \brief Returns the type of the \c this pointer. + /// + /// Should only be called for instance (i.e., non-static) methods. QualType getThisType(ASTContext &C) const; unsigned getTypeQualifiers() const { @@ -1702,11 +1781,11 @@ public: /// or clone the function call operator. bool isLambdaStaticInvoker() const; - /// \brief Find the method in RD that corresponds to this one. + /// \brief Find the method in \p RD that corresponds to this one. /// - /// Find if RD or one of the classes it inherits from override this method. - /// If so, return it. RD is assumed to be a subclass of the class defining - /// this method (or be the class itself), unless MayBeBase is set to true. + /// Find if \p RD or one of the classes it inherits from override this method. + /// If so, return it. \p RD is assumed to be a subclass of the class defining + /// this method (or be the class itself), unless \p MayBeBase is set to true. CXXMethodDecl * getCorrespondingMethodInClass(const CXXRecordDecl *RD, bool MayBeBase = false); @@ -1725,20 +1804,21 @@ public: } }; -/// CXXCtorInitializer - Represents a C++ base or member -/// initializer, which is part of a constructor initializer that +/// \brief Represents a C++ base or member initializer. +/// +/// This is part of a constructor initializer that /// initializes one non-static member variable or one base class. For /// example, in the following, both 'A(a)' and 'f(3.14159)' are member /// initializers: /// -/// @code +/// \code /// class A { }; /// class B : public A { /// float f; /// public: /// B(A& a) : A(a), f(3.14159) { } /// }; -/// @endcode +/// \endcode class CXXCtorInitializer { /// \brief Either the base class name/delegating constructor type (stored as /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field @@ -1747,7 +1827,9 @@ class CXXCtorInitializer { Initializee; /// \brief The source location for the field name or, for a base initializer - /// pack expansion, the location of the ellipsis. In the case of a delegating + /// pack expansion, the location of the ellipsis. + /// + /// In the case of a delegating /// constructor, it will still include the type's source location as the /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; @@ -1756,29 +1838,28 @@ class CXXCtorInitializer { /// end up constructing an object (when multiple arguments are involved). Stmt *Init; - /// LParenLoc - Location of the left paren of the ctor-initializer. + /// \brief Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; - /// RParenLoc - Location of the right paren of the ctor-initializer. + /// \brief Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; /// \brief If the initializee is a type, whether that type makes this /// a delegating initialization. bool IsDelegating : 1; - /// IsVirtual - If the initializer is a base initializer, this keeps track + /// \brief If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. bool IsVirtual : 1; - /// IsWritten - Whether or not the initializer is explicitly written + /// \brief Whether or not the initializer is explicitly written /// in the sources. bool IsWritten : 1; - /// SourceOrderOrNumArrayIndices - If IsWritten is true, then this - /// number keeps track of the textual order of this initializer in the - /// original sources, counting from 0; otherwise, if IsWritten is false, - /// it stores the number of array index variables stored after this - /// object in memory. + /// If IsWritten is true, then this number keeps track of the textual order + /// of this initializer in the original sources, counting from 0; otherwise, + /// it stores the number of array index variables stored after this object + /// in memory. unsigned SourceOrderOrNumArrayIndices : 13; CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, @@ -1786,25 +1867,25 @@ class CXXCtorInitializer { SourceLocation R, VarDecl **Indices, unsigned NumIndices); public: - /// CXXCtorInitializer - Creates a new base-class initializer. + /// \brief Creates a new base-class initializer. explicit CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R, SourceLocation EllipsisLoc); - /// CXXCtorInitializer - Creates a new member initializer. + /// \brief Creates a new member initializer. explicit CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); - /// CXXCtorInitializer - Creates a new anonymous field initializer. + /// \brief Creates a new anonymous field initializer. explicit CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); - /// CXXCtorInitializer - Creates a new delegating Initializer. + /// \brief Creates a new delegating initializer. explicit CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, SourceLocation L, Expr *Init, SourceLocation R); @@ -1816,14 +1897,13 @@ public: Expr *Init, SourceLocation R, VarDecl **Indices, unsigned NumIndices); - /// isBaseInitializer - Returns true when this initializer is - /// initializing a base class. + /// \brief Determine whether this initializer is initializing a base class. bool isBaseInitializer() const { return Initializee.is() && !IsDelegating; } - /// isMemberInitializer - Returns true when this initializer is - /// initializing a non-static data member. + /// \brief Determine whether this initializer is initializing a non-static + /// data member. bool isMemberInitializer() const { return Initializee.is(); } bool isAnyMemberInitializer() const { @@ -1834,15 +1914,18 @@ public: return Initializee.is(); } - /// isInClassMemberInitializer - Returns true when this initializer is an - /// implicit ctor initializer generated for a field with an initializer - /// defined on the member declaration. + /// \brief Determine whether this initializer is an implicit initializer + /// generated for a field with an initializer defined on the member + /// declaration. + /// + /// In-class member initializers (also known as "non-static data member + /// initializations", NSDMIs) were introduced in C++11. bool isInClassMemberInitializer() const { return isa(Init); } - /// isDelegatingInitializer - Returns true when this initializer is creating - /// a delegating constructor. + /// \brief Determine whether this initializer is creating a delegating + /// constructor. bool isDelegatingInitializer() const { return Initializee.is() && IsDelegating; } @@ -1864,7 +1947,7 @@ public: TypeLoc getBaseClassLoc() const; /// If this is a base class initializer, returns the type of the base class. - /// Otherwise, returns NULL. + /// Otherwise, returns null. const Type *getBaseClass() const; /// Returns whether the base is virtual or not. @@ -1880,9 +1963,8 @@ public: return Initializee.dyn_cast(); } - /// getMember - If this is a member initializer, returns the - /// declaration of the non-static data member being - /// initialized. Otherwise, returns NULL. + /// \brief If this is a member initializer, returns the declaration of the + /// non-static data member being initialized. Otherwise, returns null. FieldDecl *getMember() const { if (isMemberInitializer()) return Initializee.get(); @@ -1912,7 +1994,7 @@ public: /// \brief Determine the source range covering the entire initializer. SourceRange getSourceRange() const LLVM_READONLY; - /// isWritten - Returns true if this initializer is explicitly written + /// \brief Determine whether this initializer is explicitly written /// in the source code. bool isWritten() const { return IsWritten; } @@ -1922,9 +2004,13 @@ public: return IsWritten ? static_cast(SourceOrderOrNumArrayIndices) : -1; } - /// \brief Set the source order of this initializer. This method can only - /// be called once for each initializer; it cannot be called on an - /// initializer having a positive number of (implicit) array indices. + /// \brief Set the source order of this initializer. + /// + /// This can only be called once for each initializer; it cannot be called + /// on an initializer having a positive number of (implicit) array indices. + /// + /// This assumes that the initialzier was written in the source code, and + /// ensures that isWritten() returns true. void setSourceOrder(int pos) { assert(!IsWritten && "calling twice setSourceOrder() on the same initializer"); @@ -1969,34 +2055,28 @@ public: Expr *getInit() const { return static_cast(Init); } }; -/// CXXConstructorDecl - Represents a C++ constructor within a -/// class. For example: +/// \brief Represents a C++ constructor within a class. /// -/// @code +/// For example: +/// +/// \code /// class X { /// public: /// explicit X(int); // represented by a CXXConstructorDecl. /// }; -/// @endcode +/// \endcode class CXXConstructorDecl : public CXXMethodDecl { virtual void anchor(); - /// IsExplicitSpecified - Whether this constructor declaration has the - /// 'explicit' keyword specified. + /// \brief Whether this constructor declaration has the \c explicit keyword + /// specified. bool IsExplicitSpecified : 1; - /// ImplicitlyDefined - Whether this constructor was implicitly - /// defined by the compiler. When false, the constructor was defined - /// by the user. In C++03, this flag will have the same value as - /// Implicit. In C++0x, however, a constructor that is - /// explicitly defaulted (i.e., defined with " = default") will have - /// @c !Implicit && ImplicitlyDefined. - bool ImplicitlyDefined : 1; - - /// Support for base and member initializers. - /// CtorInitializers - The arguments used to initialize the base - /// or member. + /// \name Support for base and member initializers. + /// \{ + /// \brief The arguments used to initialize the base or member. CXXCtorInitializer **CtorInitializers; unsigned NumCtorInitializers; + /// \} CXXConstructorDecl(CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, @@ -2005,8 +2085,8 @@ class CXXConstructorDecl : public CXXMethodDecl { bool isImplicitlyDeclared, bool isConstexpr) : CXXMethodDecl(CXXConstructor, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), - IsExplicitSpecified(isExplicitSpecified), ImplicitlyDefined(false), - CtorInitializers(0), NumCtorInitializers(0) { + IsExplicitSpecified(isExplicitSpecified), CtorInitializers(0), + NumCtorInitializers(0) { setImplicit(isImplicitlyDeclared); } @@ -2020,52 +2100,31 @@ public: bool isInline, bool isImplicitlyDeclared, bool isConstexpr); - /// isExplicitSpecified - Whether this constructor declaration has the - /// 'explicit' keyword specified. + /// \brief Determine whether this constructor declaration has the + /// \c explicit keyword specified. bool isExplicitSpecified() const { return IsExplicitSpecified; } - /// isExplicit - Whether this constructor was marked "explicit" or not. + /// \brief Determine whether this constructor was marked "explicit" or not. bool isExplicit() const { - return cast(getFirstDeclaration()) - ->isExplicitSpecified(); - } - - /// isImplicitlyDefined - Whether this constructor was implicitly - /// defined. If false, then this constructor was defined by the - /// user. This operation can only be invoked if the constructor has - /// already been defined. - bool isImplicitlyDefined() const { - assert(isThisDeclarationADefinition() && - "Can only get the implicit-definition flag once the " - "constructor has been defined"); - return ImplicitlyDefined; - } - - /// setImplicitlyDefined - Set whether this constructor was - /// implicitly defined or not. - void setImplicitlyDefined(bool ID) { - assert(isThisDeclarationADefinition() && - "Can only set the implicit-definition flag once the constructor " - "has been defined"); - ImplicitlyDefined = ID; + return cast(getFirstDecl())->isExplicitSpecified(); } - /// init_iterator - Iterates through the member/base initializer list. + /// \brief Iterates through the member/base initializer list. typedef CXXCtorInitializer **init_iterator; - /// init_const_iterator - Iterates through the memberbase initializer list. + /// \brief Iterates through the member/base initializer list. typedef CXXCtorInitializer * const * init_const_iterator; - /// init_begin() - Retrieve an iterator to the first initializer. + /// \brief Retrieve an iterator to the first initializer. init_iterator init_begin() { return CtorInitializers; } - /// begin() - Retrieve an iterator to the first initializer. + /// \brief Retrieve an iterator to the first initializer. init_const_iterator init_begin() const { return CtorInitializers; } - /// init_end() - Retrieve an iterator past the last initializer. + /// \brief Retrieve an iterator past the last initializer. init_iterator init_end() { return CtorInitializers + NumCtorInitializers; } - /// end() - Retrieve an iterator past the last initializer. + /// \brief Retrieve an iterator past the last initializer. init_const_iterator init_end() const { return CtorInitializers + NumCtorInitializers; } @@ -2088,8 +2147,8 @@ public: return init_const_reverse_iterator(init_begin()); } - /// getNumArgs - Determine the number of arguments used to - /// initialize the member or base. + /// \brief Determine the number of arguments used to initialize the member + /// or base. unsigned getNumCtorInitializers() const { return NumCtorInitializers; } @@ -2102,37 +2161,36 @@ public: CtorInitializers = initializers; } - /// isDelegatingConstructor - Whether this constructor is a - /// delegating constructor + /// \brief Determine whether this constructor is a delegating constructor. bool isDelegatingConstructor() const { return (getNumCtorInitializers() == 1) && CtorInitializers[0]->isDelegatingInitializer(); } - /// getTargetConstructor - When this constructor delegates to - /// another, retrieve the target + /// \brief When this constructor delegates to another, retrieve the target. CXXConstructorDecl *getTargetConstructor() const; - /// isDefaultConstructor - Whether this constructor is a default + /// Whether this constructor is a default /// constructor (C++ [class.ctor]p5), which can be used to /// default-initialize a class of this type. bool isDefaultConstructor() const; - /// isCopyConstructor - Whether this constructor is a copy - /// constructor (C++ [class.copy]p2, which can be used to copy the - /// class. @p TypeQuals will be set to the qualifiers on the - /// argument type. For example, @p TypeQuals would be set to @c + /// \brief Whether this constructor is a copy constructor (C++ [class.copy]p2, + /// which can be used to copy the class. + /// + /// \p TypeQuals will be set to the qualifiers on the + /// argument type. For example, \p TypeQuals would be set to \c /// Qualifiers::Const for the following copy constructor: /// - /// @code + /// \code /// class X { /// public: /// X(const X&); /// }; - /// @endcode + /// \endcode bool isCopyConstructor(unsigned &TypeQuals) const; - /// isCopyConstructor - Whether this constructor is a copy + /// Whether this constructor is a copy /// constructor (C++ [class.copy]p2, which can be used to copy the /// class. bool isCopyConstructor() const { @@ -2166,7 +2224,7 @@ public: return isCopyOrMoveConstructor(Quals); } - /// isConvertingConstructor - Whether this constructor is a + /// Whether this constructor is a /// converting constructor (C++ [class.conv.ctor]), which can be /// used for user-defined conversions. bool isConvertingConstructor(bool AllowExplicit) const; @@ -2197,24 +2255,18 @@ public: friend class ASTDeclWriter; }; -/// CXXDestructorDecl - Represents a C++ destructor within a -/// class. For example: +/// \brief Represents a C++ destructor within a class. /// -/// @code +/// For example: +/// +/// \code /// class X { /// public: /// ~X(); // represented by a CXXDestructorDecl. /// }; -/// @endcode +/// \endcode class CXXDestructorDecl : public CXXMethodDecl { virtual void anchor(); - /// ImplicitlyDefined - Whether this destructor was implicitly - /// defined by the compiler. When false, the destructor was defined - /// by the user. In C++03, this flag will have the same value as - /// Implicit. In C++0x, however, a destructor that is - /// explicitly defaulted (i.e., defined with " = default") will have - /// @c !Implicit && ImplicitlyDefined. - bool ImplicitlyDefined : 1; FunctionDecl *OperatorDelete; @@ -2224,7 +2276,7 @@ class CXXDestructorDecl : public CXXMethodDecl { bool isInline, bool isImplicitlyDeclared) : CXXMethodDecl(CXXDestructor, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, /*isConstexpr=*/false, SourceLocation()), - ImplicitlyDefined(false), OperatorDelete(0) { + OperatorDelete(0) { setImplicit(isImplicitlyDeclared); } @@ -2237,26 +2289,6 @@ public: bool isImplicitlyDeclared); static CXXDestructorDecl *CreateDeserialized(ASTContext & C, unsigned ID); - /// isImplicitlyDefined - Whether this destructor was implicitly - /// defined. If false, then this destructor was defined by the - /// user. This operation can only be invoked if the destructor has - /// already been defined. - bool isImplicitlyDefined() const { - assert(isThisDeclarationADefinition() && - "Can only get the implicit-definition flag once the destructor has " - "been defined"); - return ImplicitlyDefined; - } - - /// setImplicitlyDefined - Set whether this destructor was - /// implicitly defined or not. - void setImplicitlyDefined(bool ID) { - assert(isThisDeclarationADefinition() && - "Can only set the implicit-definition flag once the destructor has " - "been defined"); - ImplicitlyDefined = ID; - } - void setOperatorDelete(FunctionDecl *OD) { OperatorDelete = OD; } const FunctionDecl *getOperatorDelete() const { return OperatorDelete; } @@ -2268,19 +2300,20 @@ public: friend class ASTDeclWriter; }; -/// CXXConversionDecl - Represents a C++ conversion function within a -/// class. For example: +/// \brief Represents a C++ conversion function within a class. +/// +/// For example: /// -/// @code +/// \code /// class X { /// public: /// operator bool(); /// }; -/// @endcode +/// \endcode class CXXConversionDecl : public CXXMethodDecl { virtual void anchor(); - /// IsExplicitSpecified - Whether this conversion function declaration is - /// marked "explicit", meaning that it can only be applied when the user + /// Whether this conversion function declaration is marked + /// "explicit", meaning that it can only be applied when the user /// explicitly wrote a cast. This is a C++0x feature. bool IsExplicitSpecified : 1; @@ -2303,21 +2336,20 @@ public: SourceLocation EndLocation); static CXXConversionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// IsExplicitSpecified - Whether this conversion function declaration is - /// marked "explicit", meaning that it can only be applied when the user - /// explicitly wrote a cast. This is a C++0x feature. + /// Whether this conversion function declaration is marked + /// "explicit", meaning that it can only be used for direct initialization + /// (including explitly written casts). This is a C++11 feature. bool isExplicitSpecified() const { return IsExplicitSpecified; } - /// isExplicit - Whether this is an explicit conversion operator - /// (C++0x only). Explicit conversion operators are only considered - /// when the user has explicitly written a cast. + /// \brief Whether this is an explicit conversion operator (C++11 and later). + /// + /// Explicit conversion operators are only considered for direct + /// initialization, e.g., when the user has explicitly written a cast. bool isExplicit() const { - return cast(getFirstDeclaration()) - ->isExplicitSpecified(); + return cast(getFirstDecl())->isExplicitSpecified(); } - /// getConversionType - Returns the type that this conversion - /// function is converting to. + /// \brief Returns the type that this conversion function is converting to. QualType getConversionType() const { return getType()->getAs()->getResultType(); } @@ -2334,32 +2366,37 @@ public: friend class ASTDeclWriter; }; -/// LinkageSpecDecl - This represents a linkage specification. For example: -/// extern "C" void foo(); +/// \brief Represents a linkage specification. /// +/// For example: +/// \code +/// extern "C" void foo(); +/// \endcode class LinkageSpecDecl : public Decl, public DeclContext { virtual void anchor(); public: - /// LanguageIDs - Used to represent the language in a linkage - /// specification. The values are part of the serialization abi for - /// ASTs and cannot be changed without altering that abi. To help - /// ensure a stable abi for this, we choose the DW_LANG_ encodings + /// \brief Represents the language in a linkage specification. + /// + /// The values are part of the serialization ABI for + /// ASTs and cannot be changed without altering that ABI. To help + /// ensure a stable ABI for this, we choose the DW_LANG_ encodings /// from the dwarf standard. enum LanguageIDs { lang_c = /* DW_LANG_C */ 0x0002, lang_cxx = /* DW_LANG_C_plus_plus */ 0x0004 }; private: - /// Language - The language for this linkage specification. + /// \brief The language for this linkage specification. unsigned Language : 3; - /// True if this linkage spec has brances. This is needed so that hasBraces() - /// returns the correct result while the linkage spec body is being parsed. - /// Once RBraceLoc has been set this is not used, so it doesn't need to be - /// serialized. + /// \brief True if this linkage spec has braces. + /// + /// This is needed so that hasBraces() returns the correct result while the + /// linkage spec body is being parsed. Once RBraceLoc has been set this is + /// not used, so it doesn't need to be serialized. unsigned HasBraces : 1; - /// ExternLoc - The source location for the extern keyword. + /// \brief The source location for the extern keyword. SourceLocation ExternLoc; - /// RBraceLoc - The source location for the right brace (if valid). + /// \brief The source location for the right brace (if valid). SourceLocation RBraceLoc; LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, @@ -2417,34 +2454,38 @@ public: } }; -/// UsingDirectiveDecl - Represents C++ using-directive. For example: +/// \brief Represents C++ using-directive. /// +/// For example: +/// \code /// using namespace std; +/// \endcode /// -// NB: UsingDirectiveDecl should be Decl not NamedDecl, but we provide -// artificial names for all using-directives in order to store -// them in DeclContext effectively. +/// \note UsingDirectiveDecl should be Decl not NamedDecl, but we provide +/// artificial names for all using-directives in order to store +/// them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { virtual void anchor(); - /// \brief The location of the "using" keyword. + /// \brief The location of the \c using keyword. SourceLocation UsingLoc; - /// SourceLocation - Location of 'namespace' token. + /// \brief The location of the \c namespace keyword. SourceLocation NamespaceLoc; /// \brief The nested-name-specifier that precedes the namespace. NestedNameSpecifierLoc QualifierLoc; - /// NominatedNamespace - Namespace nominated by using-directive. + /// \brief The namespace nominated by this using-directive. NamedDecl *NominatedNamespace; /// Enclosing context containing both using-directive and nominated /// namespace. DeclContext *CommonAncestor; - /// getUsingDirectiveName - Returns special DeclarationName used by - /// using-directives. This is only used by DeclContext for storing - /// UsingDirectiveDecls in its lookup structure. + /// \brief Returns special DeclarationName used by using-directives. + /// + /// This is only used by DeclContext for storing UsingDirectiveDecls in + /// its lookup structure. static DeclarationName getName() { return DeclarationName::getUsingDirectiveName(); } @@ -2475,7 +2516,7 @@ public: return NominatedNamespace; } - /// getNominatedNamespace - Returns namespace nominated by using-directive. + /// \brief Returns the namespace nominated by this using-directive. NamespaceDecl *getNominatedNamespace(); const NamespaceDecl *getNominatedNamespace() const { @@ -2487,14 +2528,14 @@ public: DeclContext *getCommonAncestor() { return CommonAncestor; } const DeclContext *getCommonAncestor() const { return CommonAncestor; } - /// \brief Return the location of the "using" keyword. + /// \brief Return the location of the \c using keyword. SourceLocation getUsingLoc() const { return UsingLoc; } // FIXME: Could omit 'Key' in name. - /// getNamespaceKeyLocation - Returns location of namespace keyword. + /// \brief Returns the location of the \c namespace keyword. SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } - /// getIdentLocation - Returns location of identifier. + /// \brief Returns the location of this using declaration's identifier. SourceLocation getIdentLocation() const { return getLocation(); } static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, @@ -2523,23 +2564,25 @@ public: /// /// For example: /// -/// @code +/// \code /// namespace Foo = Bar; -/// @endcode +/// \endcode class NamespaceAliasDecl : public NamedDecl { virtual void anchor(); - /// \brief The location of the "namespace" keyword. + /// \brief The location of the \c namespace keyword. SourceLocation NamespaceLoc; - /// IdentLoc - Location of namespace identifier. Accessed by TargetNameLoc. + /// \brief The location of the namespace's identifier. + /// + /// This is accessed by TargetNameLoc. SourceLocation IdentLoc; /// \brief The nested-name-specifier that precedes the namespace. NestedNameSpecifierLoc QualifierLoc; - /// Namespace - The Decl that this alias points to. Can either be a - /// NamespaceDecl or a NamespaceAliasDecl. + /// \brief The Decl that this alias points to, either a NamespaceDecl or + /// a NamespaceAliasDecl. NamedDecl *Namespace; NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc, @@ -2579,7 +2622,7 @@ public: /// "namespace foo = ns::bar;". SourceLocation getAliasLoc() const { return getLocation(); } - /// Returns the location of the 'namespace' keyword. + /// Returns the location of the \c namespace keyword. SourceLocation getNamespaceLoc() const { return NamespaceLoc; } /// Returns the location of the identifier in the named namespace. @@ -2611,7 +2654,7 @@ public: /// (resolved) using declaration. /// /// For example, -/// @code +/// \code /// namespace A { /// void foo(); /// } @@ -2619,8 +2662,8 @@ public: /// using A::foo; // <- a UsingDecl /// // Also creates a UsingShadowDecl for A::foo() in B /// } -/// @endcode -class UsingShadowDecl : public NamedDecl { +/// \endcode +class UsingShadowDecl : public NamedDecl, public Redeclarable { virtual void anchor(); /// The referenced declaration. @@ -2643,6 +2686,17 @@ class UsingShadowDecl : public NamedDecl { setImplicit(); } + typedef Redeclarable redeclarable_base; + virtual UsingShadowDecl *getNextRedeclaration() { + return RedeclLink.getNext(); + } + virtual UsingShadowDecl *getPreviousDeclImpl() { + return getPreviousDecl(); + } + virtual UsingShadowDecl *getMostRecentDeclImpl() { + return getMostRecentDecl(); + } + public: static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, @@ -2651,7 +2705,20 @@ public: } static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); - + + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; + + virtual UsingShadowDecl *getCanonicalDecl() { + return getFirstDecl(); + } + virtual const UsingShadowDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + /// \brief Gets the underlying declaration which has been brought into the /// local scope. NamedDecl *getTargetDecl() const { return Underlying; } @@ -2683,20 +2750,20 @@ public: /// \brief Represents a C++ using-declaration. /// /// For example: -/// @code +/// \code /// using someNameSpace::someIdentifier; -/// @endcode +/// \endcode class UsingDecl : public NamedDecl { virtual void anchor(); - /// \brief The source location of the "using" location itself. + /// \brief The source location of the 'using' keyword itself. SourceLocation UsingLocation; /// \brief The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; - /// DNLoc - Provides source/type location info for the - /// declaration name embedded in the ValueDecl base class. + /// \brief Provides source/type location info for the declaration name + /// embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; /// \brief The first shadow declaration of the shadow decl chain associated @@ -2708,18 +2775,18 @@ class UsingDecl : public NamedDecl { UsingDecl(DeclContext *DC, SourceLocation UL, NestedNameSpecifierLoc QualifierLoc, - const DeclarationNameInfo &NameInfo, bool IsTypeNameArg) + const DeclarationNameInfo &NameInfo, bool HasTypenameKeyword) : NamedDecl(Using, DC, NameInfo.getLoc(), NameInfo.getName()), UsingLocation(UL), QualifierLoc(QualifierLoc), - DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, IsTypeNameArg) { + DNLoc(NameInfo.getInfo()), FirstUsingShadow(0, HasTypenameKeyword) { } public: - /// \brief Returns the source location of the "using" keyword. - SourceLocation getUsingLocation() const { return UsingLocation; } + /// \brief Return the source location of the 'using' keyword. + SourceLocation getUsingLoc() const { return UsingLocation; } /// \brief Set the source location of the 'using' keyword. - void setUsingLocation(SourceLocation L) { UsingLocation = L; } + void setUsingLoc(SourceLocation L) { UsingLocation = L; } /// \brief Retrieve the nested-name-specifier that qualifies the name, /// with source-location information. @@ -2734,13 +2801,16 @@ public: return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } + /// \brief Return true if it is a C++03 access declaration (no 'using'). + bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } + /// \brief Return true if the using declaration has 'typename'. - bool isTypeName() const { return FirstUsingShadow.getInt(); } + bool hasTypename() const { return FirstUsingShadow.getInt(); } /// \brief Sets whether the using declaration has 'typename'. - void setTypeName(bool TN) { FirstUsingShadow.setInt(TN); } + void setTypename(bool TN) { FirstUsingShadow.setInt(TN); } - /// \brief Iterates through the using shadow declarations assosiated with + /// \brief Iterates through the using shadow declarations associated with /// this using declaration. class shadow_iterator { /// \brief The current using shadow declaration. @@ -2796,13 +2866,11 @@ public: SourceLocation UsingL, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, - bool IsTypeNameArg); + bool HasTypenameKeyword); static UsingDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(UsingLocation, getNameInfo().getEndLoc()); - } + + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Using; } @@ -2817,11 +2885,11 @@ public: /// Unlike non-dependent using declarations, these *only* bring through /// non-types; otherwise they would break two-phase lookup. /// -/// @code +/// \code /// template \ class A : public Base { /// using Base::foo; /// }; -/// @endcode +/// \endcode class UnresolvedUsingValueDecl : public ValueDecl { virtual void anchor(); @@ -2831,8 +2899,8 @@ class UnresolvedUsingValueDecl : public ValueDecl { /// \brief The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; - /// DNLoc - Provides source/type location info for the - /// declaration name embedded in the ValueDecl base class. + /// \brief Provides source/type location info for the declaration name + /// embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; UnresolvedUsingValueDecl(DeclContext *DC, QualType Ty, @@ -2852,6 +2920,9 @@ public: /// \brief Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } + /// \brief Return true if it is a C++03 access declaration (no 'using'). + bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } + /// \brief Retrieve the nested-name-specifier that qualifies the name, /// with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } @@ -2873,9 +2944,7 @@ public: static UnresolvedUsingValueDecl * CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const LLVM_READONLY { - return SourceRange(UsingLocation, getNameInfo().getEndLoc()); - } + SourceRange getSourceRange() const LLVM_READONLY; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } @@ -2884,23 +2953,20 @@ public: friend class ASTDeclWriter; }; -/// @brief Represents a dependent using declaration which was marked with +/// \brief Represents a dependent using declaration which was marked with /// \c typename. /// -/// @code +/// \code /// template \ class A : public Base { /// using typename Base::foo; /// }; -/// @endcode +/// \endcode /// /// The type associated with an unresolved using typename decl is /// currently always a typename type. class UnresolvedUsingTypenameDecl : public TypeDecl { virtual void anchor(); - /// \brief The source location of the 'using' keyword - SourceLocation UsingLocation; - /// \brief The source location of the 'typename' keyword SourceLocation TypenameLocation; diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 84f3698d6b58..9c626c80aaee 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -18,6 +18,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclarationName.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include @@ -26,23 +27,29 @@ namespace clang { class DependentDiagnostic; -/// StoredDeclsList - This is an array of decls optimized a common case of only -/// containing one entry. +/// \brief An array of decls optimized for the common case of only containing +/// one entry. struct StoredDeclsList { - /// DeclsTy - When in vector form, this is what the Data pointer points to. + /// \brief When in vector form, this is what the Data pointer points to. typedef SmallVector DeclsTy; + /// \brief A collection of declarations, with a flag to indicate if we have + /// further external declarations. + typedef llvm::PointerIntPair DeclsAndHasExternalTy; + /// \brief The stored data, which will be either a pointer to a NamedDecl, - /// or a pointer to a vector. - llvm::PointerUnion Data; + /// or a pointer to a vector with a flag to indicate if there are further + /// external declarations. + llvm::PointerUnion Data; public: StoredDeclsList() {} StoredDeclsList(const StoredDeclsList &RHS) : Data(RHS.Data) { if (DeclsTy *RHSVec = RHS.getAsVector()) - Data = new DeclsTy(*RHSVec); + Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), + RHS.hasExternalDecls()); } ~StoredDeclsList() { @@ -56,7 +63,7 @@ public: delete Vector; Data = RHS.Data; if (DeclsTy *RHSVec = RHS.getAsVector()) - Data = new DeclsTy(*RHSVec); + Data = DeclsAndHasExternalTy(new DeclsTy(*RHSVec), hasExternalDecls()); return *this; } @@ -66,8 +73,27 @@ public: return Data.dyn_cast(); } + DeclsAndHasExternalTy getAsVectorAndHasExternal() const { + return Data.dyn_cast(); + } + DeclsTy *getAsVector() const { - return Data.dyn_cast(); + return getAsVectorAndHasExternal().getPointer(); + } + + bool hasExternalDecls() const { + return getAsVectorAndHasExternal().getInt(); + } + + void setHasExternalDecls() { + if (DeclsTy *Vec = getAsVector()) + Data = DeclsAndHasExternalTy(Vec, true); + else { + DeclsTy *VT = new DeclsTy(); + if (NamedDecl *OldD = getAsDecl()) + VT->push_back(OldD); + Data = DeclsAndHasExternalTy(VT, true); + } } void setOnlyValue(NamedDecl *ND) { @@ -110,6 +136,8 @@ public: Vec.erase(std::remove_if(Vec.begin(), Vec.end(), std::mem_fun(&Decl::isFromASTFile)), Vec.end()); + // Don't have any external decls any more. + Data = DeclsAndHasExternalTy(&Vec, false); } } @@ -165,12 +193,14 @@ public: /// not a redeclaration to merge it into the appropriate place in our list. /// void AddSubsequentDecl(NamedDecl *D) { + assert(!isNull() && "don't AddSubsequentDecl when we have no decls"); + // If this is the second decl added to the list, convert this to vector // form. if (NamedDecl *OldD = getAsDecl()) { DeclsTy *VT = new DeclsTy(); VT->push_back(OldD); - Data = VT; + Data = DeclsAndHasExternalTy(VT, false); } DeclsTy &Vec = *getAsVector(); diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 3a12878e7414..be6f2eb3e3ad 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -220,7 +220,7 @@ public: }; inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_begin() const { - return friend_iterator(data().FirstFriend); + return friend_iterator(getFirstFriend()); } inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { @@ -228,7 +228,7 @@ inline CXXRecordDecl::friend_iterator CXXRecordDecl::friend_end() const { } inline void CXXRecordDecl::pushFriendDecl(FriendDecl *FD) { - assert(FD->NextFriend == 0 && "friend already has next friend?"); + assert(!FD->NextFriend && "friend already has next friend?"); FD->NextFriend = data().FirstFriend; data().FirstFriend = FD; } diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h index 4477c25a9135..c16975a3307f 100644 --- a/include/clang/AST/DeclLookups.h +++ b/include/clang/AST/DeclLookups.h @@ -37,6 +37,8 @@ public: StoredDeclsMap::iterator End) : It(It), End(End) {} + DeclarationName getLookupName() const { return It->first; } + reference operator*() const { return It->second.getLookupResult(); } pointer operator->() const { return It->second.getLookupResult(); } @@ -66,7 +68,7 @@ public: } }; -DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { +inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { DeclContext *Primary = const_cast(this)->getPrimaryContext(); if (Primary->hasExternalVisibleStorage()) getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); @@ -75,7 +77,7 @@ DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { return all_lookups_iterator(); } -DeclContext::all_lookups_iterator DeclContext::lookups_end() const { +inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const { DeclContext *Primary = const_cast(this)->getPrimaryContext(); if (Primary->hasExternalVisibleStorage()) getParentASTContext().getExternalSource()->completeVisibleDeclsMap(Primary); @@ -84,6 +86,22 @@ DeclContext::all_lookups_iterator DeclContext::lookups_end() const { return all_lookups_iterator(); } +inline +DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const { + DeclContext *Primary = const_cast(this)->getPrimaryContext(); + if (StoredDeclsMap *Map = Primary->getLookupPtr()) + return all_lookups_iterator(Map->begin(), Map->end()); + return all_lookups_iterator(); +} + +inline +DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const { + DeclContext *Primary = const_cast(this)->getPrimaryContext(); + if (StoredDeclsMap *Map = Primary->getLookupPtr()) + return all_lookups_iterator(Map->end(), Map->end()); + return all_lookups_iterator(); +} + } // end namespace clang #endif diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 40de0135a74f..2e760d658e43 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -452,7 +452,7 @@ public: } /// \brief Determine whether this method has a body. - virtual bool hasBody() const { return Body; } + virtual bool hasBody() const { return Body.isValid(); } /// \brief Retrieve the body of this method, if it has one. virtual Stmt *getBody() const; @@ -463,7 +463,7 @@ public: void setBody(Stmt *B) { Body = B; } /// \brief Returns whether this specific method is a definition. - bool isThisDeclarationADefinition() const { return Body; } + bool isThisDeclarationADefinition() const { return hasBody(); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -553,6 +553,9 @@ public: typedef llvm::DenseMap PropertyMap; + typedef llvm::DenseMap + ProtocolPropertyMap; + typedef llvm::SmallVector PropertyDeclOrder; /// This routine collects list of properties to be implemented in the class. @@ -1133,6 +1136,8 @@ public: return lookupInstanceVariable(IVarName, ClassDeclared); } + ObjCProtocolDecl *lookupNestedProtocol(IdentifierInfo *Name); + // Lookup a method. First, we search locally. If a method isn't // found, we search referenced protocols and class categories. ObjCMethodDecl *lookupMethod(Selector Sel, bool isInstance, @@ -1196,14 +1201,11 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; /// Retrieves the canonical declaration of this Objective-C class. - ObjCInterfaceDecl *getCanonicalDecl() { - return getFirstDeclaration(); - } - const ObjCInterfaceDecl *getCanonicalDecl() const { - return getFirstDeclaration(); - } + ObjCInterfaceDecl *getCanonicalDecl() { return getFirstDecl(); } + const ObjCInterfaceDecl *getCanonicalDecl() const { return getFirstDecl(); } // Low-level accessor const Type *getTypeForDecl() const { return TypeForDecl; } @@ -1244,10 +1246,12 @@ private: ObjCIvarDecl(ObjCContainerDecl *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW, - bool synthesized) + bool synthesized, + bool backingIvarReferencedInAccessor) : FieldDecl(ObjCIvar, DC, StartLoc, IdLoc, Id, T, TInfo, BW, /*Mutable=*/false, /*HasInit=*/ICIS_NoInit), - NextIvar(0), DeclAccess(ac), Synthesized(synthesized) {} + NextIvar(0), DeclAccess(ac), Synthesized(synthesized), + BackingIvarReferencedInAccessor(backingIvarReferencedInAccessor) {} public: static ObjCIvarDecl *Create(ASTContext &C, ObjCContainerDecl *DC, @@ -1255,7 +1259,8 @@ public: IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, AccessControl ac, Expr *BW = NULL, - bool synthesized=false); + bool synthesized=false, + bool backingIvarReferencedInAccessor=false); static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1277,6 +1282,13 @@ public: return DeclAccess == None ? Protected : AccessControl(DeclAccess); } + void setBackingIvarReferencedInAccessor(bool val) { + BackingIvarReferencedInAccessor = val; + } + bool getBackingIvarReferencedInAccessor() const { + return BackingIvarReferencedInAccessor; + } + void setSynthesize(bool synth) { Synthesized = synth; } bool getSynthesize() const { return Synthesized; } @@ -1291,6 +1303,7 @@ private: // NOTE: VC++ treats enums as signed, avoid using the AccessControl enum unsigned DeclAccess : 3; unsigned Synthesized : 1; + unsigned BackingIvarReferencedInAccessor : 1; }; @@ -1502,17 +1515,17 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; /// Retrieves the canonical declaration of this Objective-C protocol. - ObjCProtocolDecl *getCanonicalDecl() { - return getFirstDeclaration(); - } - const ObjCProtocolDecl *getCanonicalDecl() const { - return getFirstDeclaration(); - } + ObjCProtocolDecl *getCanonicalDecl() { return getFirstDecl(); } + const ObjCProtocolDecl *getCanonicalDecl() const { return getFirstDecl(); } virtual void collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const; + +void collectInheritedProtocolProperties(const ObjCPropertyDecl *Property, + ProtocolPropertyMap &PM) const; static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProtocol; } diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index ca92040c3286..42fe907aa174 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -1,4 +1,4 @@ -//===--- OpenMP.h - Classes for representing OpenMP directives ---*- C++ -*-===// +//===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines OpenMP nodes. +/// \brief This file defines OpenMP nodes for declarative directives. /// //===----------------------------------------------------------------------===// @@ -20,8 +20,6 @@ namespace clang { -class DeclRefExpr; - /// \brief This represents '#pragma omp threadprivate ...' directive. /// For example, in the following, both 'a' and 'A::b' are threadprivate: /// @@ -43,29 +41,29 @@ class OMPThreadPrivateDecl : public Decl { OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) : Decl(DK, DC, L), NumVars(0) { } - ArrayRef getVars() const { - return ArrayRef( - reinterpret_cast(this + 1), + ArrayRef getVars() const { + return ArrayRef( + reinterpret_cast(this + 1), NumVars); } - llvm::MutableArrayRef getVars() { - return llvm::MutableArrayRef( - reinterpret_cast(this + 1), + llvm::MutableArrayRef getVars() { + return llvm::MutableArrayRef( + reinterpret_cast(this + 1), NumVars); } - void setVars(ArrayRef VL); + void setVars(ArrayRef VL); public: static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, - ArrayRef VL); + ArrayRef VL); static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned N); - typedef llvm::MutableArrayRef::iterator varlist_iterator; - typedef ArrayRef::iterator varlist_const_iterator; + typedef llvm::MutableArrayRef::iterator varlist_iterator; + typedef ArrayRef::iterator varlist_const_iterator; unsigned varlist_size() const { return NumVars; } bool varlist_empty() const { return NumVars == 0; } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 425a617738b0..24bd28a75aaa 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -34,6 +34,8 @@ class TemplateTypeParmDecl; class NonTypeTemplateParmDecl; class TemplateTemplateParmDecl; class TypeAliasTemplateDecl; +class VarTemplateDecl; +class VarTemplatePartialSpecializationDecl; /// \brief Stores a template parameter of any kind. typedef llvm::PointerUnion3 friend class RedeclarableTemplate; /// \brief Retrieves the canonical declaration of this template. - RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDeclaration(); } - const RedeclarableTemplateDecl *getCanonicalDecl() const { - return getFirstDeclaration(); + RedeclarableTemplateDecl *getCanonicalDecl() { return getFirstDecl(); } + const RedeclarableTemplateDecl *getCanonicalDecl() const { + return getFirstDecl(); } /// \brief Determines whether this template was a specialization of a @@ -713,6 +715,7 @@ public: using redeclarable_base::redecls_end; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -743,7 +746,7 @@ protected: /// \brief Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { - Common() : InjectedArgs(0) { } + Common() : InjectedArgs(), LazySpecializations() { } /// \brief The function template specializations for this function /// template, including explicit specializations and instantiations. @@ -757,6 +760,13 @@ protected: /// template, and is allocated lazily, since most function templates do not /// require the use of this information. TemplateArgument *InjectedArgs; + + /// \brief If non-null, points to an array of specializations known only + /// by their external declaration IDs. + /// + /// The first value in the array is the number of of specializations + /// that follow. + uint32_t *LazySpecializations; }; FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -771,12 +781,13 @@ protected: friend class FunctionDecl; + /// \brief Load any lazily-loaded specializations from the external source. + void LoadLazySpecializations() const; + /// \brief Retrieve the set of function template specializations of this /// function template. llvm::FoldingSetVector & - getSpecializations() const { - return getCommonPtr()->Specializations; - } + getSpecializations() const; /// \brief Add a specialization of this function template. /// @@ -815,14 +826,14 @@ public: /// NULL if no such declaration exists. FunctionTemplateDecl *getPreviousDecl() { return cast_or_null( - RedeclarableTemplateDecl::getPreviousDecl()); + static_cast(this)->getPreviousDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. const FunctionTemplateDecl *getPreviousDecl() const { return cast_or_null( - RedeclarableTemplateDecl::getPreviousDecl()); + static_cast(this)->getPreviousDecl()); } FunctionTemplateDecl *getInstantiatedFromMemberTemplate() { @@ -847,7 +858,7 @@ public: /// arguments for a function template, the notion is convenient when /// we need to perform substitutions inside the definition of a function /// template. - std::pair getInjectedTemplateArgs(); + ArrayRef getInjectedTemplateArgs(); /// \brief Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, @@ -1377,7 +1388,7 @@ class ClassTemplateSpecializationDecl /// \brief The template argument list deduced for the class template /// partial specialization itself. - TemplateArgumentList *TemplateArgs; + const TemplateArgumentList *TemplateArgs; }; /// \brief The template that this specialization specializes @@ -1402,7 +1413,7 @@ class ClassTemplateSpecializationDecl ExplicitSpecializationInfo *ExplicitInfo; /// \brief The template arguments used to describe this specialization. - TemplateArgumentList *TemplateArgs; + const TemplateArgumentList *TemplateArgs; /// \brief The point where this template was instantiated (if any) SourceLocation PointOfInstantiation; @@ -1438,9 +1449,9 @@ public: bool Qualified) const; ClassTemplateSpecializationDecl *getMostRecentDecl() { - CXXRecordDecl *Recent - = cast(CXXRecordDecl::getMostRecentDecl()); - if (!isa(Recent)) { + CXXRecordDecl *Recent = static_cast( + this)->getMostRecentDecl(); + while (!isa(Recent)) { // FIXME: Does injected class name need to be in the redeclarations chain? assert(Recent->isInjectedClassName() && Recent->getPreviousDecl()); Recent = Recent->getPreviousDecl(); @@ -1553,7 +1564,7 @@ public: /// instantiation of the given class template partial specialization whose /// template arguments have been deduced. void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, - TemplateArgumentList *TemplateArgs) { + const TemplateArgumentList *TemplateArgs) { assert(!SpecializedTemplate.is() && "Already set to a class template partial specialization!"); SpecializedPartialSpecialization *PS @@ -1639,13 +1650,7 @@ class ClassTemplatePartialSpecializationDecl /// \brief The source info for the template arguments as written. /// FIXME: redundant with TypeAsWritten? - TemplateArgumentLoc *ArgsAsWritten; - unsigned NumArgsAsWritten; - - /// \brief Sequence number indicating when this class template partial - /// specialization was added to the set of partial specializations for - /// its owning class template. - unsigned SequenceNumber; + const ASTTemplateArgumentListInfo *ArgsAsWritten; /// \brief The class template partial specialization from which this /// class template partial specialization was instantiated. @@ -1663,16 +1668,12 @@ class ClassTemplatePartialSpecializationDecl ClassTemplateDecl *SpecializedTemplate, const TemplateArgument *Args, unsigned NumArgs, - TemplateArgumentLoc *ArgInfos, - unsigned NumArgInfos, - ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber); + const ASTTemplateArgumentListInfo *ArgsAsWritten, + ClassTemplatePartialSpecializationDecl *PrevDecl); ClassTemplatePartialSpecializationDecl() : ClassTemplateSpecializationDecl(ClassTemplatePartialSpecialization), - TemplateParams(0), ArgsAsWritten(0), - NumArgsAsWritten(0), SequenceNumber(0), - InstantiatedFromMember(0, false) { } + TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) { } public: static ClassTemplatePartialSpecializationDecl * @@ -1684,15 +1685,15 @@ public: unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, - ClassTemplatePartialSpecializationDecl *PrevDecl, - unsigned SequenceNumber); + ClassTemplatePartialSpecializationDecl *PrevDecl); static ClassTemplatePartialSpecializationDecl * CreateDeserialized(ASTContext &C, unsigned ID); ClassTemplatePartialSpecializationDecl *getMostRecentDecl() { return cast( - ClassTemplateSpecializationDecl::getMostRecentDecl()); + static_cast( + this)->getMostRecentDecl()); } /// Get the list of template parameters @@ -1701,19 +1702,10 @@ public: } /// Get the template arguments as written. - TemplateArgumentLoc *getTemplateArgsAsWritten() const { + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { return ArgsAsWritten; } - /// Get the number of template arguments as written. - unsigned getNumTemplateArgsAsWritten() const { - return NumArgsAsWritten; - } - - /// \brief Get the sequence number for this class template partial - /// specialization. - unsigned getSequenceNumber() const { return SequenceNumber; } - /// \brief Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. @@ -1735,15 +1727,15 @@ public: /// \c Outer::Inner, this function would return /// \c Outer::Inner. ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() { - ClassTemplatePartialSpecializationDecl *First - = cast(getFirstDeclaration()); + ClassTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); return First->InstantiatedFromMember.getPointer(); } void setInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *PartialSpec) { - ClassTemplatePartialSpecializationDecl *First - = cast(getFirstDeclaration()); + ClassTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); First->InstantiatedFromMember.setPointer(PartialSpec); } @@ -1764,15 +1756,15 @@ public: /// struct X::Inner { /* ... */ }; /// \endcode bool isMemberSpecialization() { - ClassTemplatePartialSpecializationDecl *First - = cast(getFirstDeclaration()); + ClassTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); return First->InstantiatedFromMember.getInt(); } /// \brief Note that this member template is a specialization. void setMemberSpecialization() { - ClassTemplatePartialSpecializationDecl *First - = cast(getFirstDeclaration()); + ClassTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); assert(First->InstantiatedFromMember.getPointer() && "Only member templates can be member template specializations"); return First->InstantiatedFromMember.setInt(true); @@ -1821,7 +1813,7 @@ protected: QualType InjectedClassNameType; /// \brief If non-null, points to an array of specializations (including - /// partial specializations) known ownly by their external declaration IDs. + /// partial specializations) known only by their external declaration IDs. /// /// The first value in the array is the number of of specializations/ /// partial specializations that follow. @@ -1900,14 +1892,23 @@ public: /// NULL if no such declaration exists. ClassTemplateDecl *getPreviousDecl() { return cast_or_null( - RedeclarableTemplateDecl::getPreviousDecl()); + static_cast(this)->getPreviousDecl()); } /// \brief Retrieve the previous declaration of this class template, or /// NULL if no such declaration exists. const ClassTemplateDecl *getPreviousDecl() const { return cast_or_null( - RedeclarableTemplateDecl::getPreviousDecl()); + static_cast( + this)->getPreviousDecl()); + } + + ClassTemplateDecl *getMostRecentDecl() { + return cast( + static_cast(this)->getMostRecentDecl()); + } + const ClassTemplateDecl *getMostRecentDecl() const { + return const_cast(this)->getMostRecentDecl(); } ClassTemplateDecl *getInstantiatedFromMemberTemplate() { @@ -1926,11 +1927,6 @@ public: void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, void *InsertPos); - /// \brief Return the next partial specialization sequence number. - unsigned getNextPartialSpecSequenceNumber() { - return getPartialSpecializations().size(); - } - /// \brief Retrieve the partial specializations as an ordered list. void getPartialSpecializations( SmallVectorImpl &PS); @@ -2139,14 +2135,15 @@ public: /// NULL if no such declaration exists. TypeAliasTemplateDecl *getPreviousDecl() { return cast_or_null( - RedeclarableTemplateDecl::getPreviousDecl()); + static_cast(this)->getPreviousDecl()); } /// \brief Retrieve the previous declaration of this function template, or /// NULL if no such declaration exists. const TypeAliasTemplateDecl *getPreviousDecl() const { return cast_or_null( - RedeclarableTemplateDecl::getPreviousDecl()); + static_cast( + this)->getPreviousDecl()); } TypeAliasTemplateDecl *getInstantiatedFromMemberTemplate() { @@ -2239,6 +2236,578 @@ public: inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) : Function(FTD) { } +/// \brief Represents a variable template specialization, which refers to +/// a variable template with a given set of template arguments. +/// +/// Variable template specializations represent both explicit +/// specializations of variable templates, as in the example below, and +/// implicit instantiations of variable templates. +/// +/// \code +/// template constexpr T pi = T(3.1415926535897932385); +/// +/// template<> +/// constexpr float pi; // variable template specialization pi +/// \endcode +class VarTemplateSpecializationDecl : public VarDecl, + public llvm::FoldingSetNode { + + /// \brief Structure that stores information about a variable template + /// specialization that was instantiated from a variable template partial + /// specialization. + struct SpecializedPartialSpecialization { + /// \brief The variable template partial specialization from which this + /// variable template specialization was instantiated. + VarTemplatePartialSpecializationDecl *PartialSpecialization; + + /// \brief The template argument list deduced for the variable template + /// partial specialization itself. + const TemplateArgumentList *TemplateArgs; + }; + + /// \brief The template that this specialization specializes. + llvm::PointerUnion + SpecializedTemplate; + + /// \brief Further info for explicit template specialization/instantiation. + struct ExplicitSpecializationInfo { + /// \brief The type-as-written. + TypeSourceInfo *TypeAsWritten; + /// \brief The location of the extern keyword. + SourceLocation ExternLoc; + /// \brief The location of the template keyword. + SourceLocation TemplateKeywordLoc; + + ExplicitSpecializationInfo() + : TypeAsWritten(0), ExternLoc(), TemplateKeywordLoc() {} + }; + + /// \brief Further info for explicit template specialization/instantiation. + /// Does not apply to implicit specializations. + ExplicitSpecializationInfo *ExplicitInfo; + + /// \brief The template arguments used to describe this specialization. + const TemplateArgumentList *TemplateArgs; + TemplateArgumentListInfo TemplateArgsInfo; + + /// \brief The point where this template was instantiated (if any). + SourceLocation PointOfInstantiation; + + /// \brief The kind of specialization this declaration refers to. + /// Really a value of type TemplateSpecializationKind. + unsigned SpecializationKind : 3; + +protected: + VarTemplateSpecializationDecl(ASTContext &Context, Kind DK, DeclContext *DC, + SourceLocation StartLoc, SourceLocation IdLoc, + VarTemplateDecl *SpecializedTemplate, + QualType T, TypeSourceInfo *TInfo, + StorageClass S, const TemplateArgument *Args, + unsigned NumArgs); + + explicit VarTemplateSpecializationDecl(Kind DK); + +public: + static VarTemplateSpecializationDecl * + Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, + TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, + unsigned NumArgs); + static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + virtual void getNameForDiagnostic(raw_ostream &OS, + const PrintingPolicy &Policy, + bool Qualified) const; + + VarTemplateSpecializationDecl *getMostRecentDecl() { + VarDecl *Recent = static_cast(this)->getMostRecentDecl(); + return cast(Recent); + } + + /// \brief Retrieve the template that this specialization specializes. + VarTemplateDecl *getSpecializedTemplate() const; + + /// \brief Retrieve the template arguments of the variable template + /// specialization. + const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; } + + // TODO: Always set this when creating the new specialization? + void setTemplateArgsInfo(const TemplateArgumentListInfo &ArgsInfo); + + const TemplateArgumentListInfo &getTemplateArgsInfo() const { + return TemplateArgsInfo; + } + + /// \brief Determine the kind of specialization that this + /// declaration represents. + TemplateSpecializationKind getSpecializationKind() const { + return static_cast(SpecializationKind); + } + + bool isExplicitSpecialization() const { + return getSpecializationKind() == TSK_ExplicitSpecialization; + } + + /// \brief True if this declaration is an explicit specialization, + /// explicit instantiation declaration, or explicit instantiation + /// definition. + bool isExplicitInstantiationOrSpecialization() const { + switch (getTemplateSpecializationKind()) { + case TSK_ExplicitSpecialization: + case TSK_ExplicitInstantiationDeclaration: + case TSK_ExplicitInstantiationDefinition: + return true; + + case TSK_Undeclared: + case TSK_ImplicitInstantiation: + return false; + } + llvm_unreachable("bad template specialization kind"); + } + + void setSpecializationKind(TemplateSpecializationKind TSK) { + SpecializationKind = TSK; + } + + /// \brief Get the point of instantiation (if any), or null if none. + SourceLocation getPointOfInstantiation() const { + return PointOfInstantiation; + } + + void setPointOfInstantiation(SourceLocation Loc) { + assert(Loc.isValid() && "point of instantiation must be valid!"); + PointOfInstantiation = Loc; + } + + /// \brief If this variable template specialization is an instantiation of + /// a template (rather than an explicit specialization), return the + /// variable template or variable template partial specialization from which + /// it was instantiated. + llvm::PointerUnion + getInstantiatedFrom() const { + if (getSpecializationKind() != TSK_ImplicitInstantiation && + getSpecializationKind() != TSK_ExplicitInstantiationDefinition && + getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) + return llvm::PointerUnion(); + + if (SpecializedPartialSpecialization *PartialSpec = + SpecializedTemplate.dyn_cast()) + return PartialSpec->PartialSpecialization; + + return SpecializedTemplate.get(); + } + + /// \brief Retrieve the variable template or variable template partial + /// specialization which was specialized by this. + llvm::PointerUnion + getSpecializedTemplateOrPartial() const { + if (SpecializedPartialSpecialization *PartialSpec = + SpecializedTemplate.dyn_cast()) + return PartialSpec->PartialSpecialization; + + return SpecializedTemplate.get(); + } + + /// \brief Retrieve the set of template arguments that should be used + /// to instantiate the initializer of the variable template or variable + /// template partial specialization from which this variable template + /// specialization was instantiated. + /// + /// \returns For a variable template specialization instantiated from the + /// primary template, this function will return the same template arguments + /// as getTemplateArgs(). For a variable template specialization instantiated + /// from a variable template partial specialization, this function will the + /// return deduced template arguments for the variable template partial + /// specialization itself. + const TemplateArgumentList &getTemplateInstantiationArgs() const { + if (SpecializedPartialSpecialization *PartialSpec = + SpecializedTemplate.dyn_cast()) + return *PartialSpec->TemplateArgs; + + return getTemplateArgs(); + } + + /// \brief Note that this variable template specialization is actually an + /// instantiation of the given variable template partial specialization whose + /// template arguments have been deduced. + void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec, + const TemplateArgumentList *TemplateArgs) { + assert(!SpecializedTemplate.is() && + "Already set to a variable template partial specialization!"); + SpecializedPartialSpecialization *PS = + new (getASTContext()) SpecializedPartialSpecialization(); + PS->PartialSpecialization = PartialSpec; + PS->TemplateArgs = TemplateArgs; + SpecializedTemplate = PS; + } + + /// \brief Note that this variable template specialization is an instantiation + /// of the given variable template. + void setInstantiationOf(VarTemplateDecl *TemplDecl) { + assert(!SpecializedTemplate.is() && + "Previously set to a variable template partial specialization!"); + SpecializedTemplate = TemplDecl; + } + + /// \brief Sets the type of this specialization as it was written by + /// the user. + void setTypeAsWritten(TypeSourceInfo *T) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->TypeAsWritten = T; + } + /// \brief Gets the type of this specialization as it was written by + /// the user, if it was so written. + TypeSourceInfo *getTypeAsWritten() const { + return ExplicitInfo ? ExplicitInfo->TypeAsWritten : 0; + } + + /// \brief Gets the location of the extern keyword, if present. + SourceLocation getExternLoc() const { + return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); + } + /// \brief Sets the location of the extern keyword. + void setExternLoc(SourceLocation Loc) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->ExternLoc = Loc; + } + + /// \brief Sets the location of the template keyword. + void setTemplateKeywordLoc(SourceLocation Loc) { + if (!ExplicitInfo) + ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; + ExplicitInfo->TemplateKeywordLoc = Loc; + } + /// \brief Gets the location of the template keyword, if present. + SourceLocation getTemplateKeywordLoc() const { + return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + Profile(ID, TemplateArgs->data(), TemplateArgs->size(), getASTContext()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, + const TemplateArgument *TemplateArgs, + unsigned NumTemplateArgs, ASTContext &Context) { + ID.AddInteger(NumTemplateArgs); + for (unsigned Arg = 0; Arg != NumTemplateArgs; ++Arg) + TemplateArgs[Arg].Profile(ID, Context); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K >= firstVarTemplateSpecialization && + K <= lastVarTemplateSpecialization; + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + +class VarTemplatePartialSpecializationDecl + : public VarTemplateSpecializationDecl { + virtual void anchor(); + + /// \brief The list of template parameters + TemplateParameterList *TemplateParams; + + /// \brief The source info for the template arguments as written. + /// FIXME: redundant with TypeAsWritten? + const ASTTemplateArgumentListInfo *ArgsAsWritten; + + /// \brief The variable template partial specialization from which this + /// variable template partial specialization was instantiated. + /// + /// The boolean value will be true to indicate that this variable template + /// partial specialization was specialized at this level. + llvm::PointerIntPair + InstantiatedFromMember; + + VarTemplatePartialSpecializationDecl( + ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, + StorageClass S, const TemplateArgument *Args, unsigned NumArgs, + const ASTTemplateArgumentListInfo *ArgInfos); + + VarTemplatePartialSpecializationDecl() + : VarTemplateSpecializationDecl(VarTemplatePartialSpecialization), + TemplateParams(0), ArgsAsWritten(0), InstantiatedFromMember(0, false) {} + +public: + static VarTemplatePartialSpecializationDecl * + Create(ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, + SourceLocation IdLoc, TemplateParameterList *Params, + VarTemplateDecl *SpecializedTemplate, QualType T, + TypeSourceInfo *TInfo, StorageClass S, const TemplateArgument *Args, + unsigned NumArgs, const TemplateArgumentListInfo &ArgInfos); + + static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + VarTemplatePartialSpecializationDecl *getMostRecentDecl() { + return cast( + static_cast( + this)->getMostRecentDecl()); + } + + /// Get the list of template parameters + TemplateParameterList *getTemplateParameters() const { + return TemplateParams; + } + + /// Get the template arguments as written. + const ASTTemplateArgumentListInfo *getTemplateArgsAsWritten() const { + return ArgsAsWritten; + } + + /// \brief Retrieve the member variable template partial specialization from + /// which this particular variable template partial specialization was + /// instantiated. + /// + /// \code + /// template + /// struct Outer { + /// template U Inner; + /// template U* Inner = (U*)(0); // #1 + /// }; + /// + /// template int* Outer::Inner; + /// \endcode + /// + /// In this example, the instantiation of \c Outer::Inner will + /// end up instantiating the partial specialization + /// \c Outer::Inner, which itself was instantiated from the + /// variable template partial specialization \c Outer::Inner. Given + /// \c Outer::Inner, this function would return + /// \c Outer::Inner. + VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() { + VarTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); + return First->InstantiatedFromMember.getPointer(); + } + + void + setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) { + VarTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); + First->InstantiatedFromMember.setPointer(PartialSpec); + } + + /// \brief Determines whether this variable template partial specialization + /// was a specialization of a member partial specialization. + /// + /// In the following example, the member template partial specialization + /// \c X::Inner is a member specialization. + /// + /// \code + /// template + /// struct X { + /// template U Inner; + /// template U* Inner = (U*)(0); + /// }; + /// + /// template<> template + /// U* X::Inner = (T*)(0) + 1; + /// \endcode + bool isMemberSpecialization() { + VarTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); + return First->InstantiatedFromMember.getInt(); + } + + /// \brief Note that this member template is a specialization. + void setMemberSpecialization() { + VarTemplatePartialSpecializationDecl *First = + cast(getFirstDecl()); + assert(First->InstantiatedFromMember.getPointer() && + "Only member templates can be member template specializations"); + return First->InstantiatedFromMember.setInt(true); + } + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { + return K == VarTemplatePartialSpecialization; + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + +/// Declaration of a variable template. +class VarTemplateDecl : public RedeclarableTemplateDecl { + static void DeallocateCommon(void *Ptr); + +protected: + /// \brief Data that is common to all of the declarations of a given + /// variable template. + struct Common : CommonBase { + Common() : LazySpecializations() {} + + /// \brief The variable template specializations for this variable + /// template, including explicit specializations and instantiations. + llvm::FoldingSetVector Specializations; + + /// \brief The variable template partial specializations for this variable + /// template. + llvm::FoldingSetVector + PartialSpecializations; + + /// \brief If non-null, points to an array of specializations (including + /// partial specializations) known ownly by their external declaration IDs. + /// + /// The first value in the array is the number of of specializations/ + /// partial specializations that follow. + uint32_t *LazySpecializations; + }; + + /// \brief Load any lazily-loaded specializations from the external source. + void LoadLazySpecializations() const; + + /// \brief Retrieve the set of specializations of this variable template. + llvm::FoldingSetVector & + getSpecializations() const; + + /// \brief Retrieve the set of partial specializations of this class + /// template. + llvm::FoldingSetVector & + getPartialSpecializations(); + + VarTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : RedeclarableTemplateDecl(VarTemplate, DC, L, Name, Params, Decl) {} + + VarTemplateDecl(EmptyShell Empty) + : RedeclarableTemplateDecl(VarTemplate, 0, SourceLocation(), + DeclarationName(), 0, 0) {} + + CommonBase *newCommon(ASTContext &C) const; + + Common *getCommonPtr() const { + return static_cast(RedeclarableTemplateDecl::getCommonPtr()); + } + +public: + /// \brief Get the underlying variable declarations of the template. + VarDecl *getTemplatedDecl() const { + return static_cast(TemplatedDecl); + } + + /// \brief Returns whether this template declaration defines the primary + /// variable pattern. + bool isThisDeclarationADefinition() const { + return getTemplatedDecl()->isThisDeclarationADefinition(); + } + + VarTemplateDecl *getDefinition(); + + /// \brief Create a variable template node. + static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl, + VarTemplateDecl *PrevDecl); + + /// \brief Create an empty variable template node. + static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + /// \brief Return the specialization with the provided arguments if it exists, + /// otherwise return the insertion point. + VarTemplateSpecializationDecl * + findSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + /// \brief Insert the specified specialization knowing that it is not already + /// in. InsertPos must be obtained from findSpecialization. + void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos); + + VarTemplateDecl *getCanonicalDecl() { + return cast(RedeclarableTemplateDecl::getCanonicalDecl()); + } + const VarTemplateDecl *getCanonicalDecl() const { + return cast(RedeclarableTemplateDecl::getCanonicalDecl()); + } + + /// \brief Retrieve the previous declaration of this variable template, or + /// NULL if no such declaration exists. + VarTemplateDecl *getPreviousDecl() { + return cast_or_null( + static_cast(this)->getPreviousDecl()); + } + + /// \brief Retrieve the previous declaration of this variable template, or + /// NULL if no such declaration exists. + const VarTemplateDecl *getPreviousDecl() const { + return cast_or_null( + static_cast( + this)->getPreviousDecl()); + } + + VarTemplateDecl *getInstantiatedFromMemberTemplate() { + return cast_or_null( + RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); + } + + /// \brief Return the partial specialization with the provided arguments if it + /// exists, otherwise return the insertion point. + VarTemplatePartialSpecializationDecl * + findPartialSpecialization(const TemplateArgument *Args, unsigned NumArgs, + void *&InsertPos); + + /// \brief Insert the specified partial specialization knowing that it is not + /// already in. InsertPos must be obtained from findPartialSpecialization. + void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D, + void *InsertPos); + + /// \brief Retrieve the partial specializations as an ordered list. + void getPartialSpecializations( + SmallVectorImpl &PS); + + /// \brief Find a variable template partial specialization which was + /// instantiated + /// from the given member partial specialization. + /// + /// \param D a member variable template partial specialization. + /// + /// \returns the variable template partial specialization which was + /// instantiated + /// from the given member partial specialization, or NULL if no such partial + /// specialization exists. + VarTemplatePartialSpecializationDecl *findPartialSpecInstantiatedFromMember( + VarTemplatePartialSpecializationDecl *D); + + typedef SpecIterator spec_iterator; + + spec_iterator spec_begin() const { + return makeSpecIterator(getSpecializations(), false); + } + + spec_iterator spec_end() const { + return makeSpecIterator(getSpecializations(), true); + } + + typedef SpecIterator + partial_spec_iterator; + + partial_spec_iterator partial_spec_begin() { + return makeSpecIterator(getPartialSpecializations(), false); + } + + partial_spec_iterator partial_spec_end() { + return makeSpecIterator(getPartialSpecializations(), true); + } + + // Implement isa/cast/dyncast support + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == VarTemplate; } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + } /* end of namespace clang */ #endif diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index f28882b3bf94..00766c27c136 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -182,11 +182,16 @@ public: // operator bool() - Evaluates true when this declaration name is // non-empty. - operator bool() const { + LLVM_EXPLICIT operator bool() const { return ((Ptr & PtrMask) != 0) || (reinterpret_cast(Ptr & ~PtrMask)); } + /// \brief Evaluates true when this declaration name is empty. + bool isEmpty() const { + return !*this; + } + /// Predicate functions for querying what type of name this is. bool isIdentifier() const { return getStoredNameKind() == StoredIdentifier; } bool isObjCZeroArgSelector() const { @@ -210,9 +215,6 @@ public: /// getNameAsString - Retrieve the human-readable string for this name. std::string getAsString() const; - /// printName - Print the human-readable name to a stream. - void printName(raw_ostream &OS) const; - /// getAsIdentifierInfo - Retrieve the IdentifierInfo * stored in /// this declaration name, or NULL if this declaration name isn't a /// simple identifier. @@ -302,6 +304,8 @@ public: void dump() const; }; +raw_ostream &operator<<(raw_ostream &OS, DeclarationName N); + /// Ordering on two declaration names. If both names are identifiers, /// this provides a lexicographical ordering. inline bool operator<(DeclarationName LHS, DeclarationName RHS) { diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index 2e3cbfad919d..12c4fcc49b01 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -53,7 +53,7 @@ public: if (E->getCond()->isValueDependent()) return; // Only the selected subexpression matters; the other one is not evaluated. - return this->Visit(E->getChosenSubExpr(Context)); + return this->Visit(E->getChosenSubExpr()); } void VisitDesignatedInitExpr(DesignatedInitExpr *E) { diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 4ff1257b7dc8..f2648b9a4a04 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -277,7 +277,6 @@ public: MLV_IncompleteType, MLV_ConstQualified, MLV_ArrayType, - MLV_ReadonlyProperty, MLV_NoSetterProperty, MLV_MemberFunction, MLV_SubObjCPropertySetting, @@ -483,21 +482,22 @@ public: /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - bool isIntegerConstantExpr(llvm::APSInt &Result, ASTContext &Ctx, + bool isIntegerConstantExpr(llvm::APSInt &Result, const ASTContext &Ctx, SourceLocation *Loc = 0, bool isEvaluated = true) const; - bool isIntegerConstantExpr(ASTContext &Ctx, SourceLocation *Loc = 0) const; + bool isIntegerConstantExpr(const ASTContext &Ctx, + SourceLocation *Loc = 0) const; /// isCXX98IntegralConstantExpr - Return true if this expression is an /// integral constant expression in C++98. Can only be used in C++. - bool isCXX98IntegralConstantExpr(ASTContext &Ctx) const; + bool isCXX98IntegralConstantExpr(const ASTContext &Ctx) const; /// isCXX11ConstantExpr - Return true if this expression is a constant /// expression in C++11. Can only be used in C++. /// /// Note: This does not perform the implicit conversions required by C++11 /// [expr.const]p5. - bool isCXX11ConstantExpr(ASTContext &Ctx, APValue *Result = 0, + bool isCXX11ConstantExpr(const ASTContext &Ctx, APValue *Result = 0, SourceLocation *Loc = 0) const; /// isPotentialConstantExpr - Return true if this function's definition @@ -579,15 +579,14 @@ public: /// \brief Determine whether this expression involves a call to any function /// that is not trivial. bool hasNonTrivialCall(ASTContext &Ctx); - + /// EvaluateKnownConstInt - Call EvaluateAsRValue and return the folded /// integer. This must be called on an expression that constant folds to an /// integer. llvm::APSInt EvaluateKnownConstInt(const ASTContext &Ctx, SmallVectorImpl *Diag=0) const; - - void EvaluateForOverflow(const ASTContext &Ctx, - SmallVectorImpl *Diag) const; + + void EvaluateForOverflow(const ASTContext &Ctx) const; /// EvaluateAsLValue - Evaluate an expression to see if we can fold it to an /// lvalue with link time known address, with no side-effects. @@ -760,10 +759,10 @@ public: /// Walk outwards from an expression we want to bind a reference to and /// find the expression whose lifetime needs to be extended. Record - /// the adjustments needed along the path. - const Expr * - skipRValueSubobjectAdjustments( - SmallVectorImpl &Adjustments) const; + /// the LHSs of comma expressions and adjustments needed along the path. + const Expr *skipRValueSubobjectAdjustments( + SmallVectorImpl &CommaLHS, + SmallVectorImpl &Adjustments) const; /// Skip irrelevant expressions to find what should be materialize for /// binding with a reference. @@ -893,7 +892,7 @@ class DeclRefExpr : public Expr { bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } /// \brief Helper to retrieve the optional NamedDecl through which this - /// reference occured. + /// reference occurred. NamedDecl *&getInternalFoundDecl() { assert(hasFoundDecl()); if (hasQualifier()) @@ -902,12 +901,12 @@ class DeclRefExpr : public Expr { } /// \brief Helper to retrieve the optional NamedDecl through which this - /// reference occured. + /// reference occurred. NamedDecl *getInternalFoundDecl() const { return const_cast(this)->getInternalFoundDecl(); } - DeclRefExpr(ASTContext &Ctx, + DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, bool refersToEnclosingLocal, @@ -922,7 +921,7 @@ class DeclRefExpr : public Expr { /// \brief Computes the type- and value-dependence flags for this /// declaration reference expression. - void computeDependence(ASTContext &C); + void computeDependence(const ASTContext &C); public: DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T, @@ -938,7 +937,7 @@ public: computeDependence(D->getASTContext()); } - static DeclRefExpr *Create(ASTContext &Context, + static DeclRefExpr *Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, @@ -948,7 +947,7 @@ public: NamedDecl *FoundD = 0, const TemplateArgumentListInfo *TemplateArgs = 0); - static DeclRefExpr *Create(ASTContext &Context, + static DeclRefExpr *Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *D, @@ -959,7 +958,7 @@ public: const TemplateArgumentListInfo *TemplateArgs = 0); /// \brief Construct an empty declaration reference expression. - static DeclRefExpr *CreateEmpty(ASTContext &Context, + static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, bool HasFoundDecl, bool HasTemplateKWAndArgsInfo, @@ -1000,7 +999,7 @@ public: return getInternalQualifierLoc(); } - /// \brief Get the NamedDecl through which this reference occured. + /// \brief Get the NamedDecl through which this reference occurred. /// /// This Decl may be different from the ValueDecl actually referred to in the /// presence of using declarations, etc. It always returns non-NULL, and may @@ -1151,6 +1150,7 @@ public: Func, Function, LFunction, // Same as Function, but as wide string. + FuncDName, PrettyFunction, /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. @@ -1221,13 +1221,15 @@ protected: else return llvm::APInt(BitWidth, VAL); } - void setIntValue(ASTContext &C, const llvm::APInt &Val); + void setIntValue(const ASTContext &C, const llvm::APInt &Val); }; class APIntStorage : private APNumericStorage { public: llvm::APInt getValue() const { return getIntValue(); } - void setValue(ASTContext &C, const llvm::APInt &Val) { setIntValue(C, Val); } + void setValue(const ASTContext &C, const llvm::APInt &Val) { + setIntValue(C, Val); + } }; class APFloatStorage : private APNumericStorage { @@ -1235,7 +1237,7 @@ public: llvm::APFloat getValue(const llvm::fltSemantics &Semantics) const { return llvm::APFloat(Semantics, getIntValue()); } - void setValue(ASTContext &C, const llvm::APFloat &Val) { + void setValue(const ASTContext &C, const llvm::APFloat &Val) { setIntValue(C, Val.bitcastToAPInt()); } }; @@ -1250,17 +1252,17 @@ class IntegerLiteral : public Expr, public APIntStorage { public: // type should be IntTy, LongTy, LongLongTy, UnsignedIntTy, UnsignedLongTy, // or UnsignedLongLongTy - IntegerLiteral(ASTContext &C, const llvm::APInt &V, QualType type, + IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l); /// \brief Returns a new integer literal with value 'V' and type 'type'. /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy, /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V /// \param V - the value that the returned integer literal contains. - static IntegerLiteral *Create(ASTContext &C, const llvm::APInt &V, + static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l); /// \brief Returns a new empty integer literal. - static IntegerLiteral *Create(ASTContext &C, EmptyShell Empty); + static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty); SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } @@ -1328,21 +1330,21 @@ public: class FloatingLiteral : public Expr, private APFloatStorage { SourceLocation Loc; - FloatingLiteral(ASTContext &C, const llvm::APFloat &V, bool isexact, + FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L); /// \brief Construct an empty floating-point literal. - explicit FloatingLiteral(ASTContext &C, EmptyShell Empty); + explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty); public: - static FloatingLiteral *Create(ASTContext &C, const llvm::APFloat &V, + static FloatingLiteral *Create(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L); - static FloatingLiteral *Create(ASTContext &C, EmptyShell Empty); + static FloatingLiteral *Create(const ASTContext &C, EmptyShell Empty); llvm::APFloat getValue() const { return APFloatStorage::getValue(getSemantics()); } - void setValue(ASTContext &C, const llvm::APFloat &Val) { + void setValue(const ASTContext &C, const llvm::APFloat &Val) { assert(&getSemantics() == &Val.getSemantics() && "Inconsistent semantics"); APFloatStorage::setValue(C, Val); } @@ -1420,7 +1422,7 @@ public: }; /// StringLiteral - This represents a string literal expression, e.g. "foo" -/// or L"bar" (wide strings). The actual string is returned by getStrData() +/// or L"bar" (wide strings). The actual string is returned by getBytes() /// is NOT null-terminated, and the length of the string is determined by /// calling getByteLength(). The C type for a string is always a /// ConstantArrayType. In C++, the char type is const qualified, in C it is @@ -1469,19 +1471,19 @@ private: public: /// This is the "fully general" constructor that allows representation of /// strings formed from multiple concatenated tokens. - static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind, - bool Pascal, QualType Ty, + static StringLiteral *Create(const ASTContext &C, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, const SourceLocation *Loc, unsigned NumStrs); /// Simple constructor for string literals made from one token. - static StringLiteral *Create(ASTContext &C, StringRef Str, StringKind Kind, - bool Pascal, QualType Ty, + static StringLiteral *Create(const ASTContext &C, StringRef Str, + StringKind Kind, bool Pascal, QualType Ty, SourceLocation Loc) { return Create(C, Str, Kind, Pascal, Ty, &Loc, 1); } /// \brief Construct an empty string literal. - static StringLiteral *CreateEmpty(ASTContext &C, unsigned NumStrs); + static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs); StringRef getString() const { assert(CharByteWidth==1 @@ -1520,7 +1522,7 @@ public: unsigned getCharByteWidth() const { return CharByteWidth; } /// \brief Sets the string data to the given string data. - void setString(ASTContext &C, StringRef Str, + void setString(const ASTContext &C, StringRef Str, StringKind Kind, bool IsPascal); StringKind getKind() const { return static_cast(Kind); } @@ -1853,7 +1855,7 @@ private: // Number of sub-expressions (i.e. array subscript expressions). unsigned NumExprs; - OffsetOfExpr(ASTContext &C, QualType type, + OffsetOfExpr(const ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, ArrayRef comps, ArrayRef exprs, SourceLocation RParenLoc); @@ -1864,12 +1866,12 @@ private: public: - static OffsetOfExpr *Create(ASTContext &C, QualType type, + static OffsetOfExpr *Create(const ASTContext &C, QualType type, SourceLocation OperatorLoc, TypeSourceInfo *tsi, ArrayRef comps, ArrayRef exprs, SourceLocation RParenLoc); - static OffsetOfExpr *CreateEmpty(ASTContext &C, + static OffsetOfExpr *CreateEmpty(const ASTContext &C, unsigned NumComps, unsigned NumExprs); /// getOperatorLoc - Return the location of the operator. @@ -2133,10 +2135,11 @@ class CallExpr : public Expr { protected: // These versions of the constructor are for derived classes. - CallExpr(ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, + CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation rparenloc); - CallExpr(ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty); + CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, + EmptyShell Empty); Stmt *getPreArg(unsigned i) { assert(i < getNumPreArgs() && "Prearg access out of range!"); @@ -2154,11 +2157,11 @@ protected: unsigned getNumPreArgs() const { return CallExprBits.NumPreArgs; } public: - CallExpr(ASTContext& C, Expr *fn, ArrayRef args, QualType t, + CallExpr(const ASTContext& C, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation rparenloc); /// \brief Build an empty call expression. - CallExpr(ASTContext &C, StmtClass SC, EmptyShell Empty); + CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty); const Expr *getCallee() const { return cast(SubExprs[FN]); } Expr *getCallee() { return cast(SubExprs[FN]); } @@ -2206,7 +2209,7 @@ public: /// setNumArgs - This changes the number of arguments present in this call. /// Any orphaned expressions are deleted by this, and any new operands are set /// to null. - void setNumArgs(ASTContext& C, unsigned NumArgs); + void setNumArgs(const ASTContext& C, unsigned NumArgs); typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; @@ -2360,7 +2363,7 @@ public: HasQualifierOrFoundDecl(false), HasTemplateKWAndArgsInfo(false), HadMultipleCandidates(false) {} - static MemberExpr *Create(ASTContext &C, Expr *base, bool isarrow, + static MemberExpr *Create(const ASTContext &C, Expr *base, bool isarrow, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, ValueDecl *memberdecl, DeclAccessPair founddecl, @@ -2747,12 +2750,13 @@ public: : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { } - static ImplicitCastExpr *Create(ASTContext &Context, QualType T, + static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, ExprValueKind Cat); - static ImplicitCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); + static ImplicitCastExpr *CreateEmpty(const ASTContext &Context, + unsigned PathSize); SourceLocation getLocStart() const LLVM_READONLY { return getSubExpr()->getLocStart(); @@ -2838,13 +2842,14 @@ class CStyleCastExpr : public ExplicitCastExpr { : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } public: - static CStyleCastExpr *Create(ASTContext &Context, QualType T, + static CStyleCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *BasePath, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation R); - static CStyleCastExpr *CreateEmpty(ASTContext &Context, unsigned PathSize); + static CStyleCastExpr *CreateEmpty(const ASTContext &Context, + unsigned PathSize); SourceLocation getLParenLoc() const { return LPLoc; } void setLParenLoc(SourceLocation L) { LPLoc = L; } @@ -3412,7 +3417,7 @@ class ShuffleVectorExpr : public Expr { unsigned NumExprs; public: - ShuffleVectorExpr(ASTContext &C, ArrayRef args, QualType Type, + ShuffleVectorExpr(const ASTContext &C, ArrayRef args, QualType Type, SourceLocation BLoc, SourceLocation RP); /// \brief Build an empty vector-shuffle expression. @@ -3450,11 +3455,11 @@ public: return cast(SubExprs[Index]); } - void setExprs(ASTContext &C, Expr ** Exprs, unsigned NumExprs); + void setExprs(const ASTContext &C, ArrayRef Exprs); - unsigned getShuffleMaskIdx(ASTContext &Ctx, unsigned N) const { + llvm::APSInt getShuffleMaskIdx(const ASTContext &Ctx, unsigned N) const { assert((N < NumExprs - 2) && "Shuffle idx out of range!"); - return getExpr(N+2)->EvaluateKnownConstInt(Ctx).getZExtValue(); + return getExpr(N+2)->EvaluateKnownConstInt(Ctx); } // Iterators @@ -3463,6 +3468,60 @@ public: } }; +/// ConvertVectorExpr - Clang builtin function __builtin_convertvector +/// This AST node provides support for converting a vector type to another +/// vector type of the same arity. +class ConvertVectorExpr : public Expr { +private: + Stmt *SrcExpr; + TypeSourceInfo *TInfo; + SourceLocation BuiltinLoc, RParenLoc; + + friend class ASTReader; + friend class ASTStmtReader; + explicit ConvertVectorExpr(EmptyShell Empty) : Expr(ConvertVectorExprClass, Empty) {} + +public: + ConvertVectorExpr(Expr* SrcExpr, TypeSourceInfo *TI, QualType DstType, + ExprValueKind VK, ExprObjectKind OK, + SourceLocation BuiltinLoc, SourceLocation RParenLoc) + : Expr(ConvertVectorExprClass, DstType, VK, OK, + DstType->isDependentType(), + DstType->isDependentType() || SrcExpr->isValueDependent(), + (DstType->isInstantiationDependentType() || + SrcExpr->isInstantiationDependent()), + (DstType->containsUnexpandedParameterPack() || + SrcExpr->containsUnexpandedParameterPack())), + SrcExpr(SrcExpr), TInfo(TI), BuiltinLoc(BuiltinLoc), RParenLoc(RParenLoc) {} + + /// getSrcExpr - Return the Expr to be converted. + Expr *getSrcExpr() const { return cast(SrcExpr); } + + /// getTypeSourceInfo - Return the destination type. + TypeSourceInfo *getTypeSourceInfo() const { + return TInfo; + } + void setTypeSourceInfo(TypeSourceInfo *ti) { + TInfo = ti; + } + + /// getBuiltinLoc - Return the location of the __builtin_convertvector token. + SourceLocation getBuiltinLoc() const { return BuiltinLoc; } + + /// getRParenLoc - Return the location of final right parenthesis. + SourceLocation getRParenLoc() const { return RParenLoc; } + + SourceLocation getLocStart() const LLVM_READONLY { return BuiltinLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ConvertVectorExprClass; + } + + // Iterators + child_range children() { return child_range(&SrcExpr, &SrcExpr+1); } +}; + /// ChooseExpr - GNU builtin-in function __builtin_choose_expr. /// This AST node is similar to the conditional operator (?:) in C, with /// the following exceptions: @@ -3476,10 +3535,12 @@ class ChooseExpr : public Expr { enum { COND, LHS, RHS, END_EXPR }; Stmt* SubExprs[END_EXPR]; // Left/Middle/Right hand sides. SourceLocation BuiltinLoc, RParenLoc; + bool CondIsTrue; public: ChooseExpr(SourceLocation BLoc, Expr *cond, Expr *lhs, Expr *rhs, QualType t, ExprValueKind VK, ExprObjectKind OK, - SourceLocation RP, bool TypeDependent, bool ValueDependent) + SourceLocation RP, bool condIsTrue, + bool TypeDependent, bool ValueDependent) : Expr(ChooseExprClass, t, VK, OK, TypeDependent, ValueDependent, (cond->isInstantiationDependent() || lhs->isInstantiationDependent() || @@ -3487,7 +3548,7 @@ public: (cond->containsUnexpandedParameterPack() || lhs->containsUnexpandedParameterPack() || rhs->containsUnexpandedParameterPack())), - BuiltinLoc(BLoc), RParenLoc(RP) { + BuiltinLoc(BLoc), RParenLoc(RP), CondIsTrue(condIsTrue) { SubExprs[COND] = cond; SubExprs[LHS] = lhs; SubExprs[RHS] = rhs; @@ -3498,12 +3559,21 @@ public: /// isConditionTrue - Return whether the condition is true (i.e. not /// equal to zero). - bool isConditionTrue(const ASTContext &C) const; + bool isConditionTrue() const { + assert(!isConditionDependent() && + "Dependent condition isn't true or false"); + return CondIsTrue; + } + void setIsConditionTrue(bool isTrue) { CondIsTrue = isTrue; } + + bool isConditionDependent() const { + return getCond()->isTypeDependent() || getCond()->isValueDependent(); + } /// getChosenSubExpr - Return the subexpression chosen according to the /// condition. - Expr *getChosenSubExpr(const ASTContext &C) const { - return isConditionTrue(C) ? getLHS() : getRHS(); + Expr *getChosenSubExpr() const { + return isConditionTrue() ? getLHS() : getRHS(); } Expr *getCond() const { return cast(SubExprs[COND]); } @@ -3663,7 +3733,7 @@ class InitListExpr : public Expr { SourceLocation LBraceLoc, RBraceLoc; /// The alternative form of the initializer list (if it exists). - /// The int part of the pair stores whether this initalizer list is + /// The int part of the pair stores whether this initializer list is /// in semantic form. If not null, the pointer points to: /// - the syntactic form, if this is in semantic form; /// - the semantic form, if this is in syntactic form. @@ -3679,7 +3749,7 @@ class InitListExpr : public Expr { llvm::PointerUnion ArrayFillerOrUnionFieldInit; public: - InitListExpr(ASTContext &C, SourceLocation lbraceloc, + InitListExpr(const ASTContext &C, SourceLocation lbraceloc, ArrayRef initExprs, SourceLocation rbraceloc); /// \brief Build an empty initializer list. @@ -3707,7 +3777,7 @@ public: } /// \brief Reserve space for some number of initializers. - void reserveInits(ASTContext &C, unsigned NumInits); + void reserveInits(const ASTContext &C, unsigned NumInits); /// @brief Specify the number of initializers /// @@ -3715,7 +3785,7 @@ public: /// initializers will be destroyed. If there are fewer than @p /// NumInits initializers, NULL expressions will be added for the /// unknown initializers. - void resizeInits(ASTContext &Context, unsigned NumInits); + void resizeInits(const ASTContext &Context, unsigned NumInits); /// @brief Updates the initializer at index @p Init with the new /// expression @p expr, and returns the old expression at that @@ -3724,7 +3794,7 @@ public: /// When @p Init is out of range for this initializer list, the /// initializer list will be extended with NULL expressions to /// accommodate the new entry. - Expr *updateInit(ASTContext &C, unsigned Init, Expr *expr); + Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr); /// \brief If this initializer list initializes an array with more elements /// than there are initializers in the list, specifies an expression to be @@ -3754,6 +3824,10 @@ public: return const_cast(this)->getInitializedFieldInUnion(); } void setInitializedFieldInUnion(FieldDecl *FD) { + assert((FD == 0 + || getInitializedFieldInUnion() == 0 + || getInitializedFieldInUnion() == FD) + && "Only one field of a union may be initialized at a time!"); ArrayFillerOrUnionFieldInit = FD; } @@ -3794,13 +3868,6 @@ public: InitListExprBits.HadArrayRangeDesignator = ARD; } - bool initializesStdInitializerList() const { - return InitListExprBits.InitializesStdInitializerList != 0; - } - void setInitializesStdInitializerList(bool ISIL = true) { - InitListExprBits.InitializesStdInitializerList = ISIL; - } - SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; @@ -3851,7 +3918,7 @@ public: /// The InitListExpr contains three DesignatedInitExprs, the first of /// which covers @c [2].y=1.0. This DesignatedInitExpr will have two /// designators, one array designator for @c [2] followed by one field -/// designator for @c .y. The initalization expression will be 1.0. +/// designator for @c .y. The initialization expression will be 1.0. class DesignatedInitExpr : public Expr { public: /// \brief Forward declaration of the Designator class. @@ -3879,7 +3946,7 @@ private: Designator *Designators; - DesignatedInitExpr(ASTContext &C, QualType Ty, unsigned NumDesignators, + DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators, const Designator *Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, ArrayRef IndexExprs, Expr *Init); @@ -4041,13 +4108,15 @@ public: } }; - static DesignatedInitExpr *Create(ASTContext &C, Designator *Designators, + static DesignatedInitExpr *Create(const ASTContext &C, + Designator *Designators, unsigned NumDesignators, ArrayRef IndexExprs, SourceLocation EqualOrColonLoc, bool GNUSyntax, Expr *Init); - static DesignatedInitExpr *CreateEmpty(ASTContext &C, unsigned NumIndexExprs); + static DesignatedInitExpr *CreateEmpty(const ASTContext &C, + unsigned NumIndexExprs); /// @brief Returns the number of designators in this initializer. unsigned size() const { return NumDesignators; } @@ -4085,7 +4154,7 @@ public: Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } - void setDesignators(ASTContext &C, const Designator *Desigs, + void setDesignators(const ASTContext &C, const Designator *Desigs, unsigned NumDesigs); Expr *getArrayIndex(const Designator &D) const; @@ -4133,8 +4202,8 @@ public: /// \brief Replaces the designator at index @p Idx with the series /// of designators in [First, Last). - void ExpandDesignator(ASTContext &C, unsigned Idx, const Designator *First, - const Designator *Last); + void ExpandDesignator(const ASTContext &C, unsigned Idx, + const Designator *First, const Designator *Last); SourceRange getDesignatorsSourceRange() const; @@ -4188,8 +4257,8 @@ class ParenListExpr : public Expr { SourceLocation LParenLoc, RParenLoc; public: - ParenListExpr(ASTContext& C, SourceLocation lparenloc, ArrayRef exprs, - SourceLocation rparenloc); + ParenListExpr(const ASTContext& C, SourceLocation lparenloc, + ArrayRef exprs, SourceLocation rparenloc); /// \brief Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } @@ -4262,7 +4331,7 @@ class GenericSelectionExpr : public Expr { SourceLocation GenericLoc, DefaultLoc, RParenLoc; public: - GenericSelectionExpr(ASTContext &Context, + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, ArrayRef AssocExprs, @@ -4271,7 +4340,7 @@ public: unsigned ResultIndex); /// This constructor is used in the result-dependent case. - GenericSelectionExpr(ASTContext &Context, + GenericSelectionExpr(const ASTContext &Context, SourceLocation GenericLoc, Expr *ControllingExpr, ArrayRef AssocTypes, ArrayRef AssocExprs, @@ -4450,7 +4519,7 @@ public: /// AsTypeExpr - Clang builtin function __builtin_astype [OpenCL 6.2.4.2] /// This AST node provides support for reinterpreting a type to another /// type of the same size. -class AsTypeExpr : public Expr { // Should this be an ExplicitCastExpr? +class AsTypeExpr : public Expr { private: Stmt *SrcExpr; SourceLocation BuiltinLoc, RParenLoc; @@ -4552,13 +4621,13 @@ class PseudoObjectExpr : public Expr { public: /// NoResult - A value for the result index indicating that there is /// no semantic result. - enum { NoResult = ~0U }; + enum LLVM_ENUM_INT_TYPE(unsigned) { NoResult = ~0U }; - static PseudoObjectExpr *Create(ASTContext &Context, Expr *syntactic, + static PseudoObjectExpr *Create(const ASTContext &Context, Expr *syntactic, ArrayRef semantic, unsigned resultIndex); - static PseudoObjectExpr *Create(ASTContext &Context, EmptyShell shell, + static PseudoObjectExpr *Create(const ASTContext &Context, EmptyShell shell, unsigned numSemanticExprs); /// Return the syntactic form of this expression, i.e. the diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 91e5b21eacff..6356ee7aee63 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the Expr interface and subclasses for C++ expressions. -// +/// +/// \file +/// \brief Defines the clang::Expr interface and subclasses for C++ expressions. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXPRCXX_H @@ -74,15 +75,15 @@ public: CallExpr(C, CXXOperatorCallExprClass, Empty) { } - /// getOperator - Returns the kind of overloaded operator that this + /// \brief Returns the kind of overloaded operator that this /// expression refers to. OverloadedOperatorKind getOperator() const { return Operator; } - /// getOperatorLoc - Returns the location of the operator symbol in - /// the expression. When @c getOperator()==OO_Call, this is the - /// location of the right parentheses; when @c - /// getOperator()==OO_Subscript, this is the location of the right - /// bracket. + /// \brief Returns the location of the operator symbol in the expression. + /// + /// When \c getOperator()==OO_Call, this is the location of the right + /// parentheses; when \c getOperator()==OO_Subscript, this is the location + /// of the right bracket. SourceLocation getOperatorLoc() const { return getRParenLoc(); } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } @@ -105,7 +106,7 @@ public: friend class ASTStmtWriter; }; -/// CXXMemberCallExpr - Represents a call to a member function that +/// Represents a call to a member function that /// may be written either with member call syntax (e.g., "obj.func()" /// or "objptr->func()") or with normal function-call syntax /// ("func()") within a member function that ends up calling a member @@ -122,18 +123,19 @@ public: CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) : CallExpr(C, CXXMemberCallExprClass, Empty) { } - /// getImplicitObjectArgument - Retrieves the implicit object - /// argument for the member call. For example, in "x.f(5)", this - /// operation would return "x". + /// \brief Retrieves the implicit object argument for the member call. + /// + /// For example, in "x.f(5)", this returns the sub-expression "x". Expr *getImplicitObjectArgument() const; - /// Retrieves the declaration of the called method. + /// \brief Retrieves the declaration of the called method. CXXMethodDecl *getMethodDecl() const; - /// getRecordDecl - Retrieves the CXXRecordDecl for the underlying type of - /// the implicit object argument. Note that this is may not be the same - /// declaration as that of the class context of the CXXMethodDecl which this - /// function is calling. + /// \brief Retrieves the CXXRecordDecl for the underlying type of + /// the implicit object argument. + /// + /// Note that this is may not be the same declaration as that of the class + /// context of the CXXMethodDecl which this function is calling. /// FIXME: Returns 0 for member pointer call exprs. CXXRecordDecl *getRecordDecl() const; @@ -142,7 +144,7 @@ public: } }; -/// CUDAKernelCallExpr - Represents a call to a CUDA kernel function. +/// \brief Represents a call to a CUDA kernel function. class CUDAKernelCallExpr : public CallExpr { private: enum { CONFIG, END_PREARG }; @@ -169,13 +171,12 @@ public: } }; -/// CXXNamedCastExpr - Abstract class common to all of the C++ "named" -/// casts, @c static_cast, @c dynamic_cast, @c reinterpret_cast, or @c -/// const_cast. +/// \brief Abstract class common to all of the C++ "named"/"keyword" casts. /// /// This abstract class is inherited by all of the classes -/// representing "named" casts, e.g., CXXStaticCastExpr, -/// CXXDynamicCastExpr, CXXReinterpretCastExpr, and CXXConstCastExpr. +/// representing "named" casts: CXXStaticCastExpr for \c static_cast, +/// CXXDynamicCastExpr for \c dynamic_cast, CXXReinterpretCastExpr for +/// reinterpret_cast, and CXXConstCastExpr for \c const_cast. class CXXNamedCastExpr : public ExplicitCastExpr { private: SourceLocation Loc; // the location of the casting op @@ -200,7 +201,7 @@ public: const char *getCastName() const; /// \brief Retrieve the location of the cast operator keyword, e.g., - /// "static_cast". + /// \c static_cast. SourceLocation getOperatorLoc() const { return Loc; } /// \brief Retrieve the location of the closing parenthesis. @@ -223,11 +224,10 @@ public: } }; -/// CXXStaticCastExpr - A C++ @c static_cast expression -/// (C++ [expr.static.cast]). +/// \brief A C++ \c static_cast expression (C++ [expr.static.cast]). /// /// This expression node represents a C++ static cast, e.g., -/// @c static_cast(1.0). +/// \c static_cast(1.0). class CXXStaticCastExpr : public CXXNamedCastExpr { CXXStaticCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, @@ -240,13 +240,13 @@ class CXXStaticCastExpr : public CXXNamedCastExpr { : CXXNamedCastExpr(CXXStaticCastExprClass, Empty, PathSize) { } public: - static CXXStaticCastExpr *Create(ASTContext &Context, QualType T, + static CXXStaticCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind K, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets); - static CXXStaticCastExpr *CreateEmpty(ASTContext &Context, + static CXXStaticCastExpr *CreateEmpty(const ASTContext &Context, unsigned PathSize); static bool classof(const Stmt *T) { @@ -254,12 +254,11 @@ public: } }; -/// CXXDynamicCastExpr - A C++ @c dynamic_cast expression -/// (C++ [expr.dynamic.cast]), which may perform a run-time check to -/// determine how to perform the type cast. +/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). /// /// This expression node represents a dynamic cast, e.g., -/// @c dynamic_cast(BasePtr). +/// \c dynamic_cast(BasePtr). Such a cast may perform a run-time +/// check to determine how to perform the type conversion. class CXXDynamicCastExpr : public CXXNamedCastExpr { CXXDynamicCastExpr(QualType ty, ExprValueKind VK, CastKind kind, Expr *op, unsigned pathSize, TypeSourceInfo *writtenTy, @@ -272,14 +271,14 @@ class CXXDynamicCastExpr : public CXXNamedCastExpr { : CXXNamedCastExpr(CXXDynamicCastExprClass, Empty, pathSize) { } public: - static CXXDynamicCastExpr *Create(ASTContext &Context, QualType T, + static CXXDynamicCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *Written, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets); - static CXXDynamicCastExpr *CreateEmpty(ASTContext &Context, + static CXXDynamicCastExpr *CreateEmpty(const ASTContext &Context, unsigned pathSize); bool isAlwaysNull() const; @@ -289,12 +288,14 @@ public: } }; -/// CXXReinterpretCastExpr - A C++ @c reinterpret_cast expression (C++ -/// [expr.reinterpret.cast]), which provides a differently-typed view -/// of a value but performs no actual work at run time. +/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). /// /// This expression node represents a reinterpret cast, e.g., /// @c reinterpret_cast(VoidPtr). +/// +/// A reinterpret_cast provides a differently-typed view of a value but +/// (in Clang, as in most C++ implementations) performs no actual work at +/// run time. class CXXReinterpretCastExpr : public CXXNamedCastExpr { CXXReinterpretCastExpr(QualType ty, ExprValueKind vk, CastKind kind, Expr *op, unsigned pathSize, @@ -308,13 +309,13 @@ class CXXReinterpretCastExpr : public CXXNamedCastExpr { : CXXNamedCastExpr(CXXReinterpretCastExprClass, Empty, pathSize) { } public: - static CXXReinterpretCastExpr *Create(ASTContext &Context, QualType T, + static CXXReinterpretCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, CastKind Kind, Expr *Op, const CXXCastPath *Path, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets); - static CXXReinterpretCastExpr *CreateEmpty(ASTContext &Context, + static CXXReinterpretCastExpr *CreateEmpty(const ASTContext &Context, unsigned pathSize); static bool classof(const Stmt *T) { @@ -322,11 +323,13 @@ public: } }; -/// CXXConstCastExpr - A C++ @c const_cast expression (C++ [expr.const.cast]), -/// which can remove type qualifiers but does not change the underlying value. +/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]). /// /// This expression node represents a const cast, e.g., -/// @c const_cast(PtrToConstChar). +/// \c const_cast(PtrToConstChar). +/// +/// A const_cast can remove type qualifiers but does not change the underlying +/// value. class CXXConstCastExpr : public CXXNamedCastExpr { CXXConstCastExpr(QualType ty, ExprValueKind VK, Expr *op, TypeSourceInfo *writtenTy, SourceLocation l, @@ -338,19 +341,19 @@ class CXXConstCastExpr : public CXXNamedCastExpr { : CXXNamedCastExpr(CXXConstCastExprClass, Empty, 0) { } public: - static CXXConstCastExpr *Create(ASTContext &Context, QualType T, + static CXXConstCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, Expr *Op, TypeSourceInfo *WrittenTy, SourceLocation L, SourceLocation RParenLoc, SourceRange AngleBrackets); - static CXXConstCastExpr *CreateEmpty(ASTContext &Context); + static CXXConstCastExpr *CreateEmpty(const ASTContext &Context); static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstCastExprClass; } }; -/// UserDefinedLiteral - A call to a literal operator (C++11 [over.literal]) +/// \brief A call to a literal operator (C++11 [over.literal]) /// written as a user-defined literal (C++11 [lit.ext]). /// /// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this @@ -364,12 +367,12 @@ class UserDefinedLiteral : public CallExpr { SourceLocation UDSuffixLoc; public: - UserDefinedLiteral(ASTContext &C, Expr *Fn, ArrayRef Args, + UserDefinedLiteral(const ASTContext &C, Expr *Fn, ArrayRef Args, QualType T, ExprValueKind VK, SourceLocation LitEndLoc, SourceLocation SuffixLoc) : CallExpr(C, UserDefinedLiteralClass, Fn, 0, Args, T, VK, LitEndLoc), UDSuffixLoc(SuffixLoc) {} - explicit UserDefinedLiteral(ASTContext &C, EmptyShell Empty) + explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty) : CallExpr(C, UserDefinedLiteralClass, Empty) {} /// The kind of literal operator which is invoked. @@ -382,11 +385,11 @@ public: LOK_Character ///< operator "" X (CharT) }; - /// getLiteralOperatorKind - Returns the kind of literal operator invocation + /// \brief Returns the kind of literal operator invocation /// which this expression represents. LiteralOperatorKind getLiteralOperatorKind() const; - /// getCookedLiteral - If this is not a raw user-defined literal, get the + /// \brief If this is not a raw user-defined literal, get the /// underlying cooked literal (representing the literal with the suffix /// removed). Expr *getCookedLiteral(); @@ -402,12 +405,13 @@ public: SourceLocation getLocEnd() const { return getRParenLoc(); } - /// getUDSuffixLoc - Returns the location of a ud-suffix in the expression. + /// \brief Returns the location of a ud-suffix in the expression. + /// /// For a string literal, there may be multiple identical suffixes. This /// returns the first. SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; } - /// getUDSuffix - Returns the ud-suffix specified for this literal. + /// \brief Returns the ud-suffix specified for this literal. const IdentifierInfo *getUDSuffix() const; static bool classof(const Stmt *S) { @@ -418,7 +422,7 @@ public: friend class ASTStmtWriter; }; -/// CXXBoolLiteralExpr - [C++ 2.13.5] C++ Boolean Literal. +/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals). /// class CXXBoolLiteralExpr : public Expr { bool Value; @@ -449,7 +453,9 @@ public: child_range children() { return child_range(); } }; -/// CXXNullPtrLiteralExpr - [C++0x 2.14.7] C++ Pointer Literal +/// \brief The null pointer literal (C++11 [lex.nullptr]) +/// +/// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. class CXXNullPtrLiteralExpr : public Expr { SourceLocation Loc; public: @@ -474,11 +480,50 @@ public: child_range children() { return child_range(); } }; -/// CXXTypeidExpr - A C++ @c typeid expression (C++ [expr.typeid]), which gets -/// the type_info that corresponds to the supplied type, or the (possibly +/// \brief Implicit construction of a std::initializer_list object from an +/// array temporary within list-initialization (C++11 [dcl.init.list]p5). +class CXXStdInitializerListExpr : public Expr { + Stmt *SubExpr; + + CXXStdInitializerListExpr(EmptyShell Empty) + : Expr(CXXStdInitializerListExprClass, Empty), SubExpr(0) {} + +public: + CXXStdInitializerListExpr(QualType Ty, Expr *SubExpr) + : Expr(CXXStdInitializerListExprClass, Ty, VK_RValue, OK_Ordinary, + Ty->isDependentType(), SubExpr->isValueDependent(), + SubExpr->isInstantiationDependent(), + SubExpr->containsUnexpandedParameterPack()), + SubExpr(SubExpr) {} + + Expr *getSubExpr() { return static_cast(SubExpr); } + const Expr *getSubExpr() const { return static_cast(SubExpr); } + + SourceLocation getLocStart() const LLVM_READONLY { + return SubExpr->getLocStart(); + } + SourceLocation getLocEnd() const LLVM_READONLY { + return SubExpr->getLocEnd(); + } + SourceRange getSourceRange() const LLVM_READONLY { + return SubExpr->getSourceRange(); + } + + static bool classof(const Stmt *S) { + return S->getStmtClass() == CXXStdInitializerListExprClass; + } + + child_range children() { return child_range(&SubExpr, &SubExpr + 1); } + + friend class ASTReader; + friend class ASTStmtReader; +}; + +/// A C++ \c typeid expression (C++ [expr.typeid]), which gets +/// the \c type_info that corresponds to the supplied type, or the (possibly /// dynamic) type of the supplied expression. /// -/// This represents code like @c typeid(int) or @c typeid(*objPtr) +/// This represents code like \c typeid(int) or \c typeid(*objPtr) class CXXTypeidExpr : public Expr { private: llvm::PointerUnion Operand; @@ -521,7 +566,7 @@ public: /// \brief Retrieves the type operand of this typeid() expression after /// various required adjustments (removing reference types, cv-qualifiers). - QualType getTypeOperand() const; + QualType getTypeOperand(ASTContext &Context) const; /// \brief Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { @@ -561,10 +606,11 @@ public: } }; -/// A member reference to an MSPropertyDecl. This expression always -/// has pseudo-object type, and therefore it is typically not -/// encountered in a fully-typechecked expression except within the -/// syntactic form of a PseudoObjectExpr. +/// \brief A member reference to an MSPropertyDecl. +/// +/// This expression always has pseudo-object type, and therefore it is +/// typically not encountered in a fully-typechecked expression except +/// within the syntactic form of a PseudoObjectExpr. class MSPropertyRefExpr : public Expr { Expr *BaseExpr; MSPropertyDecl *TheDecl; @@ -619,7 +665,7 @@ public: friend class ASTStmtReader; }; -/// CXXUuidofExpr - A microsoft C++ @c __uuidof expression, which gets +/// A Microsoft C++ @c __uuidof expression, which gets /// the _GUID that corresponds to the supplied type or expression. /// /// This represents code like @c __uuidof(COMTYPE) or @c __uuidof(*comPtr) @@ -655,7 +701,7 @@ public: /// \brief Retrieves the type operand of this __uuidof() expression after /// various required adjustments (removing reference types, cv-qualifiers). - QualType getTypeOperand() const; + QualType getTypeOperand(ASTContext &Context) const; /// \brief Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { @@ -678,6 +724,8 @@ public: Operand = E; } + StringRef getUuidAsStringRef(ASTContext &Context) const; + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } @@ -687,8 +735,10 @@ public: return T->getStmtClass() == CXXUuidofExprClass; } - /// Grabs __declspec(uuid()) off a type, or returns 0 if there is none. - static UuidAttr *GetUuidAttrOfType(QualType QT); + /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to + /// a single GUID. + static UuidAttr *GetUuidAttrOfType(QualType QT, + bool *HasMultipleGUIDsPtr = 0); // Iterators child_range children() { @@ -698,17 +748,18 @@ public: } }; -/// CXXThisExpr - Represents the "this" expression in C++, which is a -/// pointer to the object on which the current member function is +/// \brief Represents the \c this expression in C++. +/// +/// This is a pointer to the object on which the current member function is /// executing (C++ [expr.prim]p3). Example: /// -/// @code +/// \code /// class Foo { /// public: /// void bar(); /// void test() { this->bar(); } /// }; -/// @endcode +/// \endcode class CXXThisExpr : public Expr { SourceLocation Loc; bool Implicit : 1; @@ -742,10 +793,11 @@ public: child_range children() { return child_range(); } }; -/// CXXThrowExpr - [C++ 15] C++ Throw Expression. This handles -/// 'throw' and 'throw' assignment-expression. When -/// assignment-expression isn't present, Op will be null. +/// \brief A C++ throw-expression (C++ [except.throw]). /// +/// This handles 'throw' (for re-throwing the current exception) and +/// 'throw' assignment-expression. When assignment-expression isn't +/// present, Op will be null. class CXXThrowExpr : public Expr { Stmt *Op; SourceLocation ThrowLoc; @@ -755,8 +807,8 @@ class CXXThrowExpr : public Expr { friend class ASTStmtReader; public: - // Ty is the void type which is used as the result type of the - // exepression. The l is the location of the throw keyword. expr + // \p Ty is the void type which is used as the result type of the + // expression. The \p l is the location of the throw keyword. \p expr // can by null, if the optional expression to throw isn't present. CXXThrowExpr(Expr *expr, QualType Ty, SourceLocation l, bool IsThrownVariableInScope) : @@ -795,10 +847,11 @@ public: } }; -/// CXXDefaultArgExpr - C++ [dcl.fct.default]. This wraps up a -/// function call argument that was created from the corresponding -/// parameter's default argument, when the call did not explicitly -/// supply arguments for all of the parameters. +/// \brief A default argument (C++ [dcl.fct.default]). +/// +/// This wraps up a function call argument that was created from the +/// corresponding parameter's default argument, when the call did not +/// explicitly supply arguments for all of the parameters. class CXXDefaultArgExpr : public Expr { /// \brief The parameter whose default is being used. /// @@ -831,20 +884,17 @@ class CXXDefaultArgExpr : public Expr { public: CXXDefaultArgExpr(EmptyShell Empty) : Expr(CXXDefaultArgExprClass, Empty) {} - - // Param is the parameter whose default argument is used by this + // \p Param is the parameter whose default argument is used by this // expression. - static CXXDefaultArgExpr *Create(ASTContext &C, SourceLocation Loc, + static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, ParmVarDecl *Param) { return new (C) CXXDefaultArgExpr(CXXDefaultArgExprClass, Loc, Param); } - // Param is the parameter whose default argument is used by this - // expression, and SubExpr is the expression that will actually be used. - static CXXDefaultArgExpr *Create(ASTContext &C, - SourceLocation Loc, - ParmVarDecl *Param, - Expr *SubExpr); + // \p Param is the parameter whose default argument is used by this + // expression, and \p SubExpr is the expression that will actually be used. + static CXXDefaultArgExpr *Create(const ASTContext &C, SourceLocation Loc, + ParmVarDecl *Param, Expr *SubExpr); // Retrieve the parameter that the argument was created from. const ParmVarDecl *getParam() const { return Param.getPointer(); } @@ -866,8 +916,8 @@ public: /// used. SourceLocation getUsedLocation() const { return Loc; } - // Default argument expressions have no representation in the - // source, so they have an empty source range. + /// Default argument expressions have no representation in the + /// source, so they have an empty source range. SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } @@ -884,7 +934,10 @@ public: friend class ASTStmtWriter; }; -/// \brief This wraps a use of a C++ default initializer (technically, +/// \brief A use of a default initializer in a constructor or in aggregate +/// initialization. +/// +/// This wraps a use of a C++ default initializer (technically, /// a brace-or-equal-initializer for a non-static data member) when it /// is implicitly used in a mem-initializer-list in a constructor /// (C++11 [class.base.init]p8) or in aggregate initialization @@ -896,24 +949,24 @@ class CXXDefaultInitExpr : public Expr { /// \brief The location where the default initializer expression was used. SourceLocation Loc; - CXXDefaultInitExpr(ASTContext &C, SourceLocation Loc, FieldDecl *Field, + CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, QualType T); CXXDefaultInitExpr(EmptyShell Empty) : Expr(CXXDefaultInitExprClass, Empty) {} public: - // Field is the non-static data member whose default initializer is used - // by this expression. - static CXXDefaultInitExpr *Create(ASTContext &C, SourceLocation Loc, + /// \p Field is the non-static data member whose default initializer is used + /// by this expression. + static CXXDefaultInitExpr *Create(const ASTContext &C, SourceLocation Loc, FieldDecl *Field) { return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType()); } - // Get the field whose initializer will be used. + /// \brief Get the field whose initializer will be used. FieldDecl *getField() { return Field; } const FieldDecl *getField() const { return Field; } - // Get the initialization expression that will be used. + /// \brief Get the initialization expression that will be used. const Expr *getExpr() const { return Field->getInClassInitializer(); } Expr *getExpr() { return Field->getInClassInitializer(); } @@ -931,16 +984,16 @@ public: friend class ASTStmtReader; }; -/// CXXTemporary - Represents a C++ temporary. +/// \brief Represents a C++ temporary. class CXXTemporary { - /// Destructor - The destructor that needs to be called. + /// \brief The destructor that needs to be called. const CXXDestructorDecl *Destructor; - CXXTemporary(const CXXDestructorDecl *destructor) + explicit CXXTemporary(const CXXDestructorDecl *destructor) : Destructor(destructor) { } public: - static CXXTemporary *Create(ASTContext &C, + static CXXTemporary *Create(const ASTContext &C, const CXXDestructorDecl *Destructor); const CXXDestructorDecl *getDestructor() const { return Destructor; } @@ -980,7 +1033,7 @@ public: CXXBindTemporaryExpr(EmptyShell Empty) : Expr(CXXBindTemporaryExprClass, Empty), Temp(0), SubExpr(0) {} - static CXXBindTemporaryExpr *Create(ASTContext &C, CXXTemporary *Temp, + static CXXBindTemporaryExpr *Create(const ASTContext &C, CXXTemporary *Temp, Expr* SubExpr); CXXTemporary *getTemporary() { return Temp; } @@ -1019,7 +1072,7 @@ private: CXXConstructorDecl *Constructor; SourceLocation Loc; - SourceRange ParenRange; + SourceRange ParenOrBraceRange; unsigned NumArgs : 16; bool Elidable : 1; bool HadMultipleCandidates : 1; @@ -1029,7 +1082,7 @@ private: Stmt **Args; protected: - CXXConstructExpr(ASTContext &C, StmtClass SC, QualType T, + CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, CXXConstructorDecl *d, bool elidable, ArrayRef Args, @@ -1037,7 +1090,7 @@ protected: bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, - SourceRange ParenRange); + SourceRange ParenOrBraceRange); /// \brief Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) @@ -1055,7 +1108,7 @@ public: ConstructKind(0), Args(0) { } - static CXXConstructExpr *Create(ASTContext &C, QualType T, + static CXXConstructExpr *Create(const ASTContext &C, QualType T, SourceLocation Loc, CXXConstructorDecl *D, bool Elidable, ArrayRef Args, @@ -1063,7 +1116,7 @@ public: bool ListInitialization, bool ZeroInitialization, ConstructionKind ConstructKind, - SourceRange ParenRange); + SourceRange ParenOrBraceRange); CXXConstructorDecl* getConstructor() const { return Constructor; } void setConstructor(CXXConstructorDecl *C) { Constructor = C; } @@ -1091,7 +1144,7 @@ public: ZeroInitialization = ZeroInit; } - /// \brief Determines whether this constructor is actually constructing + /// \brief Determine whether this constructor is actually constructing /// a base class (rather than a complete object). ConstructionKind getConstructionKind() const { return (ConstructionKind)ConstructKind; @@ -1111,7 +1164,7 @@ public: Expr **getArgs() const { return reinterpret_cast(Args); } unsigned getNumArgs() const { return NumArgs; } - /// getArg - Return the specified argument. + /// \brief Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); return cast(Args[Arg]); @@ -1121,7 +1174,7 @@ public: return cast(Args[Arg]); } - /// setArg - Set the specified argument. + /// \brief Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); Args[Arg] = ArgExpr; @@ -1129,8 +1182,8 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; - SourceRange getParenRange() const { return ParenRange; } - void setParenRange(SourceRange Range) { ParenRange = Range; } + SourceRange getParenOrBraceRange() const { return ParenOrBraceRange; } + void setParenOrBraceRange(SourceRange Range) { ParenOrBraceRange = Range; } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXConstructExprClass || @@ -1149,43 +1202,42 @@ public: /// notation (C++ [expr.type.conv]). /// /// Example: -/// @code +/// \code /// x = int(0.5); -/// @endcode +/// \endcode class CXXFunctionalCastExpr : public ExplicitCastExpr { - SourceLocation TyBeginLoc; + SourceLocation LParenLoc; SourceLocation RParenLoc; CXXFunctionalCastExpr(QualType ty, ExprValueKind VK, TypeSourceInfo *writtenTy, - SourceLocation tyBeginLoc, CastKind kind, - Expr *castExpr, unsigned pathSize, - SourceLocation rParenLoc) + CastKind kind, Expr *castExpr, unsigned pathSize, + SourceLocation lParenLoc, SourceLocation rParenLoc) : ExplicitCastExpr(CXXFunctionalCastExprClass, ty, VK, kind, castExpr, pathSize, writtenTy), - TyBeginLoc(tyBeginLoc), RParenLoc(rParenLoc) {} + LParenLoc(lParenLoc), RParenLoc(rParenLoc) {} explicit CXXFunctionalCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CXXFunctionalCastExprClass, Shell, PathSize) { } public: - static CXXFunctionalCastExpr *Create(ASTContext &Context, QualType T, + static CXXFunctionalCastExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, TypeSourceInfo *Written, - SourceLocation TyBeginLoc, CastKind Kind, Expr *Op, const CXXCastPath *Path, + SourceLocation LPLoc, SourceLocation RPLoc); - static CXXFunctionalCastExpr *CreateEmpty(ASTContext &Context, + static CXXFunctionalCastExpr *CreateEmpty(const ASTContext &Context, unsigned PathSize); - SourceLocation getTypeBeginLoc() const { return TyBeginLoc; } - void setTypeBeginLoc(SourceLocation L) { TyBeginLoc = L; } + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } - SourceLocation getLocStart() const LLVM_READONLY { return TyBeginLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getLocStart() const LLVM_READONLY; + SourceLocation getLocEnd() const LLVM_READONLY; static bool classof(const Stmt *T) { return T->getStmtClass() == CXXFunctionalCastExprClass; @@ -1200,21 +1252,21 @@ public: /// constructor to build a temporary object. With N == 1 arguments the /// functional cast expression will be represented by CXXFunctionalCastExpr. /// Example: -/// @code +/// \code /// struct X { X(int, float); } /// /// X create_X() { /// return X(1, 3.14f); // creates a CXXTemporaryObjectExpr /// }; -/// @endcode +/// \endcode class CXXTemporaryObjectExpr : public CXXConstructExpr { TypeSourceInfo *Type; public: - CXXTemporaryObjectExpr(ASTContext &C, CXXConstructorDecl *Cons, + CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, TypeSourceInfo *Type, ArrayRef Args, - SourceRange parenRange, + SourceRange ParenOrBraceRange, bool HadMultipleCandidates, bool ListInitialization, bool ZeroInitialization); @@ -1244,26 +1296,35 @@ public: /// } /// \endcode /// -/// Lambda expressions can capture local variables, either by copying +/// C++11 lambda expressions can capture local variables, either by copying /// the values of those local variables at the time the function /// object is constructed (not when it is called!) or by holding a /// reference to the local variable. These captures can occur either /// implicitly or can be written explicitly between the square /// brackets ([...]) that start the lambda expression. +/// +/// C++1y introduces a new form of "capture" called an init-capture that +/// includes an initializing expression (rather than capturing a variable), +/// and which can never occur implicitly. class LambdaExpr : public Expr { enum { /// \brief Flag used by the Capture class to indicate that the given /// capture was implicit. Capture_Implicit = 0x01, - /// \brief Flag used by the Capture class to indciate that the + /// \brief Flag used by the Capture class to indicate that the /// given capture was by-copy. + /// + /// This includes the case of a non-reference init-capture. Capture_ByCopy = 0x02 }; /// \brief The source range that covers the lambda introducer ([...]). SourceRange IntroducerRange; + /// \brief The source location of this lambda's capture-default ('=' or '&'). + SourceLocation CaptureDefaultLoc; + /// \brief The number of captures. unsigned NumCaptures : 16; @@ -1297,9 +1358,10 @@ class LambdaExpr : public Expr { // array captures. public: - /// \brief Describes the capture of either a variable or 'this'. + /// \brief Describes the capture of a variable or of \c this, or of a + /// C++1y init-capture. class Capture { - llvm::PointerIntPair VarAndBits; + llvm::PointerIntPair DeclAndBits; SourceLocation Loc; SourceLocation EllipsisLoc; @@ -1307,15 +1369,17 @@ public: friend class ASTStmtWriter; public: - /// \brief Create a new capture. + /// \brief Create a new capture of a variable or of \c this. /// /// \param Loc The source location associated with this capture. /// - /// \param Kind The kind of capture (this, byref, bycopy). + /// \param Kind The kind of capture (this, byref, bycopy), which must + /// not be init-capture. /// /// \param Implicit Whether the capture was implicit or explicit. /// - /// \param Var The local variable being captured, or null if capturing this. + /// \param Var The local variable being captured, or null if capturing + /// \c this. /// /// \param EllipsisLoc The location of the ellipsis (...) for a /// capture that is a pack expansion, or an invalid source @@ -1327,36 +1391,43 @@ public: /// \brief Determine the kind of capture. LambdaCaptureKind getCaptureKind() const; - /// \brief Determine whether this capture handles the C++ 'this' + /// \brief Determine whether this capture handles the C++ \c this /// pointer. - bool capturesThis() const { return VarAndBits.getPointer() == 0; } + bool capturesThis() const { return DeclAndBits.getPointer() == 0; } /// \brief Determine whether this capture handles a variable. - bool capturesVariable() const { return VarAndBits.getPointer() != 0; } + bool capturesVariable() const { + return dyn_cast_or_null(DeclAndBits.getPointer()); + } + + /// \brief Determine whether this is an init-capture. + bool isInitCapture() const { + return capturesVariable() && getCapturedVar()->isInitCapture(); + } /// \brief Retrieve the declaration of the local variable being /// captured. /// - /// This operation is only valid if this capture does not capture - /// 'this'. - VarDecl *getCapturedVar() const { - assert(!capturesThis() && "No variable available for 'this' capture"); - return VarAndBits.getPointer(); + /// This operation is only valid if this capture is a variable capture + /// (other than a capture of \c this). + VarDecl *getCapturedVar() const { + assert(capturesVariable() && "No variable available for 'this' capture"); + return cast(DeclAndBits.getPointer()); } /// \brief Determine whether this was an implicit capture (not /// written between the square brackets introducing the lambda). - bool isImplicit() const { return VarAndBits.getInt() & Capture_Implicit; } + bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; } - /// \brief Determine whether this was an explicit capture, written - /// between the square brackets introducing the lambda. + /// \brief Determine whether this was an explicit capture (written + /// between the square brackets introducing the lambda). bool isExplicit() const { return !isImplicit(); } /// \brief Retrieve the source location of the capture. /// /// For an explicit capture, this returns the location of the /// explicit capture in the source. For an implicit capture, this - /// returns the location at which the variable or 'this' was first + /// returns the location at which the variable or \c this was first /// used. SourceLocation getLocation() const { return Loc; } @@ -1376,6 +1447,7 @@ private: /// \brief Construct a lambda expression. LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, ArrayRef Captures, bool ExplicitParams, bool ExplicitResultType, @@ -1414,10 +1486,11 @@ private: public: /// \brief Construct a new lambda expression. - static LambdaExpr *Create(ASTContext &C, + static LambdaExpr *Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, + SourceLocation CaptureDefaultLoc, ArrayRef Captures, bool ExplicitParams, bool ExplicitResultType, @@ -1429,14 +1502,20 @@ public: /// \brief Construct a new lambda expression that will be deserialized from /// an external source. - static LambdaExpr *CreateDeserialized(ASTContext &C, unsigned NumCaptures, + static LambdaExpr *CreateDeserialized(const ASTContext &C, + unsigned NumCaptures, unsigned NumArrayIndexVars); - + /// \brief Determine the default capture kind for this lambda. LambdaCaptureDefault getCaptureDefault() const { return static_cast(CaptureDefault); } + /// \brief Retrieve the location of this lambda's capture-default, if any. + SourceLocation getCaptureDefaultLoc() const { + return CaptureDefaultLoc; + } + /// \brief An iterator that walks over the captures of the lambda, /// both implicit and explicit. typedef const Capture *capture_iterator; @@ -1495,15 +1574,24 @@ public: /// brackets ([...]). SourceRange getIntroducerRange() const { return IntroducerRange; } - /// \brief Retrieve the class that corresponds to the lambda, which - /// stores the captures in its fields and provides the various - /// operations permitted on a lambda (copying, calling). + /// \brief Retrieve the class that corresponds to the lambda. + /// + /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the + /// captures in its fields and provides the various operations permitted + /// on a lambda (copying, calling). CXXRecordDecl *getLambdaClass() const; /// \brief Retrieve the function call operator associated with this /// lambda expression. CXXMethodDecl *getCallOperator() const; + /// \brief If this is a generic lambda expression, retrieve the template + /// parameter list associated with it, or else return null. + TemplateParameterList *getTemplateParameterList() const; + + /// \brief Whether this is a generic lambda. + bool isGenericLambda() const { return getTemplateParameterList(); } + /// \brief Retrieve the body of the lambda. CompoundStmt *getBody() const; @@ -1535,10 +1623,8 @@ public: friend class ASTStmtWriter; }; -/// CXXScalarValueInitExpr - [C++ 5.2.3p2] -/// Expression "T()" which creates a value-initialized rvalue of type -/// T, which is a non-class type. -/// +/// An expression "T()" which creates a value-initialized rvalue of type +/// T, which is a non-class type. See (C++98 [5.2.3p2]). class CXXScalarValueInitExpr : public Expr { SourceLocation RParenLoc; TypeSourceInfo *TypeInfo; @@ -1575,11 +1661,11 @@ public: child_range children() { return child_range(); } }; -/// @brief Represents a new-expression for memory allocation and constructor -// calls, e.g: "new CXXNewExpr(foo)". +/// \brief Represents a new-expression for memory allocation and constructor +/// calls, e.g: "new CXXNewExpr(foo)". class CXXNewExpr : public Expr { - // Contains an optional array size expression, an optional initialization - // expression, and any number of optional placement arguments, in that order. + /// Contains an optional array size expression, an optional initialization + /// expression, and any number of optional placement arguments, in that order. Stmt **SubExprs; /// \brief Points to the allocation function used. FunctionDecl *OperatorNew; @@ -1600,18 +1686,18 @@ class CXXNewExpr : public Expr { /// \brief Source-range of a paren-delimited initializer. SourceRange DirectInitRange; - // Was the usage ::new, i.e. is the global new to be used? + /// Was the usage ::new, i.e. is the global new to be used? bool GlobalNew : 1; - // Do we allocate an array? If so, the first SubExpr is the size expression. + /// Do we allocate an array? If so, the first SubExpr is the size expression. bool Array : 1; - // If this is an array allocation, does the usual deallocation - // function for the allocated type want to know the allocated size? + /// If this is an array allocation, does the usual deallocation + /// function for the allocated type want to know the allocated size? bool UsualArrayDeleteWantsSize : 1; - // The number of placement new arguments. + /// The number of placement new arguments. unsigned NumPlacementArgs : 13; - // What kind of initializer do we have? Could be none, parens, or braces. - // In storage, we distinguish between "none, and no initializer expr", and - // "none, but an implicit initializer expr". + /// What kind of initializer do we have? Could be none, parens, or braces. + /// In storage, we distinguish between "none, and no initializer expr", and + /// "none, but an implicit initializer expr". unsigned StoredInitializationStyle : 2; friend class ASTStmtReader; @@ -1623,7 +1709,7 @@ public: ListInit ///< New-expression has a C++11 list-initializer. }; - CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew, + CXXNewExpr(const ASTContext &C, bool globalNew, FunctionDecl *operatorNew, FunctionDecl *operatorDelete, bool usualArrayDeleteWantsSize, ArrayRef placementArgs, SourceRange typeIdParens, Expr *arraySize, @@ -1633,8 +1719,8 @@ public: explicit CXXNewExpr(EmptyShell Shell) : Expr(CXXNewExprClass, Shell), SubExprs(0) { } - void AllocateArgsArray(ASTContext &C, bool isArray, unsigned numPlaceArgs, - bool hasInitializer); + void AllocateArgsArray(const ASTContext &C, bool isArray, + unsigned numPlaceArgs, bool hasInitializer); QualType getAllocatedType() const { assert(getType()->isPointerType()); @@ -1646,15 +1732,17 @@ public: } /// \brief True if the allocation result needs to be null-checked. - /// C++0x [expr.new]p13: + /// + /// C++11 [expr.new]p13: /// If the allocation function returns null, initialization shall /// not be done, the deallocation function shall not be called, /// and the value of the new-expression shall be null. + /// /// An allocation function is not allowed to return null unless it /// has a non-throwing exception-specification. The '03 rule is /// identical except that the definition of a non-throwing /// exception specification is just "is it throw()?". - bool shouldNullCheckAllocation(ASTContext &Ctx) const; + bool shouldNullCheckAllocation(const ASTContext &Ctx) const; FunctionDecl *getOperatorNew() const { return OperatorNew; } void setOperatorNew(FunctionDecl *D) { OperatorNew = D; } @@ -1706,7 +1794,7 @@ public: return hasInitializer() ? cast(SubExprs[Array]) : 0; } - /// \brief Returns the CXXConstructExpr from this new-expression, or NULL. + /// \brief Returns the CXXConstructExpr from this new-expression, or null. const CXXConstructExpr* getConstructExpr() const { return dyn_cast_or_null(getInitializer()); } @@ -1768,22 +1856,22 @@ public: /// \brief Represents a \c delete expression for memory deallocation and /// destructor calls, e.g. "delete[] pArray". class CXXDeleteExpr : public Expr { - // Points to the operator delete overload that is used. Could be a member. + /// Points to the operator delete overload that is used. Could be a member. FunctionDecl *OperatorDelete; - // The pointer expression to be deleted. + /// The pointer expression to be deleted. Stmt *Argument; - // Location of the expression. + /// Location of the expression. SourceLocation Loc; - // Is this a forced global delete, i.e. "::delete"? + /// Is this a forced global delete, i.e. "::delete"? bool GlobalDelete : 1; - // Is this the array form of delete, i.e. "delete[]"? + /// Is this the array form of delete, i.e. "delete[]"? bool ArrayForm : 1; - // ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied - // to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm - // will be true). + /// ArrayFormAsWritten can be different from ArrayForm if 'delete' is applied + /// to pointer-to-array type (ArrayFormAsWritten will be false while ArrayForm + /// will be true). bool ArrayFormAsWritten : 1; - // Does the usual deallocation function for the element type require - // a size_t argument? + /// Does the usual deallocation function for the element type require + /// a size_t argument? bool UsualArrayDeleteWantsSize : 1; public: CXXDeleteExpr(QualType ty, bool globalDelete, bool arrayForm, @@ -1816,9 +1904,10 @@ public: Expr *getArgument() { return cast(Argument); } const Expr *getArgument() const { return cast(Argument); } - /// \brief Retrieve the type being destroyed. If the type being - /// destroyed is a dependent type which may or may not be a pointer, - /// return an invalid type. + /// \brief Retrieve the type being destroyed. + /// + /// If the type being destroyed is a dependent type which may or may not + /// be a pointer, return an invalid type. QualType getDestroyedType() const; SourceLocation getLocStart() const LLVM_READONLY { return Loc; } @@ -1918,7 +2007,7 @@ class CXXPseudoDestructorExpr : public Expr { friend class ASTStmtReader; public: - CXXPseudoDestructorExpr(ASTContext &Context, + CXXPseudoDestructorExpr(const ASTContext &Context, Expr *Base, bool isArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, TypeSourceInfo *ScopeType, @@ -1935,7 +2024,7 @@ public: /// \brief Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. - bool hasQualifier() const { return QualifierLoc; } + bool hasQualifier() const { return QualifierLoc.hasQualifier(); } /// \brief Retrieves the nested-name-specifier that qualifies the type name, /// with source-location information. @@ -1943,7 +2032,7 @@ public: /// \brief If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns - /// NULL. + /// null. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -1978,7 +2067,7 @@ public: /// /// This type-source information is available for non-dependent /// pseudo-destructor expressions and some dependent pseudo-destructor - /// expressions. Returns NULL if we only have the identifier for a + /// expressions. Returns null if we only have the identifier for a /// dependent pseudo-destructor expression. TypeSourceInfo *getDestroyedTypeInfo() const { return DestroyedType.getTypeSourceInfo(); @@ -2025,23 +2114,23 @@ public: /// implementation of TR1/C++11 type trait templates. /// /// Example: -/// @code +/// \code /// __is_pod(int) == true /// __is_enum(std::string) == false -/// @endcode +/// \endcode class UnaryTypeTraitExpr : public Expr { - /// UTT - The trait. A UnaryTypeTrait enum in MSVC compat unsigned. + /// \brief The trait. A UnaryTypeTrait enum in MSVC compatible unsigned. unsigned UTT : 31; /// The value of the type trait. Unspecified if dependent. bool Value : 1; - /// Loc - The location of the type trait keyword. + /// \brief The location of the type trait keyword. SourceLocation Loc; - /// RParen - The location of the closing paren. + /// \brief The location of the closing paren. SourceLocation RParen; - /// The type being queried. + /// \brief The type being queried. TypeSourceInfo *QueriedType; public: @@ -2083,26 +2172,26 @@ public: /// implementation of TR1/C++11 type trait templates. /// /// Example: -/// @code +/// \code /// __is_base_of(Base, Derived) == true -/// @endcode +/// \endcode class BinaryTypeTraitExpr : public Expr { - /// BTT - The trait. A BinaryTypeTrait enum in MSVC compat unsigned. + /// \brief The trait. A BinaryTypeTrait enum in MSVC compatible unsigned. unsigned BTT : 8; /// The value of the type trait. Unspecified if dependent. bool Value : 1; - /// Loc - The location of the type trait keyword. + /// \brief The location of the type trait keyword. SourceLocation Loc; - /// RParen - The location of the closing paren. + /// \brief The location of the closing paren. SourceLocation RParen; - /// The lhs type being queried. + /// \brief The lhs type being queried. TypeSourceInfo *LhsType; - /// The rhs type being queried. + /// \brief The rhs type being queried. TypeSourceInfo *RhsType; public: @@ -2184,13 +2273,14 @@ class TypeTraitExpr : public Expr { public: /// \brief Create a new type trait expression. - static TypeTraitExpr *Create(ASTContext &C, QualType T, SourceLocation Loc, - TypeTrait Kind, + static TypeTraitExpr *Create(const ASTContext &C, QualType T, + SourceLocation Loc, TypeTrait Kind, ArrayRef Args, SourceLocation RParenLoc, bool Value); - static TypeTraitExpr *CreateDeserialized(ASTContext &C, unsigned NumArgs); + static TypeTraitExpr *CreateDeserialized(const ASTContext &C, + unsigned NumArgs); /// \brief Determine which type trait this expression uses. TypeTrait getTrait() const { @@ -2249,10 +2339,10 @@ public: /// __array_rank and __array_extent. /// /// Example: -/// @code +/// \code /// __array_rank(int[10][20]) == 2 /// __array_extent(int, 1) == 20 -/// @endcode +/// \endcode class ArrayTypeTraitExpr : public Expr { virtual void anchor(); @@ -2319,12 +2409,12 @@ public: /// \brief An expression trait intrinsic. /// /// Example: -/// @code +/// \code /// __is_lvalue_expr(std::cout) == true /// __is_lvalue_expr(1) == false -/// @endcode +/// \endcode class ExpressionTraitExpr : public Expr { - /// \brief The trait. A ExpressionTrait enum in MSVC compat unsigned. + /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned. unsigned ET : 31; /// \brief The value of the type trait. Unspecified if dependent. bool Value : 1; @@ -2403,7 +2493,7 @@ protected: return const_cast(this)->getTemplateKWAndArgsInfo(); } - OverloadExpr(StmtClass K, ASTContext &C, + OverloadExpr(StmtClass K, const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, @@ -2417,7 +2507,7 @@ protected: : Expr(K, Empty), QualifierLoc(), Results(0), NumResults(0), HasTemplateKWAndArgsInfo(false) { } - void initializeResults(ASTContext &C, + void initializeResults(const ASTContext &C, UnresolvedSetIterator Begin, UnresolvedSetIterator End); @@ -2428,7 +2518,7 @@ public: bool HasFormOfMemberPointer; }; - /// Finds the overloaded expression in the given expression of + /// \brief Finds the overloaded expression in the given expression \p E of /// OverloadTy. /// /// \return the expression (which must be there) and true if it has @@ -2561,10 +2651,11 @@ public: /// parsing but could not resolve to a specific declaration. /// /// This arises in several ways: -/// * we might be waiting for argument-dependent lookup -/// * the name might resolve to an overloaded function +/// * we might be waiting for argument-dependent lookup; +/// * the name might resolve to an overloaded function; /// and eventually: -/// * the lookup might have included a function template +/// * the lookup might have included a function template. +/// /// These never include UnresolvedUsingValueDecls, which are always class /// members and therefore appear only in UnresolvedMemberLookupExprs. class UnresolvedLookupExpr : public OverloadExpr { @@ -2584,7 +2675,7 @@ class UnresolvedLookupExpr : public OverloadExpr { /// against the qualified-lookup bits. CXXRecordDecl *NamingClass; - UnresolvedLookupExpr(ASTContext &C, + UnresolvedLookupExpr(const ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -2606,7 +2697,7 @@ class UnresolvedLookupExpr : public OverloadExpr { friend class ASTStmtReader; public: - static UnresolvedLookupExpr *Create(ASTContext &C, + static UnresolvedLookupExpr *Create(const ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, @@ -2618,7 +2709,7 @@ public: ADL, Overloaded, 0, Begin, End); } - static UnresolvedLookupExpr *Create(ASTContext &C, + static UnresolvedLookupExpr *Create(const ASTContext &C, CXXRecordDecl *NamingClass, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, @@ -2628,7 +2719,7 @@ public: UnresolvedSetIterator Begin, UnresolvedSetIterator End); - static UnresolvedLookupExpr *CreateEmpty(ASTContext &C, + static UnresolvedLookupExpr *CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); @@ -2671,7 +2762,7 @@ public: /// DependentScopeDeclRefExpr node is used only within C++ templates when /// the qualification (e.g., X::) refers to a dependent type. In /// this case, X::value cannot resolve to a declaration because the -/// declaration will differ from on instantiation of X to the +/// declaration will differ from one instantiation of X to the /// next. Therefore, DependentScopeDeclRefExpr keeps track of the /// qualifier (X::) and the name of the entity being referenced /// ("value"). Such expressions will instantiate to a DeclRefExpr once the @@ -2681,7 +2772,7 @@ class DependentScopeDeclRefExpr : public Expr { /// declaration name. NestedNameSpecifierLoc QualifierLoc; - /// The name of the entity we will be referencing. + /// \brief The name of the entity we will be referencing. DeclarationNameInfo NameInfo; /// \brief Whether the name includes info for explicit template @@ -2706,13 +2797,13 @@ class DependentScopeDeclRefExpr : public Expr { const TemplateArgumentListInfo *Args); public: - static DependentScopeDeclRefExpr *Create(ASTContext &C, + static DependentScopeDeclRefExpr *Create(const ASTContext &C, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, const DeclarationNameInfo &NameInfo, const TemplateArgumentListInfo *TemplateArgs); - static DependentScopeDeclRefExpr *CreateEmpty(ASTContext &C, + static DependentScopeDeclRefExpr *CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); @@ -2723,13 +2814,14 @@ public: DeclarationName getDeclName() const { return NameInfo.getName(); } /// \brief Retrieve the location of the name within the expression. + /// + /// For example, in "X::value" this is the location of "value". SourceLocation getLocation() const { return NameInfo.getLoc(); } /// \brief Retrieve the nested-name-specifier that qualifies the /// name, with source location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies this /// declaration. NestedNameSpecifier *getQualifier() const { @@ -2779,6 +2871,7 @@ public: } /// \brief Retrieves the optional explicit template arguments. + /// /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { @@ -2800,6 +2893,8 @@ public: return getExplicitTemplateArgs().NumTemplateArgs; } + /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr, + /// and differs from getLocation().getStart(). SourceLocation getLocStart() const LLVM_READONLY { return QualifierLoc.getBeginLoc(); } @@ -2819,7 +2914,7 @@ public: friend class ASTStmtWriter; }; -/// Represents an expression --- generally a full-expression --- which +/// Represents an expression -- generally a full-expression -- that /// introduces cleanups to be run at the end of the sub-expression's /// evaluation. The most common source of expression-introduced /// cleanups is temporary objects in C++, but several other kinds of @@ -2852,10 +2947,10 @@ private: friend class ASTStmtReader; public: - static ExprWithCleanups *Create(ASTContext &C, EmptyShell empty, + static ExprWithCleanups *Create(const ASTContext &C, EmptyShell empty, unsigned numObjects); - static ExprWithCleanups *Create(ASTContext &C, Expr *subexpr, + static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr, ArrayRef objects); ArrayRef getObjects() const { @@ -2872,7 +2967,7 @@ public: Expr *getSubExpr() { return cast(SubExpr); } const Expr *getSubExpr() const { return cast(SubExpr); } - /// setSubExpr - As with any mutator of the AST, be very careful + /// As with any mutator of the AST, be very careful /// when modifying an existing AST to preserve its invariants. void setSubExpr(Expr *E) { SubExpr = E; } @@ -2935,13 +3030,13 @@ class CXXUnresolvedConstructExpr : public Expr { friend class ASTStmtReader; public: - static CXXUnresolvedConstructExpr *Create(ASTContext &C, + static CXXUnresolvedConstructExpr *Create(const ASTContext &C, TypeSourceInfo *Type, SourceLocation LParenLoc, ArrayRef Args, SourceLocation RParenLoc); - static CXXUnresolvedConstructExpr *CreateEmpty(ASTContext &C, + static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C, unsigned NumArgs); /// \brief Retrieve the type that is being constructed, as specified @@ -2993,7 +3088,10 @@ public: } SourceLocation getLocStart() const LLVM_READONLY; - SourceLocation getLocEnd() const LLVM_READONLY { return RParenLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { + assert(RParenLoc.isValid() || NumArgs == 1); + return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd(); + } static bool classof(const Stmt *T) { return T->getStmtClass() == CXXUnresolvedConstructExprClass; @@ -3047,6 +3145,7 @@ class CXXDependentScopeMemberExpr : public Expr { /// \brief The member to which this member expression refers, which /// can be name, overloaded operator, or destructor. + /// /// FIXME: could also be a template-id DeclarationNameInfo MemberNameInfo; @@ -3061,36 +3160,32 @@ class CXXDependentScopeMemberExpr : public Expr { ->getTemplateKWAndArgsInfo(); } - CXXDependentScopeMemberExpr(ASTContext &C, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierFoundInScope, - DeclarationNameInfo MemberNameInfo, - const TemplateArgumentListInfo *TemplateArgs); + CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, + QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, + NamedDecl *FirstQualifierFoundInScope, + DeclarationNameInfo MemberNameInfo, + const TemplateArgumentListInfo *TemplateArgs); public: - CXXDependentScopeMemberExpr(ASTContext &C, - Expr *Base, QualType BaseType, - bool IsArrow, + CXXDependentScopeMemberExpr(const ASTContext &C, Expr *Base, + QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo); static CXXDependentScopeMemberExpr * - Create(ASTContext &C, - Expr *Base, QualType BaseType, bool IsArrow, - SourceLocation OperatorLoc, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, - NamedDecl *FirstQualifierFoundInScope, + Create(const ASTContext &C, Expr *Base, QualType BaseType, bool IsArrow, + SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, + SourceLocation TemplateKWLoc, NamedDecl *FirstQualifierFoundInScope, DeclarationNameInfo MemberNameInfo, const TemplateArgumentListInfo *TemplateArgs); static CXXDependentScopeMemberExpr * - CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo, + CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); /// \brief True if this is an implicit access, i.e. one in which the @@ -3197,6 +3292,7 @@ public: } /// \brief Retrieves the optional explicit template arguments. + /// /// This points to the same data as getExplicitTemplateArgs(), but /// returns null if there are no explicit template arguments. const ASTTemplateArgumentListInfo *getOptionalExplicitTemplateArgs() const { @@ -3259,11 +3355,13 @@ public: /// produced a set of overloaded functions. /// /// The member access may be explicit or implicit: +/// \code /// struct A { /// int a, b; /// int explicitAccess() { return this->a + this->A::b; } /// int implicitAccess() { return a + A::b; } /// }; +/// \endcode /// /// In the final AST, an explicit access always becomes a MemberExpr. /// An implicit access may become either a MemberExpr or a @@ -3278,17 +3376,18 @@ class UnresolvedMemberExpr : public OverloadExpr { bool HasUnresolvedUsing : 1; /// \brief The expression for the base pointer or class reference, - /// e.g., the \c x in x.f. This can be null if this is an 'unbased' - /// member expression + /// e.g., the \c x in x.f. + /// + /// This can be null if this is an 'unbased' member expression. Stmt *Base; - /// \brief The type of the base expression; never null. + /// \brief The type of the base expression; never null. QualType BaseType; /// \brief The location of the '->' or '.' operator. SourceLocation OperatorLoc; - UnresolvedMemberExpr(ASTContext &C, bool HasUnresolvedUsing, + UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -3305,7 +3404,7 @@ class UnresolvedMemberExpr : public OverloadExpr { public: static UnresolvedMemberExpr * - Create(ASTContext &C, bool HasUnresolvedUsing, + Create(const ASTContext &C, bool HasUnresolvedUsing, Expr *Base, QualType BaseType, bool IsArrow, SourceLocation OperatorLoc, NestedNameSpecifierLoc QualifierLoc, @@ -3315,12 +3414,13 @@ public: UnresolvedSetIterator Begin, UnresolvedSetIterator End); static UnresolvedMemberExpr * - CreateEmpty(ASTContext &C, bool HasTemplateKWAndArgsInfo, + CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); - /// \brief True if this is an implicit access, i.e. one in which the - /// member being accessed was not written in the source. The source - /// location of the operator is invalid in this case. + /// \brief True if this is an implicit access, i.e., one in which the + /// member being accessed was not written in the source. + /// + /// The source location of the operator is invalid in this case. bool isImplicitAccess() const; /// \brief Retrieve the base object of this member expressions, @@ -3347,7 +3447,7 @@ public: /// \brief Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Retrieves the naming class of this lookup. + /// \brief Retrieve the naming class of this lookup. CXXRecordDecl *getNamingClass() const; /// \brief Retrieve the full name info for the member that this expression @@ -3362,6 +3462,10 @@ public: // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } + // \brief Return the preferred location (the member name) for the arrow when + // diagnosing a problem with this expression. + SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); } + SourceLocation getLocStart() const LLVM_READONLY { if (!isImplicitAccess()) return Base->getLocStart(); @@ -3386,7 +3490,7 @@ public: } }; -/// \brief Represents a C++0x noexcept expression (C++ [expr.unary.noexcept]). +/// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). /// /// The noexcept expression tests whether a given expression might throw. Its /// result is a boolean constant. @@ -3428,7 +3532,7 @@ public: child_range children() { return child_range(&Operand, &Operand + 1); } }; -/// \brief Represents a C++0x pack expansion that produces a sequence of +/// \brief Represents a C++11 pack expansion that produces a sequence of /// expressions. /// /// A pack expansion expression contains a pattern (which itself is an @@ -3527,7 +3631,7 @@ inline ASTTemplateKWAndArgsInfo *OverloadExpr::getTemplateKWAndArgsInfo() { /// }; /// \endcode class SizeOfPackExpr : public Expr { - /// \brief The location of the 'sizeof' keyword. + /// \brief The location of the \c sizeof keyword. SourceLocation OperatorLoc; /// \brief The location of the name of the parameter pack. @@ -3550,7 +3654,7 @@ class SizeOfPackExpr : public Expr { friend class ASTStmtWriter; public: - /// \brief Creates a value-dependent expression that computes the length of + /// \brief Create a value-dependent expression that computes the length of /// the given parameter pack. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc) @@ -3561,7 +3665,7 @@ public: OperatorLoc(OperatorLoc), PackLoc(PackLoc), RParenLoc(RParenLoc), Length(0), Pack(Pack) { } - /// \brief Creates an expression that computes the length of + /// \brief Create an expression that computes the length of /// the given parameter pack, which is already known. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, @@ -3744,11 +3848,11 @@ class FunctionParmPackExpr : public Expr { friend class ASTStmtReader; public: - static FunctionParmPackExpr *Create(ASTContext &Context, QualType T, + static FunctionParmPackExpr *Create(const ASTContext &Context, QualType T, ParmVarDecl *ParamPack, SourceLocation NameLoc, ArrayRef Params); - static FunctionParmPackExpr *CreateEmpty(ASTContext &Context, + static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context, unsigned NumParams); /// \brief Get the parameter pack which this expression refers to. @@ -3779,7 +3883,7 @@ public: child_range children() { return child_range(); } }; -/// \brief Represents a prvalue temporary that written into memory so that +/// \brief Represents a prvalue temporary that is written into memory so that /// a reference can bind to it. /// /// Prvalue expressions are materialized when they need to have an address @@ -3795,30 +3899,60 @@ public: /// binds to the temporary. \c MaterializeTemporaryExprs are always glvalues /// (either an lvalue or an xvalue, depending on the kind of reference binding /// to it), maintaining the invariant that references always bind to glvalues. +/// +/// Reference binding and copy-elision can both extend the lifetime of a +/// temporary. When either happens, the expression will also track the +/// declaration which is responsible for the lifetime extension. class MaterializeTemporaryExpr : public Expr { +public: /// \brief The temporary-generating expression whose value will be /// materialized. Stmt *Temporary; + /// \brief The declaration which lifetime-extended this reference, if any. + /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. + const ValueDecl *ExtendingDecl; + friend class ASTStmtReader; friend class ASTStmtWriter; public: MaterializeTemporaryExpr(QualType T, Expr *Temporary, - bool BoundToLvalueReference) + bool BoundToLvalueReference, + const ValueDecl *ExtendedBy) : Expr(MaterializeTemporaryExprClass, T, BoundToLvalueReference? VK_LValue : VK_XValue, OK_Ordinary, Temporary->isTypeDependent(), Temporary->isValueDependent(), Temporary->isInstantiationDependent(), Temporary->containsUnexpandedParameterPack()), - Temporary(Temporary) { } + Temporary(Temporary), ExtendingDecl(ExtendedBy) { + } MaterializeTemporaryExpr(EmptyShell Empty) : Expr(MaterializeTemporaryExprClass, Empty) { } /// \brief Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. - Expr *GetTemporaryExpr() const { return reinterpret_cast(Temporary); } + Expr *GetTemporaryExpr() const { return static_cast(Temporary); } + + /// \brief Retrieve the storage duration for the materialized temporary. + StorageDuration getStorageDuration() const { + if (!ExtendingDecl) + return SD_FullExpression; + // FIXME: This is not necessarily correct for a temporary materialized + // within a default initializer. + if (isa(ExtendingDecl)) + return SD_Automatic; + return cast(ExtendingDecl)->getStorageDuration(); + } + + /// \brief Get the declaration which triggered the lifetime-extension of this + /// temporary, if any. + const ValueDecl *getExtendingDecl() const { return ExtendingDecl; } + + void setExtendingDecl(const ValueDecl *ExtendedBy) { + ExtendingDecl = ExtendedBy; + } /// \brief Determine whether this materialized temporary is bound to an /// lvalue reference; otherwise, it's bound to an rvalue reference. diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index a94c69a115d6..aeb55da1fb91 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -143,12 +143,13 @@ class ObjCArrayLiteral : public Expr { : Expr(ObjCArrayLiteralClass, Empty), NumElements(NumElements) {} public: - static ObjCArrayLiteral *Create(ASTContext &C, + static ObjCArrayLiteral *Create(const ASTContext &C, ArrayRef Elements, QualType T, ObjCMethodDecl * Method, SourceRange SR); - static ObjCArrayLiteral *CreateEmpty(ASTContext &C, unsigned NumElements); + static ObjCArrayLiteral *CreateEmpty(const ASTContext &C, + unsigned NumElements); SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } @@ -289,13 +290,13 @@ class ObjCDictionaryLiteral : public Expr { } public: - static ObjCDictionaryLiteral *Create(ASTContext &C, + static ObjCDictionaryLiteral *Create(const ASTContext &C, ArrayRef VK, bool HasPackExpansions, QualType T, ObjCMethodDecl *method, SourceRange SR); - static ObjCDictionaryLiteral *CreateEmpty(ASTContext &C, + static ObjCDictionaryLiteral *CreateEmpty(const ASTContext &C, unsigned NumElements, bool HasPackExpansions); @@ -807,7 +808,7 @@ public: explicit ObjCSubscriptRefExpr(EmptyShell Empty) : Expr(ObjCSubscriptRefExprClass, Empty) {} - static ObjCSubscriptRefExpr *Create(ASTContext &C, + static ObjCSubscriptRefExpr *Create(const ASTContext &C, Expr *base, Expr *key, QualType T, ObjCMethodDecl *getMethod, @@ -1003,13 +1004,13 @@ class ObjCMessageExpr : public Expr { return getNumSelectorLocs(); } - static ObjCMessageExpr *alloc(ASTContext &C, + static ObjCMessageExpr *alloc(const ASTContext &C, ArrayRef Args, SourceLocation RBraceLoc, ArrayRef SelLocs, Selector Sel, SelectorLocationsKind &SelLocsK); - static ObjCMessageExpr *alloc(ASTContext &C, + static ObjCMessageExpr *alloc(const ASTContext &C, unsigned NumArgs, unsigned NumStoredSelLocs); @@ -1051,7 +1052,7 @@ public: /// \param Args The message send arguments. /// /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, SourceLocation SuperLoc, @@ -1087,7 +1088,7 @@ public: /// \param Args The message send arguments. /// /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, TypeSourceInfo *Receiver, @@ -1121,7 +1122,7 @@ public: /// \param Args The message send arguments. /// /// \param RBracLoc The location of the closing square bracket ']'. - static ObjCMessageExpr *Create(ASTContext &Context, QualType T, + static ObjCMessageExpr *Create(const ASTContext &Context, QualType T, ExprValueKind VK, SourceLocation LBracLoc, Expr *Receiver, @@ -1139,7 +1140,7 @@ public: /// /// \param NumArgs The number of message arguments, not including /// the receiver. - static ObjCMessageExpr *CreateEmpty(ASTContext &Context, + static ObjCMessageExpr *CreateEmpty(const ASTContext &Context, unsigned NumArgs, unsigned NumStoredSelLocs); diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 81fcf242b65e..b077426e6a47 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -329,7 +329,12 @@ public: /// \brief Whether this pointer is non-NULL. /// /// This operation does not require the AST node to be deserialized. - operator bool() const { return Ptr != 0; } + LLVM_EXPLICIT operator bool() const { return Ptr != 0; } + + /// \brief Whether this pointer is non-NULL. + /// + /// This operation does not require the AST node to be deserialized. + bool isValid() const { return Ptr != 0; } /// \brief Whether this pointer is currently stored as an offset. bool isOffset() const { return Ptr & 0x01; } diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h index c43e44c26f31..54c9d88c9b2e 100644 --- a/include/clang/AST/GlobalDecl.h +++ b/include/clang/AST/GlobalDecl.h @@ -41,6 +41,7 @@ public: GlobalDecl(const VarDecl *D) { Init(D);} GlobalDecl(const FunctionDecl *D) { Init(D); } GlobalDecl(const BlockDecl *D) { Init(D); } + GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) diff --git a/include/clang/AST/LambdaMangleContext.h b/include/clang/AST/LambdaMangleContext.h deleted file mode 100644 index bbaee26494a9..000000000000 --- a/include/clang/AST/LambdaMangleContext.h +++ /dev/null @@ -1,38 +0,0 @@ -//===--- LambdaMangleContext.h - Context for mangling lambdas ---*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This file defines the LambdaMangleContext interface, which keeps track of -// the Itanium C++ ABI mangling numbers for lambda expressions. -// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LAMBDAMANGLECONTEXT_H -#define LLVM_CLANG_LAMBDAMANGLECONTEXT_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" - -namespace clang { - -class CXXMethodDecl; -class FunctionProtoType; - -/// \brief Keeps track of the mangled names of lambda expressions within a -/// particular context. -class LambdaMangleContext : public RefCountedBase { - llvm::DenseMap ManglingNumbers; - -public: - /// \brief Retrieve the mangling number of a new lambda expression with the - /// given call operator within this lambda context. - unsigned getManglingNumber(CXXMethodDecl *CallOperator); -}; - -} // end namespace clang -#endif diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index b6d22cfb5fd7..c4d0d22cdf0a 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" #include "llvm/Support/raw_ostream.h" namespace clang { @@ -64,18 +65,29 @@ private: /// MangleContext - Context for tracking state which persists across multiple /// calls to the C++ name mangler. class MangleContext { +public: + enum ManglerKind { + MK_Itanium, + MK_Microsoft + }; + +private: virtual void anchor(); ASTContext &Context; DiagnosticsEngine &Diags; + const ManglerKind Kind; llvm::DenseMap GlobalBlockIds; llvm::DenseMap LocalBlockIds; - + public: + ManglerKind getKind() const { return Kind; } + explicit MangleContext(ASTContext &Context, - DiagnosticsEngine &Diags) - : Context(Context), Diags(Diags) { } + DiagnosticsEngine &Diags, + ManglerKind Kind) + : Context(Context), Diags(Diags), Kind(Kind) {} virtual ~MangleContext() { } @@ -96,8 +108,12 @@ public: /// @name Mangler Entry Points /// @{ - virtual bool shouldMangleDeclName(const NamedDecl *D) = 0; - virtual void mangleName(const NamedDecl *D, raw_ostream &)=0; + bool shouldMangleDeclName(const NamedDecl *D); + virtual bool shouldMangleCXXName(const NamedDecl *D) = 0; + + // FIXME: consider replacing raw_ostream & with something like SmallString &. + void mangleName(const NamedDecl *D, raw_ostream &); + virtual void mangleCXXName(const NamedDecl *D, raw_ostream &) = 0; virtual void mangleThunk(const CXXMethodDecl *MD, const ThunkInfo &Thunk, raw_ostream &) = 0; @@ -106,13 +122,6 @@ public: raw_ostream &) = 0; virtual void mangleReferenceTemporary(const VarDecl *D, raw_ostream &) = 0; - virtual void mangleCXXVTable(const CXXRecordDecl *RD, - raw_ostream &) = 0; - virtual void mangleCXXVTT(const CXXRecordDecl *RD, - raw_ostream &) = 0; - virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, - const CXXRecordDecl *Type, - raw_ostream &) = 0; virtual void mangleCXXRTTI(QualType T, raw_ostream &) = 0; virtual void mangleCXXRTTIName(QualType T, raw_ostream &) = 0; virtual void mangleCXXCtor(const CXXConstructorDecl *D, CXXCtorType Type, @@ -129,36 +138,78 @@ public: const BlockDecl *BD, raw_ostream &Out); void mangleBlock(const DeclContext *DC, const BlockDecl *BD, raw_ostream &Out); - // Do the right thing. - void mangleBlock(const BlockDecl *BD, raw_ostream &Out, - const NamedDecl *ID=0); - void mangleObjCMethodName(const ObjCMethodDecl *MD, - raw_ostream &); + void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &); - // This is pretty lame. - virtual void mangleItaniumGuardVariable(const VarDecl *D, - raw_ostream &) { - llvm_unreachable("Target does not support mangling guard variables"); - } - // FIXME: Revisit this once we know what we need to do for MSVC compatibility. + virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0; + + virtual void mangleDynamicInitializer(const VarDecl *D, raw_ostream &) = 0; + + virtual void mangleDynamicAtExitDestructor(const VarDecl *D, + raw_ostream &) = 0; + + /// Generates a unique string for an externally visible type for use with TBAA + /// or type uniquing. + /// TODO: Extend this to internal types by generating names that are unique + /// across translation units so it can be used with LTO. + virtual void mangleTypeName(QualType T, raw_ostream &) = 0; + + /// @} +}; + +class ItaniumMangleContext : public MangleContext { +public: + explicit ItaniumMangleContext(ASTContext &C, DiagnosticsEngine &D) + : MangleContext(C, D, MK_Itanium) {} + + virtual void mangleCXXVTable(const CXXRecordDecl *RD, raw_ostream &) = 0; + virtual void mangleCXXVTT(const CXXRecordDecl *RD, raw_ostream &) = 0; + virtual void mangleCXXCtorVTable(const CXXRecordDecl *RD, int64_t Offset, + const CXXRecordDecl *Type, + raw_ostream &) = 0; virtual void mangleItaniumThreadLocalInit(const VarDecl *D, - raw_ostream &) { - llvm_unreachable("Target does not support mangling thread_local variables"); - } + raw_ostream &) = 0; virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, - raw_ostream &) { - llvm_unreachable("Target does not support mangling thread_local variables"); + raw_ostream &) = 0; + + static bool classof(const MangleContext *C) { + return C->getKind() == MK_Itanium; } - /// @} + static ItaniumMangleContext *create(ASTContext &Context, + DiagnosticsEngine &Diags); }; -MangleContext *createItaniumMangleContext(ASTContext &Context, - DiagnosticsEngine &Diags); -MangleContext *createMicrosoftMangleContext(ASTContext &Context, - DiagnosticsEngine &Diags); +class MicrosoftMangleContext : public MangleContext { +public: + explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D) + : MangleContext(C, D, MK_Microsoft) {} + + /// \brief Mangle vftable symbols. Only a subset of the bases along the path + /// to the vftable are included in the name. It's up to the caller to pick + /// them correctly. + virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, + ArrayRef BasePath, + raw_ostream &Out) = 0; + + /// \brief Mangle vbtable symbols. Only a subset of the bases along the path + /// to the vbtable are included in the name. It's up to the caller to pick + /// them correctly. + virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, + ArrayRef BasePath, + raw_ostream &Out) = 0; + + virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, + uint64_t OffsetInVFTable, + raw_ostream &) = 0; + static bool classof(const MangleContext *C) { + return C->getKind() == MK_Microsoft; + } + + static MicrosoftMangleContext *create(ASTContext &Context, + DiagnosticsEngine &Diags); +}; } #endif diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h new file mode 100644 index 000000000000..5a227f201fbb --- /dev/null +++ b/include/clang/AST/MangleNumberingContext.h @@ -0,0 +1,59 @@ +//=== MangleNumberingContext.h - Context for mangling numbers ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the LambdaBlockMangleContext interface, which keeps track +// of the Itanium C++ ABI mangling numbers for lambda expressions and block +// literals. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H +#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" + +namespace clang { + +class BlockDecl; +class CXXMethodDecl; +class IdentifierInfo; +class TagDecl; +class Type; +class VarDecl; + +/// \brief Keeps track of the mangled names of lambda expressions and block +/// literals within a particular context. +class MangleNumberingContext + : public RefCountedBase { + llvm::DenseMap ManglingNumbers; + llvm::DenseMap TagManglingNumbers; + +public: + virtual ~MangleNumberingContext() {} + + /// \brief Retrieve the mangling number of a new lambda expression with the + /// given call operator within this context. + unsigned getManglingNumber(const CXXMethodDecl *CallOperator); + + /// \brief Retrieve the mangling number of a new block literal within this + /// context. + unsigned getManglingNumber(const BlockDecl *BD); + + /// \brief Retrieve the mangling number of a static local variable within + /// this context. + virtual unsigned getManglingNumber(const VarDecl *VD) = 0; + + /// \brief Retrieve the mangling number of a static local variable within + /// this context. + unsigned getManglingNumber(const TagDecl *TD); +}; + +} // end namespace clang +#endif diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index 58f39862b102..b332b153fe8d 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -231,7 +231,11 @@ public: /// \brief Evalutes true when this nested-name-specifier location is /// non-empty. - operator bool() const { return Qualifier; } + LLVM_EXPLICIT operator bool() const { return Qualifier; } + + /// \brief Evalutes true when this nested-name-specifier location is + /// empty. + bool hasQualifier() const { return Qualifier; } /// \brief Retrieve the nested-name-specifier to which this instance /// refers. diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index 62eae02c1525..bd2ebf5dbedb 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -29,6 +29,11 @@ public: /// visited and updated or inserted but not the parents of S. void addStmt(Stmt* S); + /// Manually sets the parent of \p S to \p Parent. + /// + /// If \p S is already in the map, this method will update the mapping. + void setParent(const Stmt *S, const Stmt *Parent); + Stmt *getParent(Stmt*) const; Stmt *getParentIgnoreParens(Stmt *) const; Stmt *getParentIgnoreParenCasts(Stmt *) const; diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index e3c09e7b418f..76426991cf47 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -39,8 +39,9 @@ struct PrintingPolicy { SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), SuppressUnwrittenScope(false), SuppressInitializers(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), - SuppressStrongLifetime(false), Bool(LO.Bool), - TerseOutput(false), PolishForDeclaration(false) { } + SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), + Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), + MSWChar(LO.MicrosoftExt && !LO.WChar) { } /// \brief What language we're printing. LangOptions LangOpts; @@ -131,6 +132,10 @@ struct PrintingPolicy { /// ARC. unsigned SuppressStrongLifetime : 1; + /// \brief When true, suppress printing of lifetime qualifier in + /// ARC. + unsigned SuppressLifetimeQualifiers : 1; + /// \brief Whether we can use 'bool' rather than '_Bool', even if the language /// doesn't actually have 'bool' (because, e.g., it is defined as a macro). unsigned Bool : 1; @@ -146,6 +151,10 @@ struct PrintingPolicy { /// declaration tag; such as, do not print attributes attached to the declaration. /// unsigned PolishForDeclaration : 1; + + /// \brief When true, print the built-in wchar_t type as __wchar_t. For use in + /// Microsoft mode when wchar_t is not available. + unsigned MSWChar : 1; }; } // end namespace clang diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 84a6e96fa01a..a4fcc108eb5d 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -107,12 +107,9 @@ public: return RawText; } - SourceRange getSourceRange() const LLVM_READONLY { - return Range; - } - - unsigned getBeginLine(const SourceManager &SM) const; - unsigned getEndLine(const SourceManager &SM) const; + SourceRange getSourceRange() const LLVM_READONLY { return Range; } + SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } + SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } const char *getBriefText(const ASTContext &Context) const { if (BriefTextValid) @@ -146,11 +143,6 @@ private: /// considered as documentation comments. bool ParseAllComments : 1; - mutable bool BeginLineValid : 1; ///< True if BeginLine is valid - mutable bool EndLineValid : 1; ///< True if EndLine is valid - mutable unsigned BeginLine; ///< Cached line number - mutable unsigned EndLine; ///< Cached line number - /// \brief Constructor for AST deserialization. RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, bool IsAlmostTrailingComment, @@ -158,8 +150,7 @@ private: Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), IsAttached(false), IsTrailingComment(IsTrailingComment), IsAlmostTrailingComment(IsAlmostTrailingComment), - ParseAllComments(ParseAllComments), - BeginLineValid(false), EndLineValid(false) + ParseAllComments(ParseAllComments) { } StringRef getRawTextSlow(const SourceManager &SourceMgr) const; @@ -178,8 +169,7 @@ public: explicit BeforeThanCompare(const SourceManager &SM) : SM(SM) { } bool operator()(const RawComment &LHS, const RawComment &RHS) { - return SM.isBeforeInTranslationUnit(LHS.getSourceRange().getBegin(), - RHS.getSourceRange().getBegin()); + return SM.isBeforeInTranslationUnit(LHS.getLocStart(), RHS.getLocStart()); } bool operator()(const RawComment *LHS, const RawComment *RHS) { @@ -191,8 +181,7 @@ public: /// sorted in order of appearance in the translation unit. class RawCommentList { public: - RawCommentList(SourceManager &SourceMgr) : - SourceMgr(SourceMgr), OnlyWhitespaceSeen(true) { } + RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator); @@ -203,15 +192,9 @@ public: private: SourceManager &SourceMgr; std::vector Comments; - SourceLocation PrevCommentEndLoc; - bool OnlyWhitespaceSeen; void addCommentsToFront(const std::vector &C) { - size_t OldSize = Comments.size(); - Comments.resize(C.size() + OldSize); - std::copy_backward(Comments.begin(), Comments.begin() + OldSize, - Comments.end()); - std::copy(C.begin(), C.end(), Comments.begin()); + Comments.insert(Comments.begin(), C.begin(), C.end()); } friend class ASTReader; diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 36556469eaf8..7268b3a8240c 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -93,10 +93,22 @@ private: /// HasOwnVFPtr - Does this class provide a virtual function table /// (vtable in Itanium, vftbl in Microsoft) that is independent from /// its base classes? - bool HasOwnVFPtr; // TODO: stash this somewhere more efficient + bool HasOwnVFPtr : 1; + + /// HasVFPtr - Does this class have a vftable that could be extended by + /// a derived class. The class may have inherited this pointer from + /// a primary base class. + bool HasExtendableVFPtr : 1; + + /// AlignAfterVBases - Force appropriate alignment after virtual bases are + /// laid out in MS-C++-ABI. + bool AlignAfterVBases : 1; /// PrimaryBase - The primary base info for this record. llvm::PointerIntPair PrimaryBase; + + /// BaseSharingVBPtr - The base we share vbptr with. + const CXXRecordDecl *BaseSharingVBPtr; /// FIXME: This should really use a SmallPtrMap, once we have one in LLVM :) typedef llvm::DenseMap BaseOffsetsMapTy; @@ -122,13 +134,16 @@ private: typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, - bool hasOwnVFPtr, CharUnits vbptroffset, + bool hasOwnVFPtr, bool hasExtendableVFPtr, + CharUnits vbptroffset, CharUnits datasize, const uint64_t *fieldoffsets, unsigned fieldcount, CharUnits nonvirtualsize, CharUnits nonvirtualalign, CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, + const CXXRecordDecl *BaseSharingVBPtr, + bool ForceAlign, const BaseOffsetsMapTy& BaseOffsets, const VBaseOffsetsMapTy& VBaseOffsets); @@ -226,6 +241,37 @@ public: return CXXInfo->HasOwnVFPtr; } + /// hasVFPtr - Does this class have a virtual function table pointer + /// that can be extended by a derived class? This is synonymous with + /// this class having a VFPtr at offset zero. + bool hasExtendableVFPtr() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->HasExtendableVFPtr; + } + + /// hasOwnVBPtr - Does this class provide its own virtual-base + /// table pointer, rather than inheriting one from a primary base + /// class? + /// + /// This implies that the ABI has no primary base class, meaning + /// that it has no base classes that are suitable under the conditions + /// of the ABI. + bool hasOwnVBPtr() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return hasVBPtr() && !CXXInfo->BaseSharingVBPtr; + } + + /// hasVBPtr - Does this class have a virtual function table pointer. + bool hasVBPtr() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return !CXXInfo->VBPtrOffset.isNegative(); + } + + bool getAlignAfterVBases() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->AlignAfterVBases; + } + /// getVBPtrOffset - Get the offset for virtual base table pointer. /// This is only meaningful with the Microsoft ABI. CharUnits getVBPtrOffset() const { @@ -233,6 +279,11 @@ public: return CXXInfo->VBPtrOffset; } + const CXXRecordDecl *getBaseSharingVBPtr() const { + assert(CXXInfo && "Record layout does not have C++ specific info!"); + return CXXInfo->BaseSharingVBPtr; + } + const VBaseOffsetsMapTy &getVBaseOffsetsMap() const { assert(CXXInfo && "Record layout does not have C++ specific info!"); return CXXInfo->VBaseOffsets; diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index b5a4b5e36d7d..d09550f0e2c2 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -27,6 +27,7 @@ #include "clang/AST/Stmt.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" @@ -108,7 +109,7 @@ namespace clang { /// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar /// is Foo's super class) before calling VisitFoo(), the result is /// that the Visit*() methods for a given node are called in the -/// top-down order (e.g. for a node of type NamedDecl, the order will +/// top-down order (e.g. for a node of type NamespaceDecl, the order will /// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()). /// /// This scheme guarantees that all Visit*() calls for the same AST @@ -243,8 +244,16 @@ public: /// \brief Recursively visit a lambda capture. /// /// \returns false if the visitation was terminated early, true otherwise. - bool TraverseLambdaCapture(LambdaExpr::Capture C); - + bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaExpr::Capture *C); + + /// \brief Recursively visit the body of a lambda expression. + /// + /// This provides a hook for visitors that need more context when visiting + /// \c LE->getBody(). + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool TraverseLambdaBody(LambdaExpr *LE); + // ---- Methods on Stmts ---- // Declare Traverse*() for all concrete Stmt classes. @@ -342,7 +351,7 @@ public: // ---- Methods on TypeLocs ---- // FIXME: this currently just calls the matching Type methods - // Declare Traverse*() for all concrete Type classes. + // Declare Traverse*() for all concrete TypeLoc classes. #define ABSTRACT_TYPELOC(CLASS, BASE) #define TYPELOC(CLASS, BASE) \ bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL); @@ -398,8 +407,12 @@ public: private: // These are helper methods used by more than one Traverse* method. bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL); - bool TraverseClassInstantiations(ClassTemplateDecl *D); - bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ; +#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ + bool TraverseTemplateInstantiations(TMPLDECLKIND##TemplateDecl *D); + DEF_TRAVERSE_TMPL_INST(Class) + DEF_TRAVERSE_TMPL_INST(Var) + DEF_TRAVERSE_TMPL_INST(Function) +#undef DEF_TRAVERSE_TMPL_INST bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL, unsigned Count); bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL); @@ -409,6 +422,13 @@ private: bool TraverseDeclContextHelper(DeclContext *DC); bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); + bool TraverseOMPClause(OMPClause *C); +#define OPENMP_CLAUSE(Name, Class) \ + bool Visit##Class(Class *C); +#include "clang/Basic/OpenMPKinds.def" + /// \brief Process clauses with list of variables. + template + void VisitOMPClauseList(T *Node); struct EnqueueJob { Stmt *S; @@ -802,10 +822,20 @@ bool RecursiveASTVisitor::TraverseConstructorInitializer( } template -bool RecursiveASTVisitor::TraverseLambdaCapture(LambdaExpr::Capture C){ +bool RecursiveASTVisitor::TraverseLambdaCapture( + LambdaExpr *LE, const LambdaExpr::Capture *C) { + if (C->isInitCapture()) + TRY_TO(TraverseDecl(C->getCapturedVar())); + return true; +} + +template +bool RecursiveASTVisitor::TraverseLambdaBody(LambdaExpr *LE) { + TRY_TO(TraverseStmt(LE->getBody())); return true; } + // ----------------- Type traversal ----------------- // This macro makes available a variable T, the passed-in type. @@ -844,6 +874,10 @@ DEF_TRAVERSE_TYPE(MemberPointerType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DecayedType, { + TRY_TO(TraverseType(T->getOriginalType())); + }) + DEF_TRAVERSE_TYPE(ConstantArrayType, { TRY_TO(TraverseType(T->getElementType())); }) @@ -1050,6 +1084,10 @@ DEF_TRAVERSE_TYPELOC(MemberPointerType, { TRY_TO(TraverseTypeLoc(TL.getPointeeLoc())); }) +DEF_TRAVERSE_TYPELOC(DecayedType, { + TRY_TO(TraverseTypeLoc(TL.getOriginalLoc())); + }) + template bool RecursiveASTVisitor::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) { // This isn't available for ArrayType, but is for the ArrayTypeLoc. @@ -1420,59 +1458,44 @@ bool RecursiveASTVisitor::TraverseTemplateParameterListHelper( return true; } -// A helper method for traversing the implicit instantiations of a -// class template. -template -bool RecursiveASTVisitor::TraverseClassInstantiations( - ClassTemplateDecl *D) { - ClassTemplateDecl::spec_iterator end = D->spec_end(); - for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) { - ClassTemplateSpecializationDecl* SD = *it; - - switch (SD->getSpecializationKind()) { - // Visit the implicit instantiations with the requested pattern. - case TSK_Undeclared: - case TSK_ImplicitInstantiation: - TRY_TO(TraverseDecl(SD)); - break; - - // We don't need to do anything on an explicit instantiation - // or explicit specialization because there will be an explicit - // node for it elsewhere. - case TSK_ExplicitInstantiationDeclaration: - case TSK_ExplicitInstantiationDefinition: - case TSK_ExplicitSpecialization: - break; - } - } - - return true; +#define DEF_TRAVERSE_TMPL_INST(TMPLDECLKIND) \ +/* A helper method for traversing the implicit instantiations of a + class or variable template. */ \ +template \ +bool RecursiveASTVisitor::TraverseTemplateInstantiations( \ + TMPLDECLKIND##TemplateDecl *D) { \ + TMPLDECLKIND##TemplateDecl::spec_iterator end = D->spec_end(); \ + for (TMPLDECLKIND##TemplateDecl::spec_iterator it = D->spec_begin(); \ + it != end; ++it) { \ + TMPLDECLKIND##TemplateSpecializationDecl* SD = *it; \ + \ + switch (SD->getSpecializationKind()) { \ + /* Visit the implicit instantiations with the requested pattern. */ \ + case TSK_Undeclared: \ + case TSK_ImplicitInstantiation: \ + TRY_TO(TraverseDecl(SD)); \ + break; \ + \ + /* We don't need to do anything on an explicit instantiation + or explicit specialization because there will be an explicit + node for it elsewhere. */ \ + case TSK_ExplicitInstantiationDeclaration: \ + case TSK_ExplicitInstantiationDefinition: \ + case TSK_ExplicitSpecialization: \ + break; \ + } \ + } \ + \ + return true; \ } - -DEF_TRAVERSE_DECL(ClassTemplateDecl, { - CXXRecordDecl* TempDecl = D->getTemplatedDecl(); - TRY_TO(TraverseDecl(TempDecl)); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // class templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the class instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseClassInstantiations(D)); - - // Note that getInstantiatedFromMemberTemplate() is just a link - // from a template instantiation back to the template from which - // it was instantiated, and thus should not be traversed. - }) + +DEF_TRAVERSE_TMPL_INST(Class) +DEF_TRAVERSE_TMPL_INST(Var) // A helper method for traversing the instantiations of a // function while skipping its specializations. template -bool RecursiveASTVisitor::TraverseFunctionInstantiations( +bool RecursiveASTVisitor::TraverseTemplateInstantiations( FunctionTemplateDecl *D) { FunctionTemplateDecl::spec_iterator end = D->spec_end(); for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end; @@ -1500,20 +1523,31 @@ bool RecursiveASTVisitor::TraverseFunctionInstantiations( return true; } -DEF_TRAVERSE_DECL(FunctionTemplateDecl, { - TRY_TO(TraverseDecl(D->getTemplatedDecl())); - TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); - - // By default, we do not traverse the instantiations of - // function templates since they do not appear in the user code. The - // following code optionally traverses them. - // - // We only traverse the function instantiations when we see the canonical - // declaration of the template, to ensure we only visit them once. - if (getDerived().shouldVisitTemplateInstantiations() && - D == D->getCanonicalDecl()) - TRY_TO(TraverseFunctionInstantiations(D)); - }) +// This macro unifies the traversal of class, variable and function +// template declarations. +#define DEF_TRAVERSE_TMPL_DECL(TMPLDECLKIND) \ +DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateDecl, { \ + TRY_TO(TraverseDecl(D->getTemplatedDecl())); \ + TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters())); \ + \ + /* By default, we do not traverse the instantiations of + class templates since they do not appear in the user code. The + following code optionally traverses them. + + We only traverse the class instantiations when we see the canonical + declaration of the template, to ensure we only visit them once. */ \ + if (getDerived().shouldVisitTemplateInstantiations() && \ + D == D->getCanonicalDecl()) \ + TRY_TO(TraverseTemplateInstantiations(D)); \ + \ + /* Note that getInstantiatedFromMemberTemplate() is just a link + from a template instantiation back to the template from which + it was instantiated, and thus should not be traversed. */ \ + }) + +DEF_TRAVERSE_TMPL_DECL(Class) +DEF_TRAVERSE_TMPL_DECL(Var) +DEF_TRAVERSE_TMPL_DECL(Function) DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, { // D is the "T" in something like @@ -1607,26 +1641,30 @@ DEF_TRAVERSE_DECL(CXXRecordDecl, { TRY_TO(TraverseCXXRecordHelper(D)); }) -DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, { - // For implicit instantiations ("set x;"), we don't want to - // recurse at all, since the instatiated class isn't written in - // the source code anywhere. (Note the instatiated *type* -- - // set -- is written, and will still get a callback of - // TemplateSpecializationType). For explicit instantiations - // ("template set;"), we do need a callback, since this - // is the only callback that's made for this instantiation. - // We use getTypeAsWritten() to distinguish. - if (TypeSourceInfo *TSI = D->getTypeAsWritten()) - TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); - - if (!getDerived().shouldVisitTemplateInstantiations() && - D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) - // Returning from here skips traversing the - // declaration context of the ClassTemplateSpecializationDecl - // (embedded in the DEF_TRAVERSE_DECL() macro) - // which contains the instantiated members of the class. - return true; - }) +#define DEF_TRAVERSE_TMPL_SPEC_DECL(TMPLDECLKIND) \ +DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplateSpecializationDecl, { \ + /* For implicit instantiations ("set x;"), we don't want to + recurse at all, since the instatiated template isn't written in + the source code anywhere. (Note the instatiated *type* -- + set -- is written, and will still get a callback of + TemplateSpecializationType). For explicit instantiations + ("template set;"), we do need a callback, since this + is the only callback that's made for this instantiation. + We use getTypeAsWritten() to distinguish. */ \ + if (TypeSourceInfo *TSI = D->getTypeAsWritten()) \ + TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); \ + \ + if (!getDerived().shouldVisitTemplateInstantiations() && \ + D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization) \ + /* Returning from here skips traversing the + declaration context of the *TemplateSpecializationDecl + (embedded in the DEF_TRAVERSE_DECL() macro) + which contains the instantiated members of the template. */ \ + return true; \ + }) + +DEF_TRAVERSE_TMPL_SPEC_DECL(Class) +DEF_TRAVERSE_TMPL_SPEC_DECL(Var) template bool RecursiveASTVisitor::TraverseTemplateArgumentLocsHelper( @@ -1637,25 +1675,30 @@ bool RecursiveASTVisitor::TraverseTemplateArgumentLocsHelper( return true; } -DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, { - // The partial specialization. - if (TemplateParameterList *TPL = D->getTemplateParameters()) { - for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); - } - } - // The args that remains unspecialized. - TRY_TO(TraverseTemplateArgumentLocsHelper( - D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten())); - - // Don't need the ClassTemplatePartialSpecializationHelper, even - // though that's our parent class -- we already visit all the - // template args here. - TRY_TO(TraverseCXXRecordHelper(D)); - - // Instantiations will have been visited with the primary template. - }) +#define DEF_TRAVERSE_TMPL_PART_SPEC_DECL(TMPLDECLKIND, DECLKIND) \ +DEF_TRAVERSE_DECL(TMPLDECLKIND##TemplatePartialSpecializationDecl, { \ + /* The partial specialization. */ \ + if (TemplateParameterList *TPL = D->getTemplateParameters()) { \ + for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end(); \ + I != E; ++I) { \ + TRY_TO(TraverseDecl(*I)); \ + } \ + } \ + /* The args that remains unspecialized. */ \ + TRY_TO(TraverseTemplateArgumentLocsHelper( \ + D->getTemplateArgsAsWritten()->getTemplateArgs(), \ + D->getTemplateArgsAsWritten()->NumTemplateArgs)); \ + \ + /* Don't need the *TemplatePartialSpecializationHelper, even + though that's our parent class -- we already visit all the + template args here. */ \ + TRY_TO(Traverse##DECLKIND##Helper(D)); \ + \ + /* Instantiations will have been visited with the primary template. */ \ + }) + +DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Class, CXXRecord) +DEF_TRAVERSE_TMPL_PART_SPEC_DECL(Var, Var) DEF_TRAVERSE_DECL(EnumConstantDecl, { TRY_TO(TraverseStmt(D->getInitExpr())); @@ -1736,6 +1779,14 @@ bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { // including exception specifications. if (TypeSourceInfo *TSI = D->getTypeSourceInfo()) { TRY_TO(TraverseTypeLoc(TSI->getTypeLoc())); + } else if (getDerived().shouldVisitImplicitCode()) { + // Visit parameter variable declarations of the implicit function + // if the traverser is visiting implicit code. Parameter variable + // declarations do not have valid TypeSourceInfo, so to visit them + // we need to traverse the declarations explicitly. + for (FunctionDecl::param_const_iterator I = D->param_begin(), + E = D->param_end(); I != E; ++I) + TRY_TO(TraverseDecl(*I)); } if (CXXConstructorDecl *Ctor = dyn_cast(D)) { @@ -2117,10 +2168,12 @@ DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, { // Walk only the visible parts of lambda expressions. template bool RecursiveASTVisitor::TraverseLambdaExpr(LambdaExpr *S) { + TRY_TO(WalkUpFromLambdaExpr(S)); + for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(), CEnd = S->explicit_capture_end(); C != CEnd; ++C) { - TRY_TO(TraverseLambdaCapture(*C)); + TRY_TO(TraverseLambdaCapture(S, C)); } if (S->hasExplicitParameters() || S->hasExplicitResultType()) { @@ -2140,7 +2193,7 @@ bool RecursiveASTVisitor::TraverseLambdaExpr(LambdaExpr *S) { } } - TRY_TO(TraverseStmt(S->getBody())); + TRY_TO(TraverseLambdaBody(S)); return true; } @@ -2174,6 +2227,7 @@ DEF_TRAVERSE_STMT(CXXDefaultInitExpr, { }) DEF_TRAVERSE_STMT(CXXDeleteExpr, { }) DEF_TRAVERSE_STMT(ExprWithCleanups, { }) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { }) +DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, { }) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo()) @@ -2211,6 +2265,7 @@ DEF_TRAVERSE_STMT(ParenExpr, { }) DEF_TRAVERSE_STMT(ParenListExpr, { }) DEF_TRAVERSE_STMT(PredefinedExpr, { }) DEF_TRAVERSE_STMT(ShuffleVectorExpr, { }) +DEF_TRAVERSE_STMT(ConvertVectorExpr, { }) DEF_TRAVERSE_STMT(StmtExpr, { }) DEF_TRAVERSE_STMT(UnresolvedLookupExpr, { TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc())); @@ -2269,6 +2324,61 @@ DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { }) // Traverse OpenCL: AsType, Convert. DEF_TRAVERSE_STMT(AsTypeExpr, { }) +// OpenMP directives. +DEF_TRAVERSE_STMT(OMPParallelDirective, { + ArrayRef Clauses = S->clauses(); + for (ArrayRef::iterator I = Clauses.begin(), E = Clauses.end(); + I != E; ++I) + if (!TraverseOMPClause(*I)) return false; +}) + +// OpenMP clauses. +template +bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { + if (!C) return true; + switch (C->getClauseKind()) { +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_##Name: \ + return getDerived().Visit##Class(static_cast(C)); +#include "clang/Basic/OpenMPKinds.def" + default: break; + } + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPDefaultClause(OMPDefaultClause *C) { + return true; +} + +template +template +void RecursiveASTVisitor::VisitOMPClauseList(T *Node) { + for (typename T::varlist_iterator I = Node->varlist_begin(), + E = Node->varlist_end(); + I != E; ++I) + TraverseStmt(*I); +} + +template +bool RecursiveASTVisitor::VisitOMPPrivateClause(OMPPrivateClause *C) { + VisitOMPClauseList(C); + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPFirstprivateClause( + OMPFirstprivateClause *C) { + VisitOMPClauseList(C); + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPSharedClause(OMPSharedClause *C) { + VisitOMPClauseList(C); + return true; +} + // FIXME: look at the following tricky-seeming exprs to see if we // need to recurse on anything. These are ones that have methods // returning decls or qualtypes or nestednamespecifier -- though I'm diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index e3b340a5a1fe..cfe5a90be0d5 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -75,7 +75,7 @@ public: /// \brief Return the first declaration of this declaration or itself if this /// is the only declaration. - decl_type *getFirstDeclaration() { + decl_type *getFirstDecl() { decl_type *D = static_cast(this); while (D->getPreviousDecl()) D = D->getPreviousDecl(); @@ -84,31 +84,29 @@ public: /// \brief Return the first declaration of this declaration or itself if this /// is the only declaration. - const decl_type *getFirstDeclaration() const { + const decl_type *getFirstDecl() const { const decl_type *D = static_cast(this); while (D->getPreviousDecl()) D = D->getPreviousDecl(); return D; } - /// \brief Returns true if this is the first declaration. - bool isFirstDeclaration() const { - return RedeclLink.NextIsLatest(); - } + /// \brief True if this is the first declaration in its redeclaration chain. + bool isFirstDecl() const { return RedeclLink.NextIsLatest(); } /// \brief Returns the most recent (re)declaration of this declaration. decl_type *getMostRecentDecl() { - return getFirstDeclaration()->RedeclLink.getNext(); + return getFirstDecl()->RedeclLink.getNext(); } /// \brief Returns the most recent (re)declaration of this declaration. const decl_type *getMostRecentDecl() const { - return getFirstDeclaration()->RedeclLink.getNext(); + return getFirstDecl()->RedeclLink.getNext(); } /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the /// first and only declaration. - void setPreviousDeclaration(decl_type *PrevDecl); + void setPreviousDecl(decl_type *PrevDecl); /// \brief Iterates through all the redeclarations of the same decl. class redecl_iterator { @@ -134,7 +132,7 @@ public: redecl_iterator& operator++() { assert(Current && "Advancing while iterator has reached end"); // Sanity check to avoid infinite loop on invalid redecl chain. - if (Current->isFirstDeclaration()) { + if (Current->isFirstDecl()) { if (PassedFirst) { assert(0 && "Passed first decl twice, invalid redecl chain!"); Current = 0; @@ -175,6 +173,40 @@ public: friend class ASTDeclWriter; }; +/// \brief Get the primary declaration for a declaration from an AST file. That +/// will be the first-loaded declaration. +Decl *getPrimaryMergedDecl(Decl *D); + +/// \brief Provides common interface for the Decls that cannot be redeclared, +/// but can be merged if the same declaration is brought in from multiple +/// modules. +template +class Mergeable { +public: + Mergeable() {} + + /// \brief Return the first declaration of this declaration or itself if this + /// is the only declaration. + decl_type *getFirstDecl() { + decl_type *D = static_cast(this); + if (!D->isFromASTFile()) + return D; + return cast(getPrimaryMergedDecl(const_cast(D))); + } + + /// \brief Return the first declaration of this declaration or itself if this + /// is the only declaration. + const decl_type *getFirstDecl() const { + const decl_type *D = static_cast(this); + if (!D->isFromASTFile()) + return D; + return cast(getPrimaryMergedDecl(const_cast(D))); + } + + /// \brief Returns true if this is the first declaration. + bool isFirstDecl() const { return getFirstDecl() == this; } +}; + } #endif diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index 74c9ec205363..ace53d83b3cf 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -266,10 +266,6 @@ protected: /// Whether this initializer list originally had a GNU array-range /// designator in it. This is a temporary marker used by CodeGen. unsigned HadArrayRangeDesignator : 1; - - /// Whether this initializer list initializes a std::initializer_list - /// object. - unsigned InitializesStdInitializerList : 1; }; class TypeTraitExprBitfields { @@ -289,7 +285,7 @@ protected: /// \brief The number of arguments to this type trait. unsigned NumArgs : 32 - 8 - 1 - NumExprBits; }; - + union { // FIXME: this is wasteful on 64-bit platforms. void *Aligner; @@ -316,19 +312,21 @@ protected: public: // Only allow allocation of Stmts using the allocator in ASTContext // or by doing a placement new. - void* operator new(size_t bytes, ASTContext& C, - unsigned alignment = 8) throw(); + void* operator new(size_t bytes, const ASTContext& C, + unsigned alignment = 8); - void* operator new(size_t bytes, ASTContext* C, - unsigned alignment = 8) throw(); + void* operator new(size_t bytes, const ASTContext* C, + unsigned alignment = 8) { + return operator new(bytes, *C, alignment); + } void* operator new(size_t bytes, void* mem) throw() { return mem; } - void operator delete(void*, ASTContext&, unsigned) throw() { } - void operator delete(void*, ASTContext*, unsigned) throw() { } - void operator delete(void*, std::size_t) throw() { } + void operator delete(void*, const ASTContext&, unsigned) throw() { } + void operator delete(void*, const ASTContext*, unsigned) throw() { } + void operator delete(void*, size_t) throw() { } void operator delete(void*, void*) throw() { } public: @@ -382,7 +380,7 @@ public: /// dumpPretty/printPretty - These two methods do a "pretty print" of the AST /// back to its original source language syntax. - void dumpPretty(ASTContext &Context) const; + void dumpPretty(const ASTContext &Context) const; void printPretty(raw_ostream &OS, PrinterHelper *Helper, const PrintingPolicy &Policy, unsigned Indentation = 0) const; @@ -401,13 +399,6 @@ public: const_cast(this)->stripLabelLikeStatements()); } - /// hasImplicitControlFlow - Some statements (e.g. short circuited operations) - /// contain implicit control-flow in the order their subexpressions - /// are evaluated. This predicate returns true if this statement has - /// such implicit control-flow. Such statements are also specially handled - /// within CFGs. - bool hasImplicitControlFlow() const; - /// Child Iterators: All subclasses must implement 'children' /// to permit easy iteration over the substatements/subexpessions of an /// AST node. This permits easy iteration over all nodes in the AST. @@ -553,10 +544,10 @@ class CompoundStmt : public Stmt { Stmt** Body; SourceLocation LBracLoc, RBracLoc; public: - CompoundStmt(ASTContext &C, ArrayRef Stmts, + CompoundStmt(const ASTContext &C, ArrayRef Stmts, SourceLocation LB, SourceLocation RB); - // \brief Build an empty compound statment with a location. + // \brief Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) : Stmt(CompoundStmtClass), Body(0), LBracLoc(Loc), RBracLoc(Loc) { CompoundStmtBits.NumStmts = 0; @@ -568,7 +559,7 @@ public: CompoundStmtBits.NumStmts = 0; } - void setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts); + void setStmts(const ASTContext &C, Stmt **Stmts, unsigned NumStmts); bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } unsigned size() const { return CompoundStmtBits.NumStmts; } @@ -827,10 +818,10 @@ class AttributedStmt : public Stmt { } public: - static AttributedStmt *Create(ASTContext &C, SourceLocation Loc, + static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, ArrayRef Attrs, Stmt *SubStmt); // \brief Build an empty attributed statement. - static AttributedStmt *CreateEmpty(ASTContext &C, unsigned NumAttrs); + static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs); SourceLocation getAttrLoc() const { return AttrLoc; } ArrayRef getAttrs() const { @@ -860,7 +851,7 @@ class IfStmt : public Stmt { SourceLocation ElseLoc; public: - IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = 0); /// \brief Build an empty if/then/else statement @@ -875,7 +866,7 @@ public: /// } /// \endcode VarDecl *getConditionVariable() const; - void setConditionVariable(ASTContext &C, VarDecl *V); + void setConditionVariable(const ASTContext &C, VarDecl *V); /// If this IfStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. @@ -933,7 +924,7 @@ class SwitchStmt : public Stmt { unsigned AllEnumCasesCovered : 1; public: - SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond); + SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond); /// \brief Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } @@ -948,7 +939,7 @@ public: /// } /// \endcode VarDecl *getConditionVariable() const; - void setConditionVariable(ASTContext &C, VarDecl *V); + void setConditionVariable(const ASTContext &C, VarDecl *V); /// If this SwitchStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. @@ -967,9 +958,6 @@ public: SwitchCase *getSwitchCaseList() { return FirstCase; } /// \brief Set the case list for this switch statement. - /// - /// The caller is responsible for incrementing the retain counts on - /// all of the SwitchCase statements in this list. void setSwitchCaseList(SwitchCase *SC) { FirstCase = SC; } SourceLocation getSwitchLoc() const { return SwitchLoc; } @@ -1021,7 +1009,7 @@ class WhileStmt : public Stmt { Stmt* SubExprs[END_EXPR]; SourceLocation WhileLoc; public: - WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, + WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL); /// \brief Build an empty while statement. @@ -1036,7 +1024,7 @@ public: /// } /// \endcode VarDecl *getConditionVariable() const; - void setConditionVariable(ASTContext &C, VarDecl *V); + void setConditionVariable(const ASTContext &C, VarDecl *V); /// If this WhileStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. @@ -1129,8 +1117,9 @@ class ForStmt : public Stmt { SourceLocation LParenLoc, RParenLoc; public: - ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, Expr *Inc, - Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP); + ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, + Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, + SourceLocation RP); /// \brief Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) { } @@ -1146,7 +1135,7 @@ public: /// } /// \endcode VarDecl *getConditionVariable() const; - void setConditionVariable(ASTContext &C, VarDecl *V); + void setConditionVariable(const ASTContext &C, VarDecl *V); /// If this ForStmt has a condition variable, return the faux DeclStmt /// associated with the creation of that condition variable. @@ -1417,7 +1406,7 @@ public: //===--- Asm String Analysis ---===// /// Assemble final IR asm string. - std::string generateAsmString(ASTContext &C) const; + std::string generateAsmString(const ASTContext &C) const; //===--- Output operands ---===// @@ -1520,7 +1509,7 @@ class GCCAsmStmt : public AsmStmt { friend class ASTStmtReader; public: - GCCAsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, + GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, bool issimple, bool isvolatile, unsigned numoutputs, unsigned numinputs, IdentifierInfo **names, StringLiteral **constraints, Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, @@ -1586,10 +1575,10 @@ public: /// translation of strings from GCC syntax to LLVM IR syntax, and handles //// flattening of named references like %[foo] to Operand AsmStringPiece's. unsigned AnalyzeAsmString(SmallVectorImpl &Pieces, - ASTContext &C, unsigned &DiagOffs) const; + const ASTContext &C, unsigned &DiagOffs) const; /// Assemble final IR asm string. - std::string generateAsmString(ASTContext &C) const; + std::string generateAsmString(const ASTContext &C) const; //===--- Output operands ---===// @@ -1649,7 +1638,7 @@ public: } private: - void setOutputsAndInputsAndClobbers(ASTContext &C, + void setOutputsAndInputsAndClobbers(const ASTContext &C, IdentifierInfo **Names, StringLiteral **Constraints, Stmt **Exprs, @@ -1695,9 +1684,9 @@ class MSAsmStmt : public AsmStmt { friend class ASTStmtReader; public: - MSAsmStmt(ASTContext &C, SourceLocation asmloc, SourceLocation lbraceloc, - bool issimple, bool isvolatile, ArrayRef asmtoks, - unsigned numoutputs, unsigned numinputs, + MSAsmStmt(const ASTContext &C, SourceLocation asmloc, + SourceLocation lbraceloc, bool issimple, bool isvolatile, + ArrayRef asmtoks, unsigned numoutputs, unsigned numinputs, ArrayRef constraints, ArrayRef exprs, StringRef asmstr, ArrayRef clobbers, SourceLocation endloc); @@ -1720,7 +1709,7 @@ public: StringRef getAsmString() const { return AsmStr; } /// Assemble final IR asm string. - std::string generateAsmString(ASTContext &C) const; + std::string generateAsmString(const ASTContext &C) const; //===--- Output operands ---===// @@ -1765,12 +1754,9 @@ public: StringRef getClobber(unsigned i) const { return getClobbers()[i]; } private: - void initialize(ASTContext &C, - StringRef AsmString, - ArrayRef AsmToks, - ArrayRef Constraints, - ArrayRef Exprs, - ArrayRef Clobbers); + void initialize(const ASTContext &C, StringRef AsmString, + ArrayRef AsmToks, ArrayRef Constraints, + ArrayRef Exprs, ArrayRef Clobbers); public: SourceLocation getLocStart() const LLVM_READONLY { return AsmLoc; } @@ -1800,7 +1786,7 @@ class SEHExceptStmt : public Stmt { explicit SEHExceptStmt(EmptyShell E) : Stmt(SEHExceptStmtClass, E) { } public: - static SEHExceptStmt* Create(ASTContext &C, + static SEHExceptStmt* Create(const ASTContext &C, SourceLocation ExceptLoc, Expr *FilterExpr, Stmt *Block); @@ -1841,7 +1827,7 @@ class SEHFinallyStmt : public Stmt { explicit SEHFinallyStmt(EmptyShell E) : Stmt(SEHFinallyStmtClass, E) { } public: - static SEHFinallyStmt* Create(ASTContext &C, + static SEHFinallyStmt* Create(const ASTContext &C, SourceLocation FinallyLoc, Stmt *Block); @@ -1880,10 +1866,8 @@ class SEHTryStmt : public Stmt { explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } public: - static SEHTryStmt* Create(ASTContext &C, - bool isCXXTry, - SourceLocation TryLoc, - Stmt *TryBlock, + static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, + SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler); SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } @@ -2006,13 +1990,13 @@ private: void setCapturedStmt(Stmt *S) { getStoredStmts()[NumCaptures] = S; } public: - static CapturedStmt *Create(ASTContext &Context, Stmt *S, + static CapturedStmt *Create(const ASTContext &Context, Stmt *S, CapturedRegionKind Kind, ArrayRef Captures, ArrayRef CaptureInits, CapturedDecl *CD, RecordDecl *RD); - static CapturedStmt *CreateDeserialized(ASTContext &Context, + static CapturedStmt *CreateDeserialized(const ASTContext &Context, unsigned NumCaptures); /// \brief Retrieve the statement being captured. diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 0112befb293f..df98d41ad5fb 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -79,10 +79,10 @@ class CXXTryStmt : public Stmt { } public: - static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, + static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, Stmt *tryBlock, ArrayRef handlers); - static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, + static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, unsigned numHandlers); SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index b933ed076260..fbc8e5d4ea71 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_AST_STMT_ITR_H #include "llvm/Support/DataTypes.h" +#include "llvm/Support/Compiler.h" #include #include #include @@ -28,18 +29,14 @@ class VariableArrayType; class StmtIteratorBase { protected: - enum { DeclMode = 0x1, SizeOfTypeVAMode = 0x2, DeclGroupMode = 0x3, + enum { StmtMode = 0x0, SizeOfTypeVAMode = 0x1, DeclGroupMode = 0x2, Flags = 0x3 }; Stmt **stmt; - union { Decl *decl; Decl **DGI; }; + Decl **DGI; uintptr_t RawVAPtr; Decl **DGE; - bool inDecl() const { - return (RawVAPtr & Flags) == DeclMode; - } - bool inDeclGroup() const { return (RawVAPtr & Flags) == DeclGroupMode; } @@ -49,7 +46,7 @@ protected: } bool inStmt() const { - return (RawVAPtr & Flags) == 0; + return (RawVAPtr & Flags) == StmtMode; } const VariableArrayType *getVAPtr() const { @@ -57,7 +54,7 @@ protected: } void setVAPtr(const VariableArrayType *P) { - assert (inDecl() || inDeclGroup() || inSizeOfTypeVA()); + assert (inDeclGroup() || inSizeOfTypeVA()); RawVAPtr = reinterpret_cast(P) | (RawVAPtr & Flags); } @@ -67,11 +64,10 @@ protected: Stmt*& GetDeclExpr() const; - StmtIteratorBase(Stmt **s) : stmt(s), decl(0), RawVAPtr(0) {} - StmtIteratorBase(Decl *d, Stmt **s); + StmtIteratorBase(Stmt **s) : stmt(s), DGI(0), RawVAPtr(0) {} StmtIteratorBase(const VariableArrayType *t); StmtIteratorBase(Decl **dgi, Decl **dge); - StmtIteratorBase() : stmt(0), decl(0), RawVAPtr(0) {} + StmtIteratorBase() : stmt(0), DGI(0), RawVAPtr(0) {} }; @@ -86,7 +82,6 @@ public: StmtIteratorImpl() {} StmtIteratorImpl(Stmt **s) : StmtIteratorBase(s) {} StmtIteratorImpl(Decl **dgi, Decl **dge) : StmtIteratorBase(dgi, dge) {} - StmtIteratorImpl(Decl *d, Stmt **s) : StmtIteratorBase(d, s) {} StmtIteratorImpl(const VariableArrayType *t) : StmtIteratorBase(t) {} DERIVED& operator++() { @@ -107,15 +102,15 @@ public: } bool operator==(const DERIVED& RHS) const { - return stmt == RHS.stmt && decl == RHS.decl && RawVAPtr == RHS.RawVAPtr; + return stmt == RHS.stmt && DGI == RHS.DGI && RawVAPtr == RHS.RawVAPtr; } bool operator!=(const DERIVED& RHS) const { - return stmt != RHS.stmt || decl != RHS.decl || RawVAPtr != RHS.RawVAPtr; + return stmt != RHS.stmt || DGI != RHS.DGI || RawVAPtr != RHS.RawVAPtr; } REFERENCE operator*() const { - return (REFERENCE) (inStmt() ? *stmt : GetDeclExpr()); + return inStmt() ? *stmt : GetDeclExpr(); } REFERENCE operator->() const { return operator*(); } @@ -131,9 +126,6 @@ struct StmtIterator : public StmtIteratorImpl { StmtIterator(const VariableArrayType *t) : StmtIteratorImpl(t) {} - - StmtIterator(Decl* D, Stmt **s = 0) - : StmtIteratorImpl(D, s) {} }; struct ConstStmtIterator : public StmtIteratorImpl { : std::pair(begin, end) {} bool empty() const { return first == second; } - operator bool() const { return !empty(); } + LLVM_EXPLICIT operator bool() const { return !empty(); } Stmt *operator->() const { return first.operator->(); } Stmt *&operator*() const { return first.operator*(); } @@ -199,7 +191,7 @@ struct ConstStmtRange : std::pair { : std::pair(begin, end) {} bool empty() const { return first == second; } - operator bool() const { return !empty(); } + LLVM_EXPLICIT operator bool() const { return !empty(); } const Stmt *operator->() const { return first.operator->(); } const Stmt *operator*() const { return first.operator*(); } diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index e97c1a5a319f..bfb4a9b0bb7a 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -181,13 +181,12 @@ private: HasFinally(HasFinally) { } public: - static ObjCAtTryStmt *Create(ASTContext &Context, SourceLocation atTryLoc, - Stmt *atTryStmt, + static ObjCAtTryStmt *Create(const ASTContext &Context, + SourceLocation atTryLoc, Stmt *atTryStmt, Stmt **CatchStmts, unsigned NumCatchStmts, Stmt *atFinallyStmt); - static ObjCAtTryStmt *CreateEmpty(ASTContext &Context, - unsigned NumCatchStmts, - bool HasFinally); + static ObjCAtTryStmt *CreateEmpty(const ASTContext &Context, + unsigned NumCatchStmts, bool HasFinally); /// \brief Retrieve the location of the @ in the \@try. SourceLocation getAtTryLoc() const { return AtTryLoc; } diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h new file mode 100644 index 000000000000..8570d8850a2f --- /dev/null +++ b/include/clang/AST/StmtOpenMP.h @@ -0,0 +1,528 @@ +//===- StmtOpenMP.h - Classes for OpenMP directives and clauses --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// \file +/// \brief This file defines OpenMP AST classes for executable directives and +/// clauses. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_STMTOPENMP_H +#define LLVM_CLANG_AST_STMTOPENMP_H + +#include "clang/Basic/OpenMPKinds.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" + +namespace clang { + +//===----------------------------------------------------------------------===// +// AST classes for clauses. +//===----------------------------------------------------------------------===// + +/// \brief This is a basic class for representing single OpenMP clause. +/// +class OMPClause { + /// \brief Starting location of the clause (the clause keyword). + SourceLocation StartLoc; + /// \brief Ending location of the clause. + SourceLocation EndLoc; + /// \brief Kind of the clause. + OpenMPClauseKind Kind; +protected: + OMPClause(OpenMPClauseKind K, SourceLocation StartLoc, SourceLocation EndLoc) + : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {} + +public: + + /// \brief Returns the starting location of the clause. + SourceLocation getLocStart() const { return StartLoc; } + /// \brief Returns the ending location of the clause. + SourceLocation getLocEnd() const { return EndLoc; } + + /// \brief Sets the starting location of the clause. + void setLocStart(SourceLocation Loc) { StartLoc = Loc; } + /// \brief Sets the ending location of the clause. + void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } + + /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.). + OpenMPClauseKind getClauseKind() const { return Kind; } + + bool isImplicit() const { return StartLoc.isInvalid();} + + StmtRange children(); + ConstStmtRange children() const { + return const_cast(this)->children(); + } + static bool classof(const OMPClause *T) { + return true; + } +}; + +/// \brief This represents clauses with the list of variables like 'private', +/// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the +/// '#pragma omp ...' directives. +template +class OMPVarList { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Number of variables in the list. + unsigned NumVars; +protected: + /// \brief Fetches list of variables associated with this clause. + llvm::MutableArrayRef getVarRefs() { + return llvm::MutableArrayRef( + reinterpret_cast(static_cast(this) + 1), + NumVars); + } + + /// \brief Sets the list of variables for this clause. + void setVarRefs(ArrayRef VL) { + assert(VL.size() == NumVars && + "Number of variables is not the same as the preallocated buffer"); + std::copy(VL.begin(), VL.end(), + reinterpret_cast(static_cast(this) + 1)); + } + + /// \brief Build clause with number of variables \a N. + /// + /// \param N Number of the variables in the clause. + /// + OMPVarList(SourceLocation LParenLoc, unsigned N) + : LParenLoc(LParenLoc), NumVars(N) { } +public: + typedef llvm::MutableArrayRef::iterator varlist_iterator; + typedef ArrayRef::iterator varlist_const_iterator; + + unsigned varlist_size() const { return NumVars; } + bool varlist_empty() const { return NumVars == 0; } + varlist_iterator varlist_begin() { return getVarRefs().begin(); } + varlist_iterator varlist_end() { return getVarRefs().end(); } + varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); } + varlist_const_iterator varlist_end() const { return getVarRefs().end(); } + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Fetches list of all variables in the clause. + ArrayRef getVarRefs() const { + return ArrayRef( + reinterpret_cast(static_cast(this) + 1), + NumVars); + } +}; + +/// \brief This represents 'default' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp parallel default(shared) +/// \endcode +/// In this example directive '#pragma omp parallel' has simple 'default' +/// clause with kind 'shared'. +/// +class OMPDefaultClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief A kind of the 'default' clause. + OpenMPDefaultClauseKind Kind; + /// \brief Start location of the kind in source code. + SourceLocation KindKwLoc; + + /// \brief Set kind of the clauses. + /// + /// \param K Argument of clause. + /// + void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } + + /// \brief Set argument location. + /// + /// \param KLoc Argument location. + /// + void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } +public: + /// \brief Build 'default' clause with argument \a A ('none' or 'shared'). + /// + /// \param A Argument of the clause ('none' or 'shared'). + /// \param ALoc Starting location of the argument. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// + OMPDefaultClause(OpenMPDefaultClauseKind A, SourceLocation ALoc, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) + : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc), + Kind(A), KindKwLoc(ALoc) { } + + /// \brief Build an empty clause. + /// + OMPDefaultClause() + : OMPClause(OMPC_default, SourceLocation(), SourceLocation()), + LParenLoc(SourceLocation()), Kind(OMPC_DEFAULT_unknown), + KindKwLoc(SourceLocation()) { } + + /// \brief Sets the location of '('. + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Returns the location of '('. + SourceLocation getLParenLoc() const { return LParenLoc; } + + /// \brief Returns kind of the clause. + OpenMPDefaultClauseKind getDefaultKind() const { return Kind; } + + /// \brief Returns location of clause kind. + SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_default; + } + + StmtRange children() { + return StmtRange(); + } +}; + +/// \brief This represents clause 'private' in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp parallel private(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'private' +/// with the variables 'a' and 'b'. +/// +class OMPPrivateClause : public OMPClause, public OMPVarList { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPPrivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPClause(OMPC_private, StartLoc, EndLoc), + OMPVarList(LParenLoc, N) { } + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPPrivateClause(unsigned N) + : OMPClause(OMPC_private, SourceLocation(), SourceLocation()), + OMPVarList(SourceLocation(), N) { } +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef VL); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_private; + } +}; + +/// \brief This represents clause 'firstprivate' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp parallel firstprivate(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'firstprivate' +/// with the variables 'a' and 'b'. +/// +class OMPFirstprivateClause : public OMPClause, + public OMPVarList { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPClause(OMPC_firstprivate, StartLoc, EndLoc), + OMPVarList(LParenLoc, N) { } + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPFirstprivateClause(unsigned N) + : OMPClause(OMPC_firstprivate, SourceLocation(), SourceLocation()), + OMPVarList(SourceLocation(), N) { } +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPFirstprivateClause *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, + ArrayRef VL); + /// \brief Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_firstprivate; + } +}; + +/// \brief This represents clause 'shared' in the '#pragma omp ...' directives. +/// +/// \code +/// #pragma omp parallel shared(a,b) +/// \endcode +/// In this example directive '#pragma omp parallel' has clause 'shared' +/// with the variables 'a' and 'b'. +/// +class OMPSharedClause : public OMPClause, public OMPVarList { + /// \brief Build clause with number of variables \a N. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param N Number of the variables in the clause. + /// + OMPSharedClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPClause(OMPC_shared, StartLoc, EndLoc), + OMPVarList(LParenLoc, N) { } + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPSharedClause(unsigned N) + : OMPClause(OMPC_shared, SourceLocation(), SourceLocation()), + OMPVarList(SourceLocation(), N) { } +public: + /// \brief Creates clause with a list of variables \a VL. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param VL List of references to the variables. + /// + static OMPSharedClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef VL); + /// \brief Creates an empty clause with \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPSharedClause *CreateEmpty(const ASTContext &C, unsigned N); + + StmtRange children() { + return StmtRange(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_shared; + } +}; + +//===----------------------------------------------------------------------===// +// AST classes for directives. +//===----------------------------------------------------------------------===// + +/// \brief This is a basic class for representing single OpenMP executable +/// directive. +/// +class OMPExecutableDirective : public Stmt { + friend class ASTStmtReader; + /// \brief Kind of the directive. + OpenMPDirectiveKind Kind; + /// \brief Starting location of the directive (directive keyword). + SourceLocation StartLoc; + /// \brief Ending location of the directive. + SourceLocation EndLoc; + /// \brief Pointer to the list of clauses. + llvm::MutableArrayRef Clauses; + /// \brief Associated statement (if any) and expressions. + llvm::MutableArrayRef StmtAndExpressions; +protected: + /// \brief Build instance of directive of class \a K. + /// + /// \param SC Statement class. + /// \param K Kind of OpenMP directive. + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending location of the directive. + /// + template + OMPExecutableDirective(const T *, StmtClass SC, OpenMPDirectiveKind K, + SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses, unsigned NumberOfExpressions) + : Stmt(SC), Kind(K), StartLoc(StartLoc), EndLoc(EndLoc), + Clauses(reinterpret_cast(static_cast(this) + 1), + NumClauses), + StmtAndExpressions(reinterpret_cast(Clauses.end()), + NumberOfExpressions) { } + + /// \brief Sets the list of variables for this clause. + /// + /// \param Clauses The list of clauses for the directive. + /// + void setClauses(ArrayRef Clauses); + + /// \brief Set the associated statement for the directive. + /// + /// /param S Associated statement. + /// + void setAssociatedStmt(Stmt *S) { + StmtAndExpressions[0] = S; + } + +public: + /// \brief Returns starting location of directive kind. + SourceLocation getLocStart() const { return StartLoc; } + /// \brief Returns ending location of directive. + SourceLocation getLocEnd() const { return EndLoc; } + + /// \brief Set starting location of directive kind. + /// + /// \param Loc New starting location of directive. + /// + void setLocStart(SourceLocation Loc) { StartLoc = Loc; } + /// \brief Set ending location of directive. + /// + /// \param Loc New ending location of directive. + /// + void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } + + /// \brief Get number of clauses. + unsigned getNumClauses() const { return Clauses.size(); } + + /// \brief Returns specified clause. + /// + /// \param i Number of clause. + /// + OMPClause *getClause(unsigned i) const { + assert(i < Clauses.size() && "index out of bound!"); + return Clauses[i]; + } + + /// \brief Returns statement associated with the directive. + Stmt *getAssociatedStmt() const { + return StmtAndExpressions[0]; + } + + OpenMPDirectiveKind getDirectiveKind() const { return Kind; } + + static bool classof(const Stmt *S) { + return S->getStmtClass() >= firstOMPExecutableDirectiveConstant && + S->getStmtClass() <= lastOMPExecutableDirectiveConstant; + } + + child_range children() { + return child_range(StmtAndExpressions.begin(), StmtAndExpressions.end()); + } + + ArrayRef clauses() { return Clauses; } + + ArrayRef clauses() const { return Clauses; } +}; + +/// \brief This represents '#pragma omp parallel' directive. +/// +/// \code +/// #pragma omp parallel private(a,b) reduction(+: c,d) +/// \endcode +/// In this example directive '#pragma omp parallel' has clauses 'private' +/// with the variables 'a' and 'b' and 'reduction' with operator '+' and +/// variables 'c' and 'd'. +/// +class OMPParallelDirective : public OMPExecutableDirective { + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending Location of the directive. + /// + OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned N) + : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, + StartLoc, EndLoc, N, 1) { } + + /// \brief Build an empty directive. + /// + /// \param N Number of clauses. + /// + explicit OMPParallelDirective(unsigned N) + : OMPExecutableDirective(this, OMPParallelDirectiveClass, OMPD_parallel, + SourceLocation(), SourceLocation(), N, 1) { } +public: + /// \brief Creates directive with a list of \a Clauses. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement associated with the directive. + /// + static OMPParallelDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a N clauses. + /// + /// \param C AST context. + /// \param N The number of clauses. + /// + static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned N, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelDirectiveClass; + } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 38c4c0220e11..c71af38b61b6 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -18,6 +18,7 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" +#include "clang/AST/StmtOpenMP.h" namespace clang { @@ -184,6 +185,41 @@ template class ConstStmtVisitor : public StmtVisitorBase {}; +/// \brief This class implements a simple visitor for OMPClause +/// subclasses. +template class Ptr, typename RetTy> +class OMPClauseVisitorBase { +public: +#define PTR(CLASS) typename Ptr::type +#define DISPATCH(CLASS) \ + return static_cast(this)->Visit##CLASS(static_cast(S)) + +#define OPENMP_CLAUSE(Name, Class) \ + RetTy Visit ## Class (PTR(Class) S) { DISPATCH(Class); } +#include "clang/Basic/OpenMPKinds.def" + + RetTy Visit(PTR(OMPClause) S) { + // Top switch clause: visit each OMPClause. + switch (S->getClauseKind()) { + default: llvm_unreachable("Unknown clause kind!"); +#define OPENMP_CLAUSE(Name, Class) \ + case OMPC_ ## Name : return Visit ## Class(static_cast(S)); +#include "clang/Basic/OpenMPKinds.def" + } + } + // Base case, ignore it. :) + RetTy VisitOMPClause(PTR(OMPClause) Node) { return RetTy(); } +#undef PTR +#undef DISPATCH +}; + +template +class OMPClauseVisitor : + public OMPClauseVisitorBase {}; +template +class ConstOMPClauseVisitor : + public OMPClauseVisitorBase {}; + } // end namespace clang #endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 70b934f36c2c..6c40eb1168ce 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -60,8 +60,8 @@ public: /// The template argument is a pack expansion of a template name that was /// provided for a template template parameter. TemplateExpansion, - /// The template argument is a value- or type-dependent expression - /// stored in an Expr*. + /// The template argument is a value- or type-dependent expression or a + /// non-dependent __uuidof expression stored in an Expr*. Expression, /// The template argument is actually a parameter pack. Arguments are stored /// in the Args struct. @@ -70,57 +70,68 @@ public: private: /// \brief The kind of template argument we're storing. - unsigned Kind; struct DA { - ValueDecl *D; + unsigned Kind; bool ForRefParam; + ValueDecl *D; }; struct I { + unsigned Kind; // We store a decomposed APSInt with the data allocated by ASTContext if // BitWidth > 64. The memory may be shared between multiple // TemplateArgument instances. + unsigned BitWidth : 31; + unsigned IsUnsigned : 1; union { uint64_t VAL; ///< Used to store the <= 64 bits integer value. const uint64_t *pVal; ///< Used to store the >64 bits integer value. }; - unsigned BitWidth : 31; - unsigned IsUnsigned : 1; void *Type; }; struct A { - const TemplateArgument *Args; + unsigned Kind; unsigned NumArgs; + const TemplateArgument *Args; }; struct TA { - void *Name; + unsigned Kind; unsigned NumExpansions; + void *Name; + }; + struct TV { + unsigned Kind; + uintptr_t V; }; union { struct DA DeclArg; struct I Integer; struct A Args; struct TA TemplateArg; - uintptr_t TypeOrValue; + struct TV TypeOrValue; }; TemplateArgument(TemplateName, bool) LLVM_DELETED_FUNCTION; public: /// \brief Construct an empty, invalid template argument. - TemplateArgument() : Kind(Null), TypeOrValue(0) { } + TemplateArgument() { + TypeOrValue.Kind = Null; + TypeOrValue.V = 0; + } /// \brief Construct a template type argument. - TemplateArgument(QualType T, bool isNullPtr = false) - : Kind(isNullPtr ? NullPtr : Type) { - TypeOrValue = reinterpret_cast(T.getAsOpaquePtr()); + TemplateArgument(QualType T, bool isNullPtr = false) { + TypeOrValue.Kind = isNullPtr ? NullPtr : Type; + TypeOrValue.V = reinterpret_cast(T.getAsOpaquePtr()); } /// \brief Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. - TemplateArgument(ValueDecl *D, bool ForRefParam) : Kind(Declaration) { + TemplateArgument(ValueDecl *D, bool ForRefParam) { assert(D && "Expected decl"); + DeclArg.Kind = Declaration; DeclArg.D = D; DeclArg.ForRefParam = ForRefParam; } @@ -131,8 +142,7 @@ public: /// \brief Construct an integral constant template argument with the same /// value as Other but a different type. - TemplateArgument(const TemplateArgument &Other, QualType Type) - : Kind(Integral) { + TemplateArgument(const TemplateArgument &Other, QualType Type) { Integer = Other.Integer; Integer.Type = Type.getAsOpaquePtr(); } @@ -145,8 +155,8 @@ public: /// is taken. /// /// \param Name The template name. - TemplateArgument(TemplateName Name) : Kind(Template) - { + TemplateArgument(TemplateName Name) { + TemplateArg.Kind = Template; TemplateArg.Name = Name.getAsVoidPointer(); TemplateArg.NumExpansions = 0; } @@ -162,9 +172,8 @@ public: /// /// \param NumExpansions The number of expansions that will be generated by /// instantiating - TemplateArgument(TemplateName Name, Optional NumExpansions) - : Kind(TemplateExpansion) - { + TemplateArgument(TemplateName Name, Optional NumExpansions) { + TemplateArg.Kind = TemplateExpansion; TemplateArg.Name = Name.getAsVoidPointer(); if (NumExpansions) TemplateArg.NumExpansions = *NumExpansions + 1; @@ -177,15 +186,17 @@ public: /// This form of template argument only occurs in template argument /// lists used for dependent types and for expression; it will not /// occur in a non-dependent, canonical template argument list. - TemplateArgument(Expr *E) : Kind(Expression) { - TypeOrValue = reinterpret_cast(E); + TemplateArgument(Expr *E) { + TypeOrValue.Kind = Expression; + TypeOrValue.V = reinterpret_cast(E); } /// \brief Construct a template argument that is a template argument pack. /// /// We assume that storage for the template arguments provided /// outlives the TemplateArgument itself. - TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) : Kind(Pack){ + TemplateArgument(const TemplateArgument *Args, unsigned NumArgs) { + this->Args.Kind = Pack; this->Args.Args = Args; this->Args.NumArgs = NumArgs; } @@ -201,10 +212,10 @@ public: unsigned NumArgs); /// \brief Return the kind of stored template argument. - ArgKind getKind() const { return (ArgKind)Kind; } + ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } /// \brief Determine whether this template argument has no value. - bool isNull() const { return Kind == Null; } + bool isNull() const { return getKind() == Null; } /// \brief Whether this template argument is dependent on a template /// parameter such that its result can change from one instantiation to @@ -224,40 +235,40 @@ public: /// \brief Retrieve the type for a type template argument. QualType getAsType() const { - assert(Kind == Type && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue)); + assert(getKind() == Type && "Unexpected kind"); + return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue.V)); } /// \brief Retrieve the declaration for a declaration non-type /// template argument. ValueDecl *getAsDecl() const { - assert(Kind == Declaration && "Unexpected kind"); + assert(getKind() == Declaration && "Unexpected kind"); return DeclArg.D; } /// \brief Retrieve whether a declaration is binding to a /// reference parameter in a declaration non-type template argument. bool isDeclForReferenceParam() const { - assert(Kind == Declaration && "Unexpected kind"); + assert(getKind() == Declaration && "Unexpected kind"); return DeclArg.ForRefParam; } /// \brief Retrieve the type for null non-type template argument. QualType getNullPtrType() const { - assert(Kind == NullPtr && "Unexpected kind"); - return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue)); + assert(getKind() == NullPtr && "Unexpected kind"); + return QualType::getFromOpaquePtr(reinterpret_cast(TypeOrValue.V)); } /// \brief Retrieve the template name for a template name argument. TemplateName getAsTemplate() const { - assert(Kind == Template && "Unexpected kind"); + assert(getKind() == Template && "Unexpected kind"); return TemplateName::getFromVoidPointer(TemplateArg.Name); } /// \brief Retrieve the template argument as a template name; if the argument /// is a pack expansion, return the pattern as a template name. TemplateName getAsTemplateOrTemplatePattern() const { - assert((Kind == Template || Kind == TemplateExpansion) && + assert((getKind() == Template || getKind() == TemplateExpansion) && "Unexpected kind"); return TemplateName::getFromVoidPointer(TemplateArg.Name); @@ -270,7 +281,7 @@ public: /// \brief Retrieve the template argument as an integral value. // FIXME: Provide a way to read the integral data without copying the value. llvm::APSInt getAsIntegral() const { - assert(Kind == Integral && "Unexpected kind"); + assert(getKind() == Integral && "Unexpected kind"); using namespace llvm; if (Integer.BitWidth <= 64) return APSInt(APInt(Integer.BitWidth, Integer.VAL), Integer.IsUnsigned); @@ -282,19 +293,19 @@ public: /// \brief Retrieve the type of the integral value. QualType getIntegralType() const { - assert(Kind == Integral && "Unexpected kind"); + assert(getKind() == Integral && "Unexpected kind"); return QualType::getFromOpaquePtr(Integer.Type); } void setIntegralType(QualType T) { - assert(Kind == Integral && "Unexpected kind"); + assert(getKind() == Integral && "Unexpected kind"); Integer.Type = T.getAsOpaquePtr(); } /// \brief Retrieve the template argument as an expression. Expr *getAsExpr() const { - assert(Kind == Expression && "Unexpected kind"); - return reinterpret_cast(TypeOrValue); + assert(getKind() == Expression && "Unexpected kind"); + return reinterpret_cast(TypeOrValue.V); } /// \brief Iterator that traverses the elements of a template argument pack. @@ -303,27 +314,27 @@ public: /// \brief Iterator referencing the first argument of a template argument /// pack. pack_iterator pack_begin() const { - assert(Kind == Pack); + assert(getKind() == Pack); return Args.Args; } /// \brief Iterator referencing one past the last argument of a template /// argument pack. pack_iterator pack_end() const { - assert(Kind == Pack); + assert(getKind() == Pack); return Args.Args + Args.NumArgs; } /// \brief The number of template arguments in the given template argument /// pack. unsigned pack_size() const { - assert(Kind == Pack); + assert(getKind() == Pack); return Args.NumArgs; } /// \brief Return the array of arguments in this template argument pack. llvm::ArrayRef getPackAsArray() const { - assert(Kind == Pack); + assert(getKind() == Pack); return llvm::ArrayRef(Args.Args, Args.NumArgs); } @@ -494,17 +505,6 @@ public: assert(Argument.getKind() == TemplateArgument::TemplateExpansion); return LocInfo.getTemplateEllipsisLoc(); } - - /// \brief When the template argument is a pack expansion, returns - /// the pattern of the pack expansion. - /// - /// \param Ellipsis Will be set to the location of the ellipsis. - /// - /// \param NumExpansions Will be set to the number of expansions that will - /// be generated from this pack expansion, if known a priori. - TemplateArgumentLoc getPackExpansionPattern(SourceLocation &Ellipsis, - Optional &NumExpansions, - ASTContext &Context) const; }; /// A convenient class for passing around template argument diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 39f10d3393ba..fb829e4d4103 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -441,7 +441,7 @@ public: bool operator==(Qualifiers Other) const { return Mask == Other.Mask; } bool operator!=(Qualifiers Other) const { return Mask != Other.Mask; } - operator bool() const { return hasQualifiers(); } + LLVM_EXPLICIT operator bool() const { return hasQualifiers(); } Qualifiers &operator+=(Qualifiers R) { addQualifiers(R); @@ -818,7 +818,7 @@ public: /// an lvalue. It removes a top-level reference (since there are no /// expressions of reference type) and deletes top-level cvr-qualifiers /// from non-class types (in C++) or all types (in C). - QualType getNonLValueExprType(ASTContext &Context) const; + QualType getNonLValueExprType(const ASTContext &Context) const; /// getDesugaredType - Return the specified type with any "sugar" removed from /// the type. This takes off typedefs, typeof's etc. If the outer level of @@ -1194,7 +1194,7 @@ private: mutable unsigned CacheValid : 1; /// \brief Linkage of this type. - mutable unsigned CachedLinkage : 2; + mutable unsigned CachedLinkage : 3; /// \brief Whether this type involves and local or unnamed types. mutable unsigned CachedLocalOrUnnamed : 1; @@ -1214,7 +1214,7 @@ private: return CachedLocalOrUnnamed; } }; - enum { NumTypeBits = 19 }; + enum { NumTypeBits = 18 }; protected: // These classes allow subclasses to somewhat cleanly pack bitfields @@ -1315,6 +1315,8 @@ protected: /// NumElements - The number of elements in the vector. unsigned NumElements : 29 - NumTypeBits; + + enum { MaxNumElements = (1 << (29 - NumTypeBits)) - 1 }; }; class AttributedTypeBitfields { @@ -1454,7 +1456,7 @@ public: /// isLiteralType - Return true if this is a literal type /// (C++11 [basic.types]p10) - bool isLiteralType(ASTContext &Ctx) const; + bool isLiteralType(const ASTContext &Ctx) const; /// \brief Test if this type is a standard-layout type. /// (C++0x [basic.type]p9) @@ -1512,7 +1514,6 @@ public: bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) bool isVoidType() const; // C99 6.2.5p19 - bool isDerivedType() const; // C99 6.2.5p20 bool isScalarType() const; // C99 6.2.5p21 (arithmetic + pointers) bool isAggregateType() const; bool isFundamentalType() const; @@ -1811,6 +1812,10 @@ template <> const TypedefType *Type::getAs() const; /// non-sugared type. template <> const TemplateSpecializationType *Type::getAs() const; +/// \brief This will check for an AttributedType by removing any existing sugar +/// until it reaches an AttributedType or a non-sugared type. +template <> const AttributedType *Type::getAs() const; + // We can do canonical leaf types faster, because we don't have to // worry about preserving child type decoration. #define TYPE(Class, Base) @@ -1991,6 +1996,44 @@ public: static bool classof(const Type *T) { return T->getTypeClass() == Pointer; } }; +/// \brief Represents a pointer type decayed from an array or function type. +class DecayedType : public Type, public llvm::FoldingSetNode { + QualType OriginalType; + QualType DecayedPointer; + + DecayedType(QualType OriginalType, QualType DecayedPointer, + QualType CanonicalPtr) + : Type(Decayed, CanonicalPtr, OriginalType->isDependentType(), + OriginalType->isInstantiationDependentType(), + OriginalType->isVariablyModifiedType(), + OriginalType->containsUnexpandedParameterPack()), + OriginalType(OriginalType), DecayedPointer(DecayedPointer) { + assert(isa(DecayedPointer)); + } + + friend class ASTContext; // ASTContext creates these. + +public: + QualType getDecayedType() const { return DecayedPointer; } + QualType getOriginalType() const { return OriginalType; } + + QualType getPointeeType() const { + return cast(DecayedPointer)->getPointeeType(); + } + + bool isSugared() const { return true; } + QualType desugar() const { return DecayedPointer; } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, OriginalType); + } + static void Profile(llvm::FoldingSetNodeID &ID, QualType OriginalType) { + ID.AddPointer(OriginalType.getAsOpaquePtr()); + } + + static bool classof(const Type *T) { return T->getTypeClass() == Decayed; } +}; + /// BlockPointerType - pointer to a block type. /// This type is to represent types syntactically represented as /// "void (^)(int)", etc. Pointee is required to always be a function type. @@ -2487,6 +2530,9 @@ public: QualType getElementType() const { return ElementType; } unsigned getNumElements() const { return VectorTypeBits.NumElements; } + static bool isVectorSizeTooLarge(unsigned NumElements) { + return NumElements > VectorTypeBitfields::MaxNumElements; + } bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2641,7 +2687,11 @@ class FunctionType : public Type { // Constructor with all defaults. Use when for example creating a // function know to use defaults. - ExtInfo() : Bits(0) {} + ExtInfo() : Bits(CC_C) { } + + // Constructor with just the calling convention, which is an important part + // of the canonical type. + ExtInfo(CallingConv CC) : Bits(CC) { } bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } @@ -2784,6 +2834,12 @@ public: ExceptionSpecDecl(0), ExceptionSpecTemplate(0), ConsumedArguments(0) {} + ExtProtoInfo(CallingConv CC) + : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), + ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), + Exceptions(0), NoexceptExpr(0), ExceptionSpecDecl(0), + ExceptionSpecTemplate(0), ConsumedArguments(0) {} + FunctionType::ExtInfo ExtInfo; bool Variadic : 1; bool HasTrailingReturn : 1; @@ -2928,7 +2984,7 @@ public: NR_Nothrow ///< The noexcept specifier evaluates to true. }; /// \brief Get the meaning of the noexcept spec on this function, if any. - NoexceptResult getNoexceptSpec(ASTContext &Ctx) const; + NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); @@ -2959,7 +3015,7 @@ public: return 0; return reinterpret_cast(arg_type_end())[1]; } - bool isNothrow(ASTContext &Ctx) const { + bool isNothrow(const ASTContext &Ctx) const { ExceptionSpecificationType EST = getExceptionSpecType(); assert(EST != EST_Unevaluated && EST != EST_Uninstantiated); if (EST == EST_DynamicNone || EST == EST_BasicNoexcept) @@ -3323,9 +3379,10 @@ public: attr_objc_gc, attr_objc_ownership, attr_pcs, + attr_pcs_vfp, FirstEnumOperandKind = attr_objc_gc, - LastEnumOperandKind = attr_pcs, + LastEnumOperandKind = attr_pcs_vfp, // No operand. attr_noreturn, @@ -3335,7 +3392,13 @@ public: attr_thiscall, attr_pascal, attr_pnaclcall, - attr_inteloclbicc + attr_inteloclbicc, + attr_ms_abi, + attr_sysv_abi, + attr_ptr32, + attr_ptr64, + attr_sptr, + attr_uptr }; private: @@ -3365,6 +3428,10 @@ public: bool isSugared() const { return true; } QualType desugar() const { return getEquivalentType(); } + bool isMSTypeSpec() const; + + bool isCallingConv() const; + void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getAttrKind(), ModifiedType, EquivalentType); } @@ -3563,10 +3630,13 @@ public: /// is no deduced type and an auto type is canonical. In the latter case, it is /// also a dependent type. class AutoType : public Type, public llvm::FoldingSetNode { - AutoType(QualType DeducedType, bool IsDecltypeAuto, bool IsDependent) + AutoType(QualType DeducedType, bool IsDecltypeAuto, + bool IsDependent) : Type(Auto, DeducedType.isNull() ? QualType(this, 0) : DeducedType, /*Dependent=*/IsDependent, /*InstantiationDependent=*/IsDependent, - /*VariablyModified=*/false, /*ContainsParameterPack=*/false) { + /*VariablyModified=*/false, + /*ContainsParameterPack=*/DeducedType.isNull() + ? false : DeducedType->containsUnexpandedParameterPack()) { assert((DeducedType.isNull() || !IsDependent) && "auto deduced to dependent type"); AutoTypeBits.IsDecltypeAuto = IsDecltypeAuto; @@ -3590,7 +3660,8 @@ public: } void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getDeducedType(), isDecltypeAuto(), isDependentType()); + Profile(ID, getDeducedType(), isDecltypeAuto(), + isDependentType()); } static void Profile(llvm::FoldingSetNodeID &ID, QualType Deduced, @@ -3654,10 +3725,6 @@ class TemplateSpecializationType public: /// \brief Determine whether any of the given template arguments are /// dependent. - static bool anyDependentTemplateArguments(const TemplateArgument *Args, - unsigned NumArgs, - bool &InstantiationDependent); - static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, unsigned NumArgs, bool &InstantiationDependent); @@ -4154,8 +4221,8 @@ public: return None; } - bool isSugared() const { return false; } - QualType desugar() const { return QualType(this, 0); } + bool isSugared() const { return !Pattern->isDependentType(); } + QualType desugar() const { return isSugared() ? Pattern : QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getPattern(), getNumExpansions()); @@ -4189,11 +4256,11 @@ public: /// /// 'C

' is an ObjCObjectType with base C and protocol list [P]. /// -/// 'id' is a TypedefType which is sugar for an ObjCPointerType whose +/// 'id' is a TypedefType which is sugar for an ObjCObjectPointerType whose /// pointee is an ObjCObjectType with base BuiltinType::ObjCIdType /// and no protocols. /// -/// 'id

' is an ObjCPointerType whose pointee is an ObjCObjecType +/// 'id

' is an ObjCObjectPointerType whose pointee is an ObjCObjectType /// with base BuiltinType::ObjCIdType and protocol list [P]. Eventually /// this should get its own sugar class to better represent the source. class ObjCObjectType : public Type { @@ -4231,7 +4298,7 @@ public: /// getBaseType - Gets the base type of this object type. This is /// always (possibly sugar for) one of: /// - the 'id' builtin type (as opposed to the 'id' type visible to the - /// user, which is a typedef for an ObjCPointerType) + /// user, which is a typedef for an ObjCObjectPointerType) /// - the 'Class' builtin type (same caveat) /// - an ObjCObjectType (currently always an ObjCInterfaceType) QualType getBaseType() const { return BaseType; } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 11cad9bb9dd9..8ddfac7ad373 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file defines the TypeLoc interface and subclasses. -// +/// +/// \file +/// \brief Defines the clang::TypeLoc interface and its subclasses. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_TYPELOC_H @@ -34,8 +35,8 @@ namespace clang { /// \brief Base wrapper for a particular "section" of type source info. /// -/// A client should use the TypeLoc subclasses through cast/dyn_cast in order to -/// get at the actual information. +/// A client should use the TypeLoc subclasses through castAs()/getAs() +/// in order to get at the actual information. class TypeLoc { protected: // The correctness of this relies on the property that, for Type *Ty, @@ -46,6 +47,8 @@ protected: public: /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc /// is of the desired type. + /// + /// \pre T::isKind(*this) template T castAs() const { assert(T::isKind(*this)); @@ -90,11 +93,15 @@ public: } bool isNull() const { return !Ty; } - operator bool() const { return Ty; } + LLVM_EXPLICIT operator bool() const { return Ty; } /// \brief Returns the size of type source info data block for the given type. static unsigned getFullDataSizeForType(QualType Ty); + /// \brief Returns the alignment of type source info data block for + /// the given type. + static unsigned getLocalAlignmentForType(QualType Ty); + /// \brief Get the type for which this source info wrapper provides /// information. QualType getType() const { @@ -229,7 +236,11 @@ public: } UnqualTypeLoc getUnqualifiedLoc() const { - return UnqualTypeLoc(getTypePtr(), Data); + unsigned align = + TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0)); + uintptr_t dataInt = reinterpret_cast(Data); + dataInt = llvm::RoundUpToAlignment(dataInt, align); + return UnqualTypeLoc(getTypePtr(), reinterpret_cast(dataInt)); } /// Initializes the local data of this type source info block to @@ -250,10 +261,11 @@ public: return 0; } - /// \brief Returns the size of the type source info data block. - unsigned getFullDataSize() const { - return getLocalDataSize() + - getFullDataSizeForType(getType().getLocalUnqualifiedType()); + /// \brief Returns the alignment of the type source info data block that is + /// specific to this type. + unsigned getLocalDataAlignment() const { + // We don't preserve any location information. + return 1; } private: @@ -280,9 +292,6 @@ inline UnqualTypeLoc TypeLoc::getUnqualifiedLoc() const { /// \tparam LocalData the structure type of local location data for /// this type /// -/// sizeof(LocalData) needs to be a multiple of sizeof(void*) or -/// else the world will end. -/// /// TypeLocs with non-constant amounts of local data should override /// getExtraLocalDataSize(); getExtraLocalData() will then point to /// this extra memory. @@ -309,7 +318,8 @@ class ConcreteTypeLoc : public Base { friend class TypeLoc; static bool isKind(const TypeLoc &TL) { - return Derived::classofType(TL.getTypePtr()); + return !TL.getType().hasLocalQualifiers() && + Derived::classofType(TL.getTypePtr()); } static bool classofType(const Type *Ty) { @@ -317,12 +327,16 @@ class ConcreteTypeLoc : public Base { } public: - unsigned getLocalDataSize() const { - return sizeof(LocalData) + asDerived()->getExtraLocalDataSize(); + unsigned getLocalDataAlignment() const { + return std::max(llvm::alignOf(), + asDerived()->getExtraLocalDataAlignment()); } - // Give a default implementation that's useful for leaf types. - unsigned getFullDataSize() const { - return asDerived()->getLocalDataSize() + getInnerTypeSize(); + unsigned getLocalDataSize() const { + unsigned size = sizeof(LocalData); + unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); + size = llvm::RoundUpToAlignment(size, extraAlign); + size += asDerived()->getExtraLocalDataSize(); + return size; } TypeLoc getNextTypeLoc() const { @@ -338,6 +352,10 @@ protected: return 0; } + unsigned getExtraLocalDataAlignment() const { + return 1; + } + LocalData *getLocalData() const { return static_cast(Base::Data); } @@ -346,11 +364,17 @@ protected: /// local data that can't be captured in the Info (e.g. because it's /// of variable size). void *getExtraLocalData() const { - return getLocalData() + 1; + unsigned size = sizeof(LocalData); + unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); + size = llvm::RoundUpToAlignment(size, extraAlign); + return reinterpret_cast(Base::Data) + size; } void *getNonLocalData() const { - return static_cast(Base::Data) + asDerived()->getLocalDataSize(); + uintptr_t data = reinterpret_cast(Base::Data); + data += asDerived()->getLocalDataSize(); + data = llvm::RoundUpToAlignment(data, getNextTypeAlign()); + return reinterpret_cast(data); } struct HasNoInnerType {}; @@ -373,6 +397,18 @@ private: return getInnerTypeLoc().getFullDataSize(); } + unsigned getNextTypeAlign() const { + return getNextTypeAlign(asDerived()->getInnerType()); + } + + unsigned getNextTypeAlign(HasNoInnerType _) const { + return 1; + } + + unsigned getNextTypeAlign(QualType T) const { + return TypeLoc::getLocalAlignmentForType(T); + } + TypeLoc getNextTypeLoc(HasNoInnerType _) const { return TypeLoc(); } @@ -393,7 +429,8 @@ class InheritingConcreteTypeLoc : public Base { } static bool isKind(const TypeLoc &TL) { - return Derived::classofType(TL.getTypePtr()); + return !TL.getType().hasLocalQualifiers() && + Derived::classofType(TL.getTypePtr()); } static bool isKind(const UnqualTypeLoc &TL) { return Derived::classofType(TL.getTypePtr()); @@ -417,7 +454,8 @@ class TypeSpecTypeLoc : public ConcreteTypeLoc { public: - enum { LocalDataSize = sizeof(TypeSpecLocInfo) }; + enum { LocalDataSize = sizeof(TypeSpecLocInfo), + LocalDataAlignment = llvm::AlignOf::Alignment }; SourceLocation getNameLoc() const { return this->getLocalData()->NameLoc; @@ -448,8 +486,6 @@ class BuiltinTypeLoc : public ConcreteTypeLoc { public: - enum { LocalDataSize = sizeof(BuiltinLocInfo) }; - SourceLocation getBuiltinLoc() const { return getLocalData()->BuiltinLoc; } @@ -478,6 +514,10 @@ public: return needsExtraLocalData() ? sizeof(WrittenBuiltinSpecs) : 0; } + unsigned getExtraLocalDataAlignment() const { + return needsExtraLocalData() ? llvm::alignOf() : 1; + } + SourceRange getLocalSourceRange() const { return SourceRange(getBuiltinLoc(), getBuiltinLoc()); } @@ -840,6 +880,10 @@ public: return this->getNumProtocols() * sizeof(SourceLocation); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + QualType getInnerType() const { return getTypePtr()->getBaseType(); } @@ -933,6 +977,40 @@ inline TypeLoc TypeLoc::IgnoreParens() const { return *this; } + +struct DecayedLocInfo { }; // Nothing. + +/// \brief Wrapper for source info for pointers decayed from arrays and +/// functions. +class DecayedTypeLoc : public ConcreteTypeLoc { +public: + TypeLoc getOriginalLoc() const { + return getInnerTypeLoc(); + } + + void initializeLocal(ASTContext &Context, SourceLocation Loc) { + // do nothing + } + + QualType getInnerType() const { + // The inner type is the undecayed type, since that's what we have source + // location information for. + return getTypePtr()->getOriginalType(); + } + + SourceRange getLocalSourceRange() const { + return SourceRange(); + } + + unsigned getLocalDataSize() const { + // sizeof(DecayedLocInfo) is 1, but we don't need its address to be unique + // anyway. TypeLocBuilder can't handle data sizes of 1. + return 0; // No data. + } +}; + + struct PointerLikeLocInfo { SourceLocation StarLoc; }; @@ -1166,6 +1244,10 @@ public: return getNumArgs() * sizeof(ParmVarDecl*); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + QualType getInnerType() const { return getTypePtr()->getResultType(); } }; @@ -1357,6 +1439,10 @@ public: return getNumArgs() * sizeof(TemplateArgumentLocInfo); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + private: TemplateArgumentLocInfo *getArgInfos() const { return static_cast(getExtraLocalData()); @@ -1761,6 +1847,10 @@ public: return getNumArgs() * sizeof(TemplateArgumentLocInfo); } + unsigned getExtraLocalDataAlignment() const { + return llvm::alignOf(); + } + private: TemplateArgumentLocInfo *getArgInfos() const { return static_cast(getExtraLocalData()); diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 840e07d94a0d..3126f48c644a 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -81,6 +81,7 @@ TYPE(FunctionNoProto, FunctionType) DEPENDENT_TYPE(UnresolvedUsing, Type) NON_CANONICAL_TYPE(Paren, Type) NON_CANONICAL_TYPE(Typedef, Type) +NON_CANONICAL_TYPE(Decayed, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOfExpr, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(TypeOf, Type) NON_CANONICAL_UNLESS_DEPENDENT_TYPE(Decltype, Type) @@ -98,7 +99,7 @@ TYPE(Auto, Type) DEPENDENT_TYPE(InjectedClassName, Type) DEPENDENT_TYPE(DependentName, Type) DEPENDENT_TYPE(DependentTemplateSpecialization, Type) -DEPENDENT_TYPE(PackExpansion, Type) +NON_CANONICAL_UNLESS_DEPENDENT_TYPE(PackExpansion, Type) TYPE(ObjCObject, Type) TYPE(ObjCInterface, ObjCObjectType) TYPE(ObjCObjectPointer, Type) diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 59b59f517168..9c9f15e95323 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -6,11 +6,14 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -// -// This file provides a function objects and specializations that -// allow QualType values to be sorted, used in std::maps, std::sets, -// llvm::DenseMaps, and llvm::DenseSets. -// +/// +/// \file +/// \brief Allows QualTypes to be sorted and hence used in maps and sets. +/// +/// Defines clang::QualTypeOrdering, a total ordering on clang::QualType, +/// and hence enables QualType values to be sorted and to be used in +/// std::maps, std::sets, llvm::DenseMaps, and llvm::DenseSets. +/// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TYPE_ORDERING_H @@ -22,8 +25,7 @@ namespace clang { -/// QualTypeOrdering - Function object that provides a total ordering -/// on QualType values. +/// \brief Function object that provides a total ordering on QualType values. struct QualTypeOrdering : std::binary_function { bool operator()(QualType T1, QualType T2) const { return std::less()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr()); diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h index 242aa586d510..11e5a47f1f29 100644 --- a/include/clang/AST/TypeVisitor.h +++ b/include/clang/AST/TypeVisitor.h @@ -22,9 +22,50 @@ namespace clang { return static_cast(this)-> \ Visit##CLASS(static_cast(T)) +/// \brief An operation on a type. +/// +/// \tparam ImplClass Class implementing the operation. Must be inherited from +/// TypeVisitor. +/// \tparam RetTy %Type of result produced by the operation. +/// +/// The class implements polymorphic operation on an object of type derived +/// from Type. The operation is performed by calling method Visit. It then +/// dispatches the call to function \c VisitFooType, if actual argument type +/// is \c FooType. +/// +/// The class implements static polymorphism using Curiously Recurring +/// Template Pattern. It is designed to be a base class for some concrete +/// class: +/// +/// \code +/// class SomeVisitor : public TypeVisitor { ... }; +/// ... +/// Type *atype = ... +/// ... +/// SomeVisitor avisitor; +/// sometype result = avisitor.Visit(atype); +/// \endcode +/// +/// Actual treatment is made by methods of the derived class, TypeVisitor only +/// dispatches call to the appropriate method. If the implementation class +/// \c ImplClass provides specific action for some type, say +/// \c ConstantArrayType, it should define method +/// VisitConstantArrayType(const ConstantArrayType*). Otherwise +/// \c TypeVisitor dispatches call to the method that handles parent type. In +/// this example handlers are tried in the sequence: +/// +/// \li ImplClass::VisitConstantArrayType(const ConstantArrayType*) +/// \li ImplClass::VisitArrayType(const ArrayType*) +/// \li ImplClass::VisitType(const Type*) +/// \li TypeVisitor::VisitType(const Type*) +/// +/// The first function of this sequence that is defined will handle object of +/// type \c ConstantArrayType. template class TypeVisitor { public: + + /// \brief Performs the operation associated with this visitor object. RetTy Visit(const Type *T) { // Top switch stmt: dispatch to VisitFooType for each FooType. switch (T->getTypeClass()) { @@ -42,7 +83,8 @@ public: } #include "clang/AST/TypeNodes.def" - // Base case, ignore it. :) + /// \brief Method called if \c ImpClass doesn't provide specific handler + /// for some type class. RetTy VisitType(const Type*) { return RetTy(); } }; diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index d26065e3745b..759af2537f75 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -51,6 +51,7 @@ public: typedef std::iterator_traits::iterator_category iterator_category; NamedDecl *getDecl() const { return ir->getDecl(); } + void setDecl(NamedDecl *ND) const { return ir->setDecl(ND); } AccessSpecifier getAccess() const { return ir->getAccess(); } void setAccess(AccessSpecifier AS) { ir->setAccess(AS); } DeclAccessPair getPair() const { return *ir; } @@ -88,7 +89,7 @@ public: bool operator>(const UnresolvedSetIterator &o) const { return ir > o.ir; } }; -/// UnresolvedSet - A set of unresolved declarations. +/// \brief A set of unresolved declarations. class UnresolvedSetImpl { typedef SmallVectorImpl DeclsTy; @@ -139,15 +140,9 @@ public: I.ir->set(New, AS); } - void erase(unsigned I) { - decls()[I] = decls().back(); - decls().pop_back(); - } + void erase(unsigned I) { decls()[I] = decls().pop_back_val(); } - void erase(iterator I) { - *I.ir = decls().back(); - decls().pop_back(); - } + void erase(iterator I) { *I.ir = decls().pop_back_val(); } void setAccess(iterator I, AccessSpecifier AS) { I.ir->setAccess(AS); @@ -177,7 +172,7 @@ private: } }; -/// A set of unresolved declarations +/// \brief A set of unresolved declarations. template class UnresolvedSet : public UnresolvedSetImpl { SmallVector Decls; diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h index f24bb3f16b86..727bf5109ad4 100644 --- a/include/clang/AST/VTTBuilder.h +++ b/include/clang/AST/VTTBuilder.h @@ -63,54 +63,50 @@ struct VTTComponent { : VTableIndex(VTableIndex), VTableBase(VTableBase) {} }; -/// VTT builder - Class for building VTT layout information. +/// \brief Class for building VTT layout information. class VTTBuilder { ASTContext &Ctx; - /// MostDerivedClass - The most derived class for which we're building this - /// vtable. + /// \brief The most derived class for which we're building this vtable. const CXXRecordDecl *MostDerivedClass; typedef SmallVector VTTVTablesVectorTy; - /// VTTVTables - The VTT vtables. + /// \brief The VTT vtables. VTTVTablesVectorTy VTTVTables; typedef SmallVector VTTComponentsVectorTy; - /// VTTComponents - The VTT components. + /// \brief The VTT components. VTTComponentsVectorTy VTTComponents; - /// MostDerivedClassLayout - the AST record layout of the most derived class. + /// \brief The AST record layout of the most derived class. const ASTRecordLayout &MostDerivedClassLayout; typedef llvm::SmallPtrSet VisitedVirtualBasesSetTy; typedef llvm::DenseMap AddressPointsMapTy; - /// SubVTTIndicies - The sub-VTT indices for the bases of the most derived - /// class. + /// \brief The sub-VTT indices for the bases of the most derived class. llvm::DenseMap SubVTTIndicies; - /// SecondaryVirtualPointerIndices - The secondary virtual pointer indices of - /// all subobjects of the most derived class. + /// \brief The secondary virtual pointer indices of all subobjects of + /// the most derived class. llvm::DenseMap SecondaryVirtualPointerIndices; - /// GenerateDefinition - Whether the VTT builder should generate LLVM IR for - /// the VTT. + /// \brief Whether the VTT builder should generate LLVM IR for the VTT. bool GenerateDefinition; - /// AddVTablePointer - Add a vtable pointer to the VTT currently being built. + /// \brief Add a vtable pointer to the VTT currently being built. void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, const CXXRecordDecl *VTableClass); - /// LayoutSecondaryVTTs - Lay out the secondary VTTs of the given base - /// subobject. + /// \brief Lay out the secondary VTTs of the given base subobject. void LayoutSecondaryVTTs(BaseSubobject Base); - /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers - /// for the given base subobject. + /// \brief Lay out the secondary virtual pointers for the given base + /// subobject. /// /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base /// or a direct or indirect base of a virtual base. @@ -120,17 +116,17 @@ class VTTBuilder { const CXXRecordDecl *VTableClass, VisitedVirtualBasesSetTy &VBases); - /// LayoutSecondaryVirtualPointers - Lay out the secondary virtual pointers - /// for the given base subobject. + /// \brief Lay out the secondary virtual pointers for the given base + /// subobject. void LayoutSecondaryVirtualPointers(BaseSubobject Base, uint64_t VTableIndex); - /// LayoutVirtualVTTs - Lay out the VTTs for the virtual base classes of the - /// given record decl. + /// \brief Lay out the VTTs for the virtual base classes of the given + /// record declaration. void LayoutVirtualVTTs(const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases); - /// LayoutVTT - Will lay out the VTT for the given subobject, including any + /// \brief Lay out the VTT for the given subobject, including any /// secondary VTTs, secondary virtual pointers and virtual VTTs. void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); @@ -138,23 +134,22 @@ public: VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, bool GenerateDefinition); - // getVTTComponents - Returns a reference to the VTT components. + // \brief Returns a reference to the VTT components. const VTTComponentsVectorTy &getVTTComponents() const { return VTTComponents; } - // getVTTVTables - Returns a reference to the VTT vtables. + // \brief Returns a reference to the VTT vtables. const VTTVTablesVectorTy &getVTTVTables() const { return VTTVTables; } - /// getSubVTTIndicies - Returns a reference to the sub-VTT indices. + /// \brief Returns a reference to the sub-VTT indices. const llvm::DenseMap &getSubVTTIndicies() const { return SubVTTIndicies; } - /// getSecondaryVirtualPointerIndices - Returns a reference to the secondary - /// virtual pointer indices. + /// \brief Returns a reference to the secondary virtual pointer indices. const llvm::DenseMap & getSecondaryVirtualPointerIndices() const { return SecondaryVirtualPointerIndices; diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h index bcbe8754ea4a..4e451324d734 100644 --- a/include/clang/AST/VTableBuilder.h +++ b/include/clang/AST/VTableBuilder.h @@ -20,12 +20,13 @@ #include "clang/AST/RecordLayout.h" #include "clang/Basic/ABI.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/DenseSet.h" #include namespace clang { class CXXRecordDecl; -/// VTableComponent - Represents a single component in a vtable. +/// \brief Represents a single component in a vtable. class VTableComponent { public: enum Kind { @@ -35,15 +36,17 @@ public: CK_RTTI, CK_FunctionPointer, - /// CK_CompleteDtorPointer - A pointer to the complete destructor. + /// \brief A pointer to the complete destructor. CK_CompleteDtorPointer, - /// CK_DeletingDtorPointer - A pointer to the deleting destructor. + /// \brief A pointer to the deleting destructor. CK_DeletingDtorPointer, - /// CK_UnusedFunctionPointer - In some cases, a vtable function pointer - /// will end up never being called. Such vtable function pointers are - /// represented as a CK_UnusedFunctionPointer. + /// \brief An entry that is never used. + /// + /// In some cases, a vtable function pointer will end up never being + /// called. Such vtable function pointers are represented as a + /// CK_UnusedFunctionPointer. CK_UnusedFunctionPointer }; @@ -94,7 +97,7 @@ public: return VTableComponent(I); } - /// getKind - Get the kind of this vtable component. + /// \brief Get the kind of this vtable component. Kind getKind() const { return (Kind)(Value & 0x7); } @@ -189,7 +192,7 @@ private: /// The kind is stored in the lower 3 bits of the value. For offsets, we /// make use of the facts that classes can't be larger than 2^55 bytes, - /// so we store the offset in the lower part of the 61 bytes that remain. + /// so we store the offset in the lower part of the 61 bits that remain. /// (The reason that we're not simply using a PointerIntPair here is that we /// need the offsets to be 64-bit, even when on a 32-bit machine). int64_t Value; @@ -198,7 +201,6 @@ private: class VTableLayout { public: typedef std::pair VTableThunkTy; - typedef SmallVector ThunkInfoVectorTy; typedef const VTableComponent *vtable_component_iterator; typedef const VTableThunkTy *vtable_thunk_iterator; @@ -208,11 +210,11 @@ private: uint64_t NumVTableComponents; llvm::OwningArrayPtr VTableComponents; - /// VTableThunks - Contains thunks needed by vtables. + /// \brief Contains thunks needed by vtables, sorted by indices. uint64_t NumVTableThunks; llvm::OwningArrayPtr VTableThunks; - /// Address points - Address points for all vtables. + /// \brief Address points for all vtables. AddressPointsMapTy AddressPoints; bool IsMicrosoftABI; @@ -231,23 +233,21 @@ public: } vtable_component_iterator vtable_component_begin() const { - return VTableComponents.get(); + return VTableComponents.get(); } vtable_component_iterator vtable_component_end() const { - return VTableComponents.get()+NumVTableComponents; + return VTableComponents.get() + NumVTableComponents; } - uint64_t getNumVTableThunks() const { - return NumVTableThunks; - } + uint64_t getNumVTableThunks() const { return NumVTableThunks; } vtable_thunk_iterator vtable_thunk_begin() const { - return VTableThunks.get(); + return VTableThunks.get(); } vtable_thunk_iterator vtable_thunk_end() const { - return VTableThunks.get()+NumVTableThunks; + return VTableThunks.get() + NumVTableThunks; } uint64_t getAddressPoint(BaseSubobject Base) const { @@ -266,19 +266,45 @@ public: } }; -class VTableContext { - ASTContext &Context; - +class VTableContextBase { public: - typedef SmallVector, 1> - VTableThunksTy; typedef SmallVector ThunkInfoVectorTy; +protected: + typedef llvm::DenseMap ThunksMapTy; + + /// \brief Contains all thunks that a given method decl will need. + ThunksMapTy Thunks; + + /// Compute and store all vtable related information (vtable layout, vbase + /// offset offsets, thunks etc) for the given record decl. + virtual void computeVTableRelatedInformation(const CXXRecordDecl *RD) = 0; + + virtual ~VTableContextBase() {} + +public: + virtual const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { + const CXXMethodDecl *MD = cast(GD.getDecl()->getCanonicalDecl()); + computeVTableRelatedInformation(MD->getParent()); + + // This assumes that all the destructors present in the vtable + // use exactly the same set of thunks. + ThunksMapTy::const_iterator I = Thunks.find(MD); + if (I == Thunks.end()) { + // We did not find a thunk for this method. + return 0; + } + + return &I->second; + } +}; + +class ItaniumVTableContext : public VTableContextBase { private: bool IsMicrosoftABI; - /// MethodVTableIndices - Contains the index (relative to the vtable address - /// point) where the function pointer for a virtual function is stored. + /// \brief Contains the index (relative to the vtable address point) + /// where the function pointer for a virtual function is stored. typedef llvm::DenseMap MethodVTableIndicesTy; MethodVTableIndicesTy MethodVTableIndices; @@ -286,49 +312,25 @@ private: VTableLayoutMapTy; VTableLayoutMapTy VTableLayouts; - /// NumVirtualFunctionPointers - Contains the number of virtual function - /// pointers in the vtable for a given record decl. - llvm::DenseMap NumVirtualFunctionPointers; - typedef std::pair ClassPairTy; - /// VirtualBaseClassOffsetOffsets - Contains the vtable offset (relative to - /// the address point) in chars where the offsets for virtual bases of a class - /// are stored. + /// \brief vtable offsets for offsets of virtual bases of a class. + /// + /// Contains the vtable offset (relative to the address point) in chars + /// where the offsets for virtual bases of a class are stored. typedef llvm::DenseMap VirtualBaseClassOffsetOffsetsMapTy; VirtualBaseClassOffsetOffsetsMapTy VirtualBaseClassOffsetOffsets; - typedef llvm::DenseMap ThunksMapTy; - - /// Thunks - Contains all thunks that a given method decl will need. - ThunksMapTy Thunks; - - void ComputeMethodVTableIndices(const CXXRecordDecl *RD); - - /// ComputeVTableRelatedInformation - Compute and store all vtable related - /// information (vtable layout, vbase offset offsets, thunks etc) for the - /// given record decl. - void ComputeVTableRelatedInformation(const CXXRecordDecl *RD); - - /// ErrorUnsupported - Print out an error that the v-table layout code - /// doesn't support the particular C++ feature yet. - void ErrorUnsupported(StringRef Feature, SourceLocation Location); + void computeVTableRelatedInformation(const CXXRecordDecl *RD); public: - VTableContext(ASTContext &Context); - ~VTableContext(); - - bool isMicrosoftABI() const { - // FIXME: Currently, this method is only used in the VTableContext and - // VTableBuilder code which is ABI-specific. Probably we can remove it - // when we add a layer of abstraction for vtable generation. - return IsMicrosoftABI; - } + ItaniumVTableContext(ASTContext &Context); + ~ItaniumVTableContext(); const VTableLayout &getVTableLayout(const CXXRecordDecl *RD) { - ComputeVTableRelatedInformation(RD); + computeVTableRelatedInformation(RD); assert(VTableLayouts.count(RD) && "No layout for this record decl!"); return *VTableLayouts[RD]; @@ -340,36 +342,177 @@ public: bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass); - const ThunkInfoVectorTy *getThunkInfo(const CXXMethodDecl *MD) { - ComputeVTableRelatedInformation(MD->getParent()); + /// \brief Locate a virtual function in the vtable. + /// + /// Return the index (relative to the vtable address point) where the + /// function pointer for the given virtual function is stored. + uint64_t getMethodVTableIndex(GlobalDecl GD); - ThunksMapTy::const_iterator I = Thunks.find(MD); - if (I == Thunks.end()) { - // We did not find a thunk for this method. - return 0; - } + /// Return the offset in chars (relative to the vtable address point) where + /// the offset of the virtual base that contains the given base is stored, + /// otherwise, if no virtual base contains the given class, return 0. + /// + /// Base must be a virtual base class or an unambiguous base. + CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, + const CXXRecordDecl *VBase); +}; - return &I->second; +struct VFPtrInfo { + typedef SmallVector BasePath; + + // Don't pass the PathToMangle as it should be calculated later. + VFPtrInfo(CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr) + : VBTableIndex(0), LastVBase(0), VFPtrOffset(VFPtrOffset), + PathToBaseWithVFPtr(PathToBaseWithVFPtr), VFPtrFullOffset(VFPtrOffset) { } - /// getNumVirtualFunctionPointers - Return the number of virtual function - /// pointers in the vtable for a given record decl. - uint64_t getNumVirtualFunctionPointers(const CXXRecordDecl *RD); + // Don't pass the PathToMangle as it should be calculated later. + VFPtrInfo(uint64_t VBTableIndex, const CXXRecordDecl *LastVBase, + CharUnits VFPtrOffset, const BasePath &PathToBaseWithVFPtr, + CharUnits VFPtrFullOffset) + : VBTableIndex(VBTableIndex), LastVBase(LastVBase), + VFPtrOffset(VFPtrOffset), PathToBaseWithVFPtr(PathToBaseWithVFPtr), + VFPtrFullOffset(VFPtrFullOffset) { + assert(VBTableIndex && "The full constructor should only be used " + "for vfptrs in virtual bases"); + assert(LastVBase); + } - /// getMethodVTableIndex - Return the index (relative to the vtable address - /// point) where the function pointer for the given virtual function is - /// stored. - uint64_t getMethodVTableIndex(GlobalDecl GD); + /// If nonzero, holds the vbtable index of the virtual base with the vfptr. + uint64_t VBTableIndex; - /// getVirtualBaseOffsetOffset - Return the offset in chars (relative to the - /// vtable address point) where the offset of the virtual base that contains - /// the given base is stored, otherwise, if no virtual base contains the given - /// class, return 0. Base must be a virtual base class or an unambigious - /// base. - CharUnits getVirtualBaseOffsetOffset(const CXXRecordDecl *RD, - const CXXRecordDecl *VBase); + /// Stores the last vbase on the path from the complete type to the vfptr. + const CXXRecordDecl *LastVBase; + + /// This is the offset of the vfptr from the start of the last vbase, + /// or the complete type if there are no virtual bases. + CharUnits VFPtrOffset; + + /// This holds the base classes path from the complete type to the first base + /// with the given vfptr offset, in the base-to-derived order. + BasePath PathToBaseWithVFPtr; + + /// This holds the subset of records that need to be mangled into the vftable + /// symbol name in order to get a unique name, in the derived-to-base order. + BasePath PathToMangle; + + /// This is the full offset of the vfptr from the start of the complete type. + CharUnits VFPtrFullOffset; }; +class MicrosoftVTableContext : public VTableContextBase { +public: + struct MethodVFTableLocation { + /// If nonzero, holds the vbtable index of the virtual base with the vfptr. + uint64_t VBTableIndex; + + /// If nonnull, holds the last vbase which contains the vfptr that the + /// method definition is adjusted to. + const CXXRecordDecl *VBase; + + /// This is the offset of the vfptr from the start of the last vbase, or the + /// complete type if there are no virtual bases. + CharUnits VFPtrOffset; + + /// Method's index in the vftable. + uint64_t Index; + + MethodVFTableLocation() + : VBTableIndex(0), VBase(0), VFPtrOffset(CharUnits::Zero()), + Index(0) {} + + MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, + CharUnits VFPtrOffset, uint64_t Index) + : VBTableIndex(VBTableIndex), VBase(VBase), + VFPtrOffset(VFPtrOffset), Index(Index) {} + + bool operator<(const MethodVFTableLocation &other) const { + if (VBTableIndex != other.VBTableIndex) { + assert(VBase != other.VBase); + return VBTableIndex < other.VBTableIndex; + } + if (VFPtrOffset != other.VFPtrOffset) + return VFPtrOffset < other.VFPtrOffset; + if (Index != other.Index) + return Index < other.Index; + return false; + } + }; + + typedef SmallVector VFPtrListTy; + +private: + ASTContext &Context; + + typedef llvm::DenseMap + MethodVFTableLocationsTy; + MethodVFTableLocationsTy MethodVFTableLocations; + + typedef llvm::DenseMap + VFPtrLocationsMapTy; + VFPtrLocationsMapTy VFPtrLocations; + + typedef std::pair VFTableIdTy; + typedef llvm::DenseMap VFTableLayoutMapTy; + VFTableLayoutMapTy VFTableLayouts; + + typedef llvm::SmallSetVector BasesSetVectorTy; + void enumerateVFPtrs(const CXXRecordDecl *MostDerivedClass, + const ASTRecordLayout &MostDerivedClassLayout, + BaseSubobject Base, const CXXRecordDecl *LastVBase, + const VFPtrInfo::BasePath &PathFromCompleteClass, + BasesSetVectorTy &VisitedVBases, + MicrosoftVTableContext::VFPtrListTy &Result); + + void enumerateVFPtrs(const CXXRecordDecl *ForClass, + MicrosoftVTableContext::VFPtrListTy &Result); + + void computeVTableRelatedInformation(const CXXRecordDecl *RD); + + void dumpMethodLocations(const CXXRecordDecl *RD, + const MethodVFTableLocationsTy &NewMethods, + raw_ostream &); + + typedef std::pair ClassPairTy; + typedef llvm::DenseMap VBTableIndicesTy; + VBTableIndicesTy VBTableIndices; + llvm::DenseSet ComputedVBTableIndices; + + void computeVBTableRelatedInformation(const CXXRecordDecl *RD); + +public: + MicrosoftVTableContext(ASTContext &Context) : Context(Context) {} + + ~MicrosoftVTableContext() { llvm::DeleteContainerSeconds(VFTableLayouts); } + + const VFPtrListTy &getVFPtrOffsets(const CXXRecordDecl *RD); + + const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD, + CharUnits VFPtrOffset); + + const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD); + + const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) { + // Complete destructors don't have a slot in a vftable, so no thunks needed. + if (isa(GD.getDecl()) && + GD.getDtorType() == Dtor_Complete) + return 0; + return VTableContextBase::getThunkInfo(GD); + } + + /// \brief Returns the index of VBase in the vbtable of Derived. + /// VBase must be a morally virtual base of Derived. + /// The vbtable is an array of i32 offsets. The first entry is a self entry, + /// and the rest are offsets from the vbptr to virtual bases. + unsigned getVBTableIndex(const CXXRecordDecl *Derived, + const CXXRecordDecl *VBase) { + computeVBTableRelatedInformation(Derived); + ClassPairTy Pair(Derived, VBase); + assert(VBTableIndices.count(Pair) == 1 && + "VBase must be a vbase of Derived"); + return VBTableIndices[Pair]; + } +}; } #endif diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 870a39b39111..db0a83d72262 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -97,6 +97,11 @@ public: /// /// Optionally override to do per translation unit tasks. virtual void onStartOfTranslationUnit() {} + + /// \brief Called at the end of each translation unit. + /// + /// Optionally override to do per translation unit tasks. + virtual void onEndOfTranslationUnit() {} }; /// \brief Called when parsing is finished. Intended for testing only. @@ -131,6 +136,17 @@ public: MatchCallback *Action); /// @} + /// \brief Adds a matcher to execute when running over the AST. + /// + /// This is similar to \c addMatcher(), but it uses the dynamic interface. It + /// is more flexible, but the lost type information enables a caller to pass + /// a matcher that cannot match anything. + /// + /// \returns \c true if the matcher is a valid top-level matcher, \c false + /// otherwise. + bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, + MatchCallback *Action); + /// \brief Creates a clang ASTConsumer that finds all matches. clang::ASTConsumer *newASTConsumer(); @@ -147,6 +163,9 @@ public: ASTContext &Context); /// @} + /// \brief Finds all matches in the given AST. + void matchAST(ASTContext &Context); + /// \brief Registers a callback to notify the end of parsing. /// /// The provided closure is called after parsing is done, before the AST is @@ -157,7 +176,7 @@ public: private: /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called /// when it matches. - std::vector > + std::vector > MatcherCallbackPairs; /// \brief Called when parsing is done. diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index ab62dd0c3e81..0a3157dde817 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -45,6 +45,7 @@ #ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H +#include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" #include "clang/ASTMatchers/ASTMatchersMacros.h" @@ -85,6 +86,16 @@ public: } /// @} + /// \brief Type of mapping from binding identifiers to bound nodes. This type + /// is an associative container with a key type of \c std::string and a value + /// type of \c clang::ast_type_traits::DynTypedNode + typedef internal::BoundNodesMap::IDToNodeMap IDToNodeMap; + + /// \brief Retrieve mapping from binding identifiers to bound nodes. + const IDToNodeMap &getMap() const { + return MyBoundNodes.getMap(); + } + private: /// \brief Create BoundNodes from a pre-filled map of bindings. BoundNodes(internal::BoundNodesMap &MyBoundNodes) @@ -92,7 +103,7 @@ private: internal::BoundNodesMap MyBoundNodes; - friend class internal::BoundNodesTree; + friend class internal::BoundNodesTreeBuilder; }; /// \brief If the provided matcher matches a node, binds the node to \c ID. @@ -204,6 +215,28 @@ const internal::VariadicDynCastAllOfMatcher< Decl, ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; +/// \brief Matches declarator declarations (field, variable, function +/// and non-type template parameter declarations). +/// +/// Given +/// \code +/// class X { int y; }; +/// \endcode +/// declaratorDecl() +/// matches \c int y. +const internal::VariadicDynCastAllOfMatcher + declaratorDecl; + +/// \brief Matches parameter variable declarations. +/// +/// Given +/// \code +/// void f(int x); +/// \endcode +/// parmVarDecl() +/// matches \c int x. +const internal::VariadicDynCastAllOfMatcher parmVarDecl; + /// \brief Matches C++ access specifier declarations. /// /// Given @@ -219,6 +252,17 @@ const internal::VariadicDynCastAllOfMatcher< Decl, AccessSpecDecl> accessSpecDecl; +/// \brief Matches constructor initializers. +/// +/// Examples matches \c i(42). +/// \code +/// class C { +/// C() : i(42) {} +/// int i; +/// }; +/// \endcode +const internal::VariadicAllOfMatcher ctorInitializer; + /// \brief Matches public C++ declarations. /// /// Given @@ -281,12 +325,9 @@ AST_MATCHER(Decl, isPrivate) { /// matches the specialization \c A AST_MATCHER_P(ClassTemplateSpecializationDecl, hasAnyTemplateArgument, internal::Matcher, InnerMatcher) { - const TemplateArgumentList &List = Node.getTemplateArgs(); - for (unsigned i = 0; i < List.size(); ++i) { - if (InnerMatcher.matches(List.get(i), Finder, Builder)) - return true; - } - return false; + llvm::ArrayRef List = Node.getTemplateArgs().asArray(); + return matchesFirstInRange(InnerMatcher, List.begin(), List.end(), Finder, + Builder); } /// \brief Matches expressions that match InnerMatcher after any implicit casts @@ -520,6 +561,16 @@ const internal::VariadicDynCastAllOfMatcher< Decl, FunctionTemplateDecl> functionTemplateDecl; +/// \brief Matches friend declarations. +/// +/// Given +/// \code +/// class X { friend void foo(); }; +/// \endcode +/// friendDecl() +/// matches 'friend void foo()'. +const internal::VariadicDynCastAllOfMatcher friendDecl; + /// \brief Matches statements. /// /// Given @@ -607,6 +658,21 @@ const internal::VariadicDynCastAllOfMatcher initListExpr; /// matches \code using X::x \endcode const internal::VariadicDynCastAllOfMatcher usingDecl; +/// \brief Matches unresolved using value declarations. +/// +/// Given +/// \code +/// template +/// class C : private X { +/// using X::x; +/// }; +/// \endcode +/// unresolvedUsingValueDecl() +/// matches \code using X::x \endcode +const internal::VariadicDynCastAllOfMatcher< + Decl, + UnresolvedUsingValueDecl> unresolvedUsingValueDecl; + /// \brief Matches constructor call expressions (including implicit ones). /// /// Example matches string(ptr, n) and ptr within arguments of f @@ -621,6 +687,18 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CXXConstructExpr> constructExpr; +/// \brief Matches unresolved constructor call expressions. +/// +/// Example matches T(t) in return statement of f +/// (matcher = unresolvedConstructExpr()) +/// \code +/// template +/// void f(const T& t) { return T(t); } +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXUnresolvedConstructExpr> unresolvedConstructExpr; + /// \brief Matches implicit and explicit this expressions. /// /// Example matches the implicit this expression in "return i". @@ -894,6 +972,26 @@ const internal::VariadicDynCastAllOfMatcher switchStmt; /// matches 'case 42: break;' and 'default: break;'. const internal::VariadicDynCastAllOfMatcher switchCase; +/// \brief Matches case statements inside switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// caseStmt() +/// matches 'case 42: break;'. +const internal::VariadicDynCastAllOfMatcher caseStmt; + +/// \brief Matches default statements inside switch statements. +/// +/// Given +/// \code +/// switch(a) { case 42: break; default: break; } +/// \endcode +/// defaultStmt() +/// matches 'default: break;'. +const internal::VariadicDynCastAllOfMatcher defaultStmt; + /// \brief Matches compound statements. /// /// Example matches '{}' and '{{}}'in 'for (;;) {{}}' @@ -981,15 +1079,25 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CharacterLiteral> characterLiteral; -/// \brief Matches integer literals of all sizes / encodings. -/// -/// Not matching character-encoded integers such as L'a'. +/// \brief Matches integer literals of all sizes / encodings, e.g. +/// 1, 1L, 0x1 and 1U. /// -/// Example matches 1, 1L, 0x1, 1U +/// Does not match character-encoded integers such as L'a'. const internal::VariadicDynCastAllOfMatcher< Stmt, IntegerLiteral> integerLiteral; +/// \brief Matches float literals of all sizes / encodings, e.g. +/// 1.0, 1.0f, 1.0L and 1e10. +/// +/// Does not match implicit conversions such as +/// \code +/// float a = 10; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + FloatingLiteral> floatLiteral; + /// \brief Matches user defined literal operator call. /// /// Example match: "foo"_suffix @@ -1171,6 +1279,16 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CXXFunctionalCastExpr> functionalCastExpr; +/// \brief Matches functional cast expressions having N != 1 arguments +/// +/// Example: Matches Foo(bar, bar) +/// \code +/// Foo h = Foo(bar, bar); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + CXXTemporaryObjectExpr> temporaryObjectExpr; + /// \brief Matches \c QualTypes in the clang AST. const internal::VariadicAllOfMatcher qualType; @@ -1199,93 +1317,23 @@ const internal::VariadicAllOfMatcher typeLoc; /// \c b. /// /// Usable as: Any Matcher -template -internal::PolymorphicMatcherWithParam2 -eachOf(const M1 &P1, const M2 &P2) { - return internal::PolymorphicMatcherWithParam2(P1, P2); -} - -/// \brief Various overloads for the anyOf matcher. -/// @{ +const internal::VariadicOperatorMatcherFunc eachOf = { + internal::EachOfVariadicOperator +}; /// \brief Matches if any of the given matchers matches. /// /// Usable as: Any Matcher -template -internal::PolymorphicMatcherWithParam2 -anyOf(const M1 &P1, const M2 &P2) { - return internal::PolymorphicMatcherWithParam2(P1, P2); -} -template -internal::PolymorphicMatcherWithParam2 > -anyOf(const M1 &P1, const M2 &P2, const M3 &P3) { - return anyOf(P1, anyOf(P2, P3)); -} -template -internal::PolymorphicMatcherWithParam2 > > -anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { - return anyOf(P1, anyOf(P2, anyOf(P3, P4))); -} -template -internal::PolymorphicMatcherWithParam2 > > > -anyOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { - return anyOf(P1, anyOf(P2, anyOf(P3, anyOf(P4, P5)))); -} - -/// @} - -/// \brief Various overloads for the allOf matcher. -/// @{ +const internal::VariadicOperatorMatcherFunc anyOf = { + internal::AnyOfVariadicOperator +}; /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher -template -internal::PolymorphicMatcherWithParam2 -allOf(const M1 &P1, const M2 &P2) { - return internal::PolymorphicMatcherWithParam2( - P1, P2); -} -template -internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M1, - internal::PolymorphicMatcherWithParam2 > -allOf(const M1 &P1, const M2 &P2, const M3 &P3) { - return allOf(P1, allOf(P2, P3)); -} -template -internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M1, - internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M2, internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M3, M4> > > -allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) { - return allOf(P1, allOf(P2, P3, P4)); -} -template -internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M1, - internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M2, - internal::PolymorphicMatcherWithParam2< - internal::AllOfMatcher, M3, - internal::PolymorphicMatcherWithParam2 > > > -allOf(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) { - return allOf(P1, allOf(P2, P3, P4, P5)); -} - -/// @} +const internal::VariadicOperatorMatcherFunc allOf = { + internal::AllOfVariadicOperator +}; /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) /// @@ -1412,10 +1460,13 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { /// /// Usable as: Matcher, Matcher inline internal::PolymorphicMatcherWithParam1< - internal::HasOverloadedOperatorNameMatcher, StringRef> + internal::HasOverloadedOperatorNameMatcher, StringRef, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)> hasOverloadedOperatorName(const StringRef Name) { return internal::PolymorphicMatcherWithParam1< - internal::HasOverloadedOperatorNameMatcher, StringRef>(Name); + internal::HasOverloadedOperatorNameMatcher, StringRef, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, CXXMethodDecl)>( + Name); } /// \brief Matches C++ classes that are directly or indirectly derived from @@ -1445,24 +1496,25 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, } /// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). -inline internal::Matcher isDerivedFrom(StringRef BaseName) { +AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) { assert(!BaseName.empty()); - return isDerivedFrom(hasName(BaseName)); + return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); } /// \brief Similar to \c isDerivedFrom(), but also matches classes that directly /// match \c Base. -inline internal::Matcher isSameOrDerivedFrom( - internal::Matcher Base) { - return anyOf(Base, isDerivedFrom(Base)); +AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, + internal::Matcher, Base, 0) { + return Matcher(anyOf(Base, isDerivedFrom(Base))) + .matches(Node, Finder, Builder); } /// \brief Overloaded method as shortcut for /// \c isSameOrDerivedFrom(hasName(...)). -inline internal::Matcher isSameOrDerivedFrom( - StringRef BaseName) { +AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName, + 1) { assert(!BaseName.empty()); - return isSameOrDerivedFrom(hasName(BaseName)); + return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); } /// \brief Matches the first method of a class or struct that satisfies \c @@ -1478,12 +1530,8 @@ inline internal::Matcher isSameOrDerivedFrom( /// but not \c B. AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher, InnerMatcher) { - for (CXXRecordDecl::method_iterator I = Node.method_begin(), - E = Node.method_end(); - I != E; ++I) - if (InnerMatcher.matches(**I, Finder, Builder)) - return true; - return false; + return matchesFirstInPointerRange(InnerMatcher, Node.method_begin(), + Node.method_end(), Finder, Builder); } /// \brief Matches AST nodes that have child AST nodes that match the @@ -1499,12 +1547,8 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher, /// ChildT must be an AST base type. /// /// Usable as: Any Matcher -template -internal::ArgumentAdaptingMatcher has( - const internal::Matcher &ChildMatcher) { - return internal::ArgumentAdaptingMatcher(ChildMatcher); -} +const internal::ArgumentAdaptingMatcherFunc +LLVM_ATTRIBUTE_UNUSED has = {}; /// \brief Matches AST nodes that have descendant AST nodes that match the /// provided matcher. @@ -1520,13 +1564,8 @@ internal::ArgumentAdaptingMatcher has( /// DescendantT must be an AST base type. /// /// Usable as: Any Matcher -template -internal::ArgumentAdaptingMatcher -hasDescendant(const internal::Matcher &DescendantMatcher) { - return internal::ArgumentAdaptingMatcher< - internal::HasDescendantMatcher, - DescendantT>(DescendantMatcher); -} +const internal::ArgumentAdaptingMatcherFunc +LLVM_ATTRIBUTE_UNUSED hasDescendant = {}; /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. @@ -1544,13 +1583,8 @@ hasDescendant(const internal::Matcher &DescendantMatcher) { /// matches instead of only on the first one. /// /// Usable as: Any Matcher -template -internal::ArgumentAdaptingMatcher forEach( - const internal::Matcher &ChildMatcher) { - return internal::ArgumentAdaptingMatcher< - internal::ForEachMatcher, - ChildT>(ChildMatcher); -} +const internal::ArgumentAdaptingMatcherFunc +LLVM_ATTRIBUTE_UNUSED forEach = {}; /// \brief Matches AST nodes that have descendant AST nodes that match the /// provided matcher. @@ -1576,15 +1610,8 @@ internal::ArgumentAdaptingMatcher forEach( /// \endcode /// /// Usable as: Any Matcher -template -internal::ArgumentAdaptingMatcher -forEachDescendant( - const internal::Matcher &DescendantMatcher) { - return internal::ArgumentAdaptingMatcher< - internal::ForEachDescendantMatcher, - DescendantT>(DescendantMatcher); -} +const internal::ArgumentAdaptingMatcherFunc +LLVM_ATTRIBUTE_UNUSED forEachDescendant = {}; /// \brief Matches if the node or any descendant matches. /// @@ -1602,10 +1629,7 @@ forEachDescendant( /// /// Usable as: Any Matcher template -internal::PolymorphicMatcherWithParam2< - internal::EachOfMatcher, internal::Matcher, - internal::ArgumentAdaptingMatcher > -findAll(const internal::Matcher &Matcher) { +internal::Matcher findAll(const internal::Matcher &Matcher) { return eachOf(Matcher, forEachDescendant(Matcher)); } @@ -1619,13 +1643,9 @@ findAll(const internal::Matcher &Matcher) { /// \c compoundStmt(hasParent(ifStmt())) matches "{ int x = 43; }". /// /// Usable as: Any Matcher -template -internal::ArgumentAdaptingMatcher -hasParent(const internal::Matcher &ParentMatcher) { - return internal::ArgumentAdaptingMatcher< - internal::HasParentMatcher, - ParentT>(ParentMatcher); -} +const internal::ArgumentAdaptingMatcherFunc< + internal::HasParentMatcher, internal::TypeList, + internal::TypeList > LLVM_ATTRIBUTE_UNUSED hasParent = {}; /// \brief Matches AST nodes that have an ancestor that matches the provided /// matcher. @@ -1638,13 +1658,9 @@ hasParent(const internal::Matcher &ParentMatcher) { /// \c expr(integerLiteral(hasAncestor(ifStmt()))) matches \c 42, but not 43. /// /// Usable as: Any Matcher -template -internal::ArgumentAdaptingMatcher -hasAncestor(const internal::Matcher &AncestorMatcher) { - return internal::ArgumentAdaptingMatcher< - internal::HasAncestorMatcher, - AncestorT>(AncestorMatcher); -} +const internal::ArgumentAdaptingMatcherFunc< + internal::HasAncestorMatcher, internal::TypeList, + internal::TypeList > LLVM_ATTRIBUTE_UNUSED hasAncestor = {}; /// \brief Matches if the provided matcher does not match. /// @@ -1662,22 +1678,31 @@ unless(const M &InnerMatcher) { internal::NotMatcher, M>(InnerMatcher); } -/// \brief Matches a type if the declaration of the type matches the given -/// matcher. +/// \brief Matches a node if the declaration associated with that node +/// matches the given matcher. +/// +/// The associated declaration is: +/// - for type nodes, the declaration of the underlying type +/// - for CallExpr, the declaration of the callee +/// - for MemberExpr, the declaration of the referenced member +/// - for CXXConstructExpr, the declaration of the constructor /// -/// In addition to being usable as Matcher, also usable as -/// Matcher for any T supporting the getDecl() member function. e.g. various -/// subtypes of clang::Type. +/// Also usable as Matcher for any T supporting the getDecl() member +/// function. e.g. various subtypes of clang::Type and various expressions. /// -/// Usable as: Matcher, Matcher, Matcher, -/// Matcher, Matcher, -/// Matcher -inline internal::PolymorphicMatcherWithParam1< internal::HasDeclarationMatcher, - internal::Matcher > - hasDeclaration(const internal::Matcher &InnerMatcher) { +/// Usable as: Matcher, Matcher, +/// Matcher, Matcher, Matcher, +/// Matcher, Matcher, Matcher, +/// Matcher, Matcher, +/// Matcher, Matcher, +/// Matcher, Matcher +inline internal::PolymorphicMatcherWithParam1< + internal::HasDeclarationMatcher, internal::Matcher, + void(internal::HasDeclarationSupportedTypes)> +hasDeclaration(const internal::Matcher &InnerMatcher) { return internal::PolymorphicMatcherWithParam1< - internal::HasDeclarationMatcher, - internal::Matcher >(InnerMatcher); + internal::HasDeclarationMatcher, internal::Matcher, + void(internal::HasDeclarationSupportedTypes)>(InnerMatcher); } /// \brief Matches on the implicit object argument of a member call expression. @@ -1728,9 +1753,9 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher, /// class Y { public: void x(); }; /// void z() { Y y; y.x(); /// \endcode -inline internal::Matcher callee( - const internal::Matcher &InnerMatcher) { - return callExpr(hasDeclaration(InnerMatcher)); +AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher, InnerMatcher, + 1) { + return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder); } /// \brief Matches if the expression's or declaration's type matches a type @@ -1742,11 +1767,9 @@ inline internal::Matcher callee( /// class X {}; /// void y(X &x) { x; X z; } /// \endcode -AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, - InnerMatcher) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || - llvm::is_base_of::value), - instantiated_with_wrong_types); +AST_POLYMORPHIC_MATCHER_P_OVERLOAD( + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl), + internal::Matcher, InnerMatcher, 0) { return InnerMatcher.matches(Node.getType(), Finder, Builder); } @@ -1767,11 +1790,27 @@ AST_POLYMORPHIC_MATCHER_P(hasType, internal::Matcher, /// \endcode /// /// Usable as: Matcher, Matcher -inline internal::PolymorphicMatcherWithParam1< - internal::matcher_hasType0Matcher, - internal::Matcher > -hasType(const internal::Matcher &InnerMatcher) { - return hasType(qualType(hasDeclaration(InnerMatcher))); +AST_POLYMORPHIC_MATCHER_P_OVERLOAD( + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES_2(Expr, ValueDecl), + internal::Matcher, InnerMatcher, 1) { + return qualType(hasDeclaration(InnerMatcher)) + .matches(Node.getType(), Finder, Builder); +} + +/// \brief Matches if the type location of the declarator decl's type matches +/// the inner matcher. +/// +/// Given +/// \code +/// int x; +/// \endcode +/// declaratorDecl(hasTypeLoc(loc(asString("int")))) +/// matches int x +AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher, Inner) { + if (!Node.getTypeSourceInfo()) + // This happens for example for implicit destructors. + return false; + return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder); } /// \brief Matches if the matched type is represented by the given string. @@ -1804,9 +1843,10 @@ AST_MATCHER_P( } /// \brief Overloaded to match the pointee type's declaration. -inline internal::Matcher pointsTo( - const internal::Matcher &InnerMatcher) { - return pointsTo(qualType(hasDeclaration(InnerMatcher))); +AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher, + InnerMatcher, 1) { + return pointsTo(qualType(hasDeclaration(InnerMatcher))) + .matches(Node, Finder, Builder); } /// \brief Matches if the matched type is a reference type and the referenced @@ -1841,13 +1881,16 @@ AST_MATCHER_P(QualType, references, internal::Matcher, /// varDecl(hasType(qualType(hasCanonicalType(referenceType())))))) does. AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher, InnerMatcher) { + if (Node.isNull()) + return false; return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); } /// \brief Overloaded to match the referenced type's declaration. -inline internal::Matcher references( - const internal::Matcher &InnerMatcher) { - return references(qualType(hasDeclaration(InnerMatcher))); +AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher, + InnerMatcher, 1) { + return references(qualType(hasDeclaration(InnerMatcher))) + .matches(Node, Finder, Builder); } AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, @@ -1859,17 +1902,19 @@ AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, /// \brief Matches if the expression's type either matches the specified /// matcher, or is a pointer to a type that matches the InnerMatcher. -inline internal::Matcher thisPointerType( - const internal::Matcher &InnerMatcher) { +AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, + internal::Matcher, InnerMatcher, 0) { return onImplicitObjectArgument( - anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))) + .matches(Node, Finder, Builder); } /// \brief Overloaded to match the type's declaration. -inline internal::Matcher thisPointerType( - const internal::Matcher &InnerMatcher) { +AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, + internal::Matcher, InnerMatcher, 1) { return onImplicitObjectArgument( - anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))); + anyOf(hasType(InnerMatcher), hasType(pointsTo(InnerMatcher)))) + .matches(Node, Finder, Builder); } /// \brief Matches a DeclRefExpr that refers to a declaration that matches the @@ -1953,11 +1998,9 @@ AST_MATCHER_P( /// void f(int x, int y); /// f(0, 0); /// \endcode -AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || - llvm::is_base_of::value), - instantiated_with_wrong_types); +AST_POLYMORPHIC_MATCHER_P(argumentCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES_2( + CallExpr, CXXConstructExpr), + unsigned, N) { return Node.getNumArgs() == N; } @@ -1970,11 +2013,9 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, unsigned, N) { /// void x(int) { int y; x(y); } /// \endcode AST_POLYMORPHIC_MATCHER_P2( - hasArgument, unsigned, N, internal::Matcher, InnerMatcher) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || - llvm::is_base_of::value), - instantiated_with_wrong_types); + hasArgument, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(CallExpr, CXXConstructExpr), + unsigned, N, internal::Matcher, InnerMatcher) { return (N < Node.getNumArgs() && InnerMatcher.matches( *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); @@ -2037,13 +2078,8 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, /// record matches Foo, hasAnyConstructorInitializer matches foo_(1) AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, internal::Matcher, InnerMatcher) { - for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(); - I != Node.init_end(); ++I) { - if (InnerMatcher.matches(**I, Finder, Builder)) { - return true; - } - } - return false; + return matchesFirstInPointerRange(InnerMatcher, Node.init_begin(), + Node.init_end(), Finder, Builder); } /// \brief Matches the field declaration of a constructor initializer. @@ -2086,7 +2122,7 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer, InnerMatcher.matches(*NodeAsExpr, Finder, Builder)); } -/// \brief Matches a contructor initializer if it is explicitly written in +/// \brief Matches a constructor initializer if it is explicitly written in /// code (as opposed to implicitly added by the compiler). /// /// Given @@ -2120,15 +2156,19 @@ AST_MATCHER(CXXConstructorDecl, isImplicit) { /// matches x(1, y, 42) /// with hasAnyArgument(...) /// matching y -AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, internal::Matcher, - InnerMatcher) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value || - llvm::is_base_of::value), - instantiated_with_wrong_types); +/// +/// FIXME: Currently this will ignore parentheses and implicit casts on +/// the argument before applying the inner matcher. We'll want to remove +/// this to allow for greater control by the user once \c ignoreImplicit() +/// has been implemented. +AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2( + CallExpr, CXXConstructExpr), + internal::Matcher, InnerMatcher) { for (unsigned I = 0; I < Node.getNumArgs(); ++I) { - if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), - Finder, Builder)) { + BoundNodesTreeBuilder Result(*Builder); + if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder, + &Result)) { + *Builder = Result; return true; } } @@ -2167,12 +2207,8 @@ AST_MATCHER_P2(FunctionDecl, hasParameter, /// matching int y AST_MATCHER_P(FunctionDecl, hasAnyParameter, internal::Matcher, InnerMatcher) { - for (unsigned I = 0; I < Node.getNumParams(); ++I) { - if (InnerMatcher.matches(*Node.getParamDecl(I), Finder, Builder)) { - return true; - } - } - return false; + return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(), + Node.param_end(), Finder, Builder); } /// \brief Matches \c FunctionDecls that have a specific parameter count. @@ -2222,27 +2258,68 @@ AST_MATCHER(FunctionDecl, isExternC) { /// \code /// if (true) {} /// \endcode -AST_POLYMORPHIC_MATCHER_P(hasCondition, internal::Matcher, - InnerMatcher) { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value), - has_condition_requires_if_statement_conditional_operator_or_loop); +AST_POLYMORPHIC_MATCHER_P( + hasCondition, AST_POLYMORPHIC_SUPPORTED_TYPES_5( + IfStmt, ForStmt, WhileStmt, DoStmt, ConditionalOperator), + internal::Matcher, InnerMatcher) { const Expr *const Condition = Node.getCond(); return (Condition != NULL && InnerMatcher.matches(*Condition, Finder, Builder)); } +namespace internal { +struct NotEqualsBoundNodePredicate { + bool operator()(const internal::BoundNodesMap &Nodes) const { + return Nodes.getNode(ID) != Node; + } + std::string ID; + ast_type_traits::DynTypedNode Node; +}; +} // namespace internal + +/// \brief Matches if a node equals a previously bound node. +/// +/// Matches a node if it equals the node previously bound to \p ID. +/// +/// Given +/// \code +/// class X { int a; int b; }; +/// \endcode +/// recordDecl( +/// has(fieldDecl(hasName("a"), hasType(type().bind("t")))), +/// has(fieldDecl(hasName("b"), hasType(type(equalsBoundNode("t")))))) +/// matches the class \c X, as \c a and \c b have the same type. +/// +/// Note that when multiple matches are involved via \c forEach* matchers, +/// \c equalsBoundNodes acts as a filter. +/// For example: +/// compoundStmt( +/// forEachDescendant(varDecl().bind("d")), +/// forEachDescendant(declRefExpr(to(decl(equalsBoundNode("d")))))) +/// will trigger a match for each combination of variable declaration +/// and reference to that variable declaration within a compound statement. +AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, AST_POLYMORPHIC_SUPPORTED_TYPES_4( + Stmt, Decl, Type, QualType), + std::string, ID) { + // FIXME: Figure out whether it makes sense to allow this + // on any other node types. + // For *Loc it probably does not make sense, as those seem + // unique. For NestedNameSepcifier it might make sense, as + // those also have pointer identity, but I'm not sure whether + // they're ever reused. + internal::NotEqualsBoundNodePredicate Predicate; + Predicate.ID = ID; + Predicate.Node = ast_type_traits::DynTypedNode::create(Node); + return Builder->removeBindings(Predicate); +} + /// \brief Matches the condition variable statement in an if statement. /// /// Given /// \code /// if (A* a = GetAPointer()) {} /// \endcode -/// hasConditionVariableStatment(...) +/// hasConditionVariableStatement(...) /// matches 'A* a = GetAPointer()'. AST_MATCHER_P(IfStmt, hasConditionVariableStatement, internal::Matcher, InnerMatcher) { @@ -2296,13 +2373,9 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, /// matches 'for (;;) {}' /// with compoundStmt() /// matching '{}' -AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher, - InnerMatcher) { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value), - has_body_requires_for_while_or_do_statement); +AST_POLYMORPHIC_MATCHER_P( + hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES_3(DoStmt, ForStmt, WhileStmt), + internal::Matcher, InnerMatcher) { const Stmt *const Statement = Node.getBody(); return (Statement != NULL && InnerMatcher.matches(*Statement, Finder, Builder)); @@ -2321,12 +2394,8 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, internal::Matcher, /// matching '{}' AST_MATCHER_P(CompoundStmt, hasAnySubstatement, internal::Matcher, InnerMatcher) { - for (CompoundStmt::const_body_iterator It = Node.body_begin(); - It != Node.body_end(); - ++It) { - if (InnerMatcher.matches(**It, Finder, Builder)) return true; - } - return false; + return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(), + Node.body_end(), Finder, Builder); } /// \brief Checks that a compound statement contains a specific number of @@ -2367,11 +2436,9 @@ equals(const ValueT &Value) { /// \code /// !(a || b) /// \endcode -AST_POLYMORPHIC_MATCHER_P(hasOperatorName, std::string, Name) { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of::value) || - (llvm::is_base_of::value), - has_condition_requires_if_statement_or_conditional_operator); +AST_POLYMORPHIC_MATCHER_P(hasOperatorName, AST_POLYMORPHIC_SUPPORTED_TYPES_2( + BinaryOperator, UnaryOperator), + std::string, Name) { return Name == Node.getOpcodeStr(Node.getOpcode()); } @@ -2493,12 +2560,8 @@ AST_MATCHER_P(ConditionalOperator, hasFalseExpression, /// \endcode /// /// Usable as: Matcher, Matcher, Matcher -AST_POLYMORPHIC_MATCHER(isDefinition) { - TOOLING_COMPILE_ASSERT( - (llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value), - is_definition_requires_isThisDeclarationADefinition_method); +AST_POLYMORPHIC_MATCHER(isDefinition, AST_POLYMORPHIC_SUPPORTED_TYPES_3( + TagDecl, VarDecl, FunctionDecl)) { return Node.isThisDeclarationADefinition(); } @@ -2540,6 +2603,21 @@ AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } +/// \brief Matches if the given method declaration is const. +/// +/// Given +/// \code +/// struct A { +/// void foo() const; +/// void bar(); +/// }; +/// \endcode +/// +/// methodDecl(isConst()) matches A::foo() but not A::bar() +AST_MATCHER(CXXMethodDecl, isConst) { + return Node.isConst(); +} + /// \brief Matches if the given method declaration overrides another method. /// /// Given @@ -2672,12 +2750,8 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression, /// matches \code using X::b \endcode AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, internal::Matcher, InnerMatcher) { - for (UsingDecl::shadow_iterator II = Node.shadow_begin(); - II != Node.shadow_end(); ++II) { - if (InnerMatcher.matches(**II, Finder, Builder)) - return true; - } - return false; + return matchesFirstInPointerRange(InnerMatcher, Node.shadow_begin(), + Node.shadow_end(), Finder, Builder); } /// \brief Matches a using shadow declaration where the target declaration is @@ -2720,11 +2794,9 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, /// does not match, as X is an explicit template specialization. /// /// Usable as: Matcher, Matcher, Matcher -AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value), - requires_getTemplateSpecializationKind_method); +AST_POLYMORPHIC_MATCHER( + isTemplateInstantiation, + AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) { return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || Node.getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition); @@ -2742,11 +2814,9 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation) { /// matches the specialization A(). /// /// Usable as: Matcher, Matcher, Matcher -AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization) { - TOOLING_COMPILE_ASSERT((llvm::is_base_of::value) || - (llvm::is_base_of::value) || - (llvm::is_base_of::value), - requires_getTemplateSpecializationKind_method); +AST_POLYMORPHIC_MATCHER( + isExplicitTemplateSpecialization, + AST_POLYMORPHIC_SUPPORTED_TYPES_3(FunctionDecl, VarDecl, CXXRecordDecl)) { return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); } @@ -2807,7 +2877,9 @@ AST_TYPE_MATCHER(ComplexType, complexType); /// matches "int b[7]" /// /// Usable as: Matcher, Matcher -AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement); +AST_TYPELOC_TRAVERSE_MATCHER( + hasElementType, getElement, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(ArrayType, ComplexType)); /// \brief Matches C arrays with a specified constant size. /// @@ -2914,7 +2986,8 @@ AST_TYPE_MATCHER(AtomicType, atomicType); /// matches "_Atomic(int) i" /// /// Usable as: Matcher -AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue); +AST_TYPELOC_TRAVERSE_MATCHER(hasValueType, getValue, + AST_POLYMORPHIC_SUPPORTED_TYPES_1(AtomicType)); /// \brief Matches types nodes representing C++11 auto types. /// @@ -2942,7 +3015,8 @@ AST_TYPE_MATCHER(AutoType, autoType); /// matches "auto a" /// /// Usable as: Matcher -AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType); +AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, + AST_POLYMORPHIC_SUPPORTED_TYPES_1(AutoType)); /// \brief Matches \c FunctionType nodes. /// @@ -2979,7 +3053,8 @@ AST_TYPE_MATCHER(ParenType, parenType); /// \c ptr_to_func but not \c ptr_to_array. /// /// Usable as: Matcher -AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType); +AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType, + AST_POLYMORPHIC_SUPPORTED_TYPES_1(ParenType)); /// \brief Matches block pointer types, i.e. types syntactically represented as /// "void (^)(int)". @@ -3073,7 +3148,10 @@ AST_TYPE_MATCHER(RValueReferenceType, rValueReferenceType); /// /// Usable as: Matcher, Matcher, /// Matcher, Matcher -AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee); +AST_TYPELOC_TRAVERSE_MATCHER( + pointee, getPointee, + AST_POLYMORPHIC_SUPPORTED_TYPES_4(BlockPointerType, MemberPointerType, + PointerType, ReferenceType)); /// \brief Matches typedef types. /// @@ -3100,6 +3178,16 @@ AST_TYPE_MATCHER(TypedefType, typedefType); /// instantiation in \c A and the type of the variable declaration in \c B. AST_TYPE_MATCHER(TemplateSpecializationType, templateSpecializationType); +/// \brief Matches types nodes representing unary type transformations. +/// +/// Given: +/// \code +/// typedef __underlying_type(T) type; +/// \endcode +/// unaryTransformType() +/// matches "__underlying_type(T)" +AST_TYPE_MATCHER(UnaryTransformType, unaryTransformType); + /// \brief Matches record types (e.g. structs, classes). /// /// Given @@ -3331,6 +3419,80 @@ AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, Stmt*, Other, 1) { /// @} +/// \brief Matches each case or default statement belonging to the given switch +/// statement. This matcher may produce multiple matches. +/// +/// Given +/// \code +/// switch (1) { case 1: case 2: default: switch (2) { case 3: case 4: ; } } +/// \endcode +/// switchStmt(forEachSwitchCase(caseStmt().bind("c"))).bind("s") +/// matches four times, with "c" binding each of "case 1:", "case 2:", +/// "case 3:" and "case 4:", and "s" respectively binding "switch (1)", +/// "switch (1)", "switch (2)" and "switch (2)". +AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher, + InnerMatcher) { + BoundNodesTreeBuilder Result; + // FIXME: getSwitchCaseList() does not necessarily guarantee a stable + // iteration order. We should use the more general iterating matchers once + // they are capable of expressing this matcher (for example, it should ignore + // case statements belonging to nested switch statements). + bool Matched = false; + for (const SwitchCase *SC = Node.getSwitchCaseList(); SC; + SC = SC->getNextSwitchCase()) { + BoundNodesTreeBuilder CaseBuilder(*Builder); + bool CaseMatched = InnerMatcher.matches(*SC, Finder, &CaseBuilder); + if (CaseMatched) { + Matched = true; + Result.addMatch(CaseBuilder); + } + } + *Builder = Result; + return Matched; +} + +/// \brief Matches each constructor initializer in a constructor definition. +/// +/// Given +/// \code +/// class A { A() : i(42), j(42) {} int i; int j; }; +/// \endcode +/// constructorDecl(forEachConstructorInitializer(forField(decl().bind("x")))) +/// will trigger two matches, binding for 'i' and 'j' respectively. +AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer, + internal::Matcher, InnerMatcher) { + BoundNodesTreeBuilder Result; + bool Matched = false; + for (CXXConstructorDecl::init_const_iterator I = Node.init_begin(), + E = Node.init_end(); + I != E; ++I) { + BoundNodesTreeBuilder InitBuilder(*Builder); + if (InnerMatcher.matches(**I, Finder, &InitBuilder)) { + Matched = true; + Result.addMatch(InitBuilder); + } + } + *Builder = Result; + return Matched; +} + +/// \brief If the given case statement does not use the GNU case range +/// extension, matches the constant given in the statement. +/// +/// Given +/// \code +/// switch (1) { case 1: case 1+1: case 3 ... 4: ; } +/// \endcode +/// caseStmt(hasCaseConstant(integerLiteral())) +/// matches "case 1:" +AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher, + InnerMatcher) { + if (Node.getRHS()) + return false; + + return InnerMatcher.matches(*Node.getLHS(), Finder, Builder); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 30691ad8f912..69cee2eb5dfd 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -36,12 +36,13 @@ #define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H #include "clang/AST/ASTTypeTraits.h" -#include "clang/AST/DeclCXX.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" -#include "clang/AST/StmtCXX.h" #include "clang/AST/Stmt.h" +#include "clang/AST/StmtCXX.h" #include "clang/AST/Type.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/VariadicFunction.h" #include "llvm/Support/type_traits.h" #include @@ -60,7 +61,6 @@ class BoundNodes; namespace internal { -class BoundNodesTreeBuilder; /// \brief Internal version of BoundNodes. Holds all the bound nodes. class BoundNodesMap { public: @@ -71,9 +71,6 @@ public: void addNode(StringRef ID, const T* Node) { NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); } - void addNode(StringRef ID, ast_type_traits::DynTypedNode Node) { - NodeMap[ID] = Node; - } /// \brief Returns the AST node bound to \c ID. /// @@ -88,29 +85,39 @@ public: return It->second.get(); } - /// \brief Copies all ID/Node pairs to BoundNodesTreeBuilder \c Builder. - void copyTo(BoundNodesTreeBuilder *Builder) const; + ast_type_traits::DynTypedNode getNode(StringRef ID) const { + IDToNodeMap::const_iterator It = NodeMap.find(ID); + if (It == NodeMap.end()) { + return ast_type_traits::DynTypedNode(); + } + return It->second; + } - /// \brief Copies all ID/Node pairs to BoundNodesMap \c Other. - void copyTo(BoundNodesMap *Other) const; + /// \brief Imposes an order on BoundNodesMaps. + bool operator<(const BoundNodesMap &Other) const { + return NodeMap < Other.NodeMap; + } -private: /// \brief A map from IDs to the bound nodes. + /// + /// Note that we're using std::map here, as for memoization: + /// - we need a comparison operator + /// - we need an assignment operator typedef std::map IDToNodeMap; + const IDToNodeMap &getMap() const { + return NodeMap; + } + +private: IDToNodeMap NodeMap; }; -/// \brief A tree of bound nodes in match results. -/// -/// If a match can contain multiple matches on the same node with different -/// matching subexpressions, BoundNodesTree contains a branch for each of -/// those matching subexpressions. +/// \brief Creates BoundNodesTree objects. /// -/// BoundNodesTree's are created during the matching process; when a match -/// is found, we iterate over the tree and create a BoundNodes object containing -/// the union of all bound nodes on the path from the root to a each leaf. -class BoundNodesTree { +/// The tree builder is used during the matching process to insert the bound +/// nodes from the Id matcher. +class BoundNodesTreeBuilder { public: /// \brief A visitor interface to visit all BoundNodes results for a /// BoundNodesTree. @@ -124,63 +131,36 @@ public: virtual void visitMatch(const BoundNodes& BoundNodesView) = 0; }; - BoundNodesTree(); - - /// \brief Create a BoundNodesTree from pre-filled maps of bindings. - BoundNodesTree(const BoundNodesMap& Bindings, - const std::vector RecursiveBindings); + /// \brief Add a binding from an id to a node. + template void setBinding(const std::string &Id, const T *Node) { + if (Bindings.empty()) + Bindings.push_back(BoundNodesMap()); + for (unsigned i = 0, e = Bindings.size(); i != e; ++i) + Bindings[i].addNode(Id, Node); + } - /// \brief Adds all bound nodes to \c Builder. - void copyTo(BoundNodesTreeBuilder* Builder) const; + /// \brief Adds a branch in the tree. + void addMatch(const BoundNodesTreeBuilder &Bindings); /// \brief Visits all matches that this BoundNodesTree represents. /// /// The ownership of 'ResultVisitor' remains at the caller. void visitMatches(Visitor* ResultVisitor); -private: - void visitMatchesRecursively( - Visitor* ResultVistior, - const BoundNodesMap& AggregatedBindings); - - // FIXME: Find out whether we want to use different data structures here - - // first benchmarks indicate that it doesn't matter though. - - BoundNodesMap Bindings; - - std::vector RecursiveBindings; -}; - -/// \brief Creates BoundNodesTree objects. -/// -/// The tree builder is used during the matching process to insert the bound -/// nodes from the Id matcher. -class BoundNodesTreeBuilder { -public: - BoundNodesTreeBuilder(); - - /// \brief Add a binding from an id to a node. - template - void setBinding(const std::string &Id, const T *Node) { - Bindings.addNode(Id, Node); - } - void setBinding(const std::string &Id, ast_type_traits::DynTypedNode Node) { - Bindings.addNode(Id, Node); + template + bool removeBindings(const ExcludePredicate &Predicate) { + Bindings.erase(std::remove_if(Bindings.begin(), Bindings.end(), Predicate), + Bindings.end()); + return !Bindings.empty(); } - /// \brief Adds a branch in the tree. - void addMatch(const BoundNodesTree& Bindings); - - /// \brief Returns a BoundNodes object containing all current bindings. - BoundNodesTree build() const; + /// \brief Imposes an order on BoundNodesTreeBuilders. + bool operator<(const BoundNodesTreeBuilder &Other) const { + return Bindings < Other.Bindings; + } private: - BoundNodesTreeBuilder(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; - void operator=(const BoundNodesTreeBuilder &) LLVM_DELETED_FUNCTION; - - BoundNodesMap Bindings; - - std::vector RecursiveBindings; + SmallVector Bindings; }; class ASTMatchFinder; @@ -225,24 +205,6 @@ private: } }; -/// \brief Base class for all matchers that works on a \c DynTypedNode. -/// -/// Matcher implementations will check whether the \c DynTypedNode is -/// convertible into the respecitve types and then do the actual match -/// on the actual node, or return false if it is not convertible. -class DynTypedMatcher { -public: - virtual ~DynTypedMatcher() {} - - /// \brief Returns true if the matcher matches the given \c DynNode. - virtual bool matches(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const = 0; - - /// \brief Returns a unique ID for the matcher. - virtual uint64_t getID() const = 0; -}; - /// \brief Wrapper of a MatcherInterface *that allows copying. /// /// A Matcher can be used anywhere a Matcher is @@ -252,7 +214,7 @@ public: /// operator rather than a type hierarchy to be able to templatize the /// type hierarchy instead of spelling it out. template -class Matcher : public DynTypedMatcher { +class Matcher { public: /// \brief Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface *Implementation) @@ -282,7 +244,13 @@ public: bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - return Implementation->matches(Node, Finder, Builder); + if (Implementation->matches(Node, Finder, Builder)) + return true; + // Delete all bindings when a matcher does not match. + // This prevents unexpected exposure of bound nodes in unmatches + // branches of the match tree. + *Builder = BoundNodesTreeBuilder(); + return false; } /// \brief Returns an ID that uniquely identifies the matcher. @@ -292,15 +260,6 @@ public: return reinterpret_cast(Implementation.getPtr()); } - /// \brief Returns whether the matcher matches on the given \c DynNode. - virtual bool matches(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const { - const T *Node = DynNode.get(); - if (!Node) return false; - return matches(*Node, Finder, Builder); - } - /// \brief Allows the conversion of a \c Matcher to a \c /// Matcher. /// @@ -353,6 +312,217 @@ inline Matcher makeMatcher(MatcherInterface *Implementation) { return Matcher(Implementation); } +template class BindableMatcher; + +/// \brief Matcher that works on a \c DynTypedNode. +/// +/// It is constructed from a \c Matcher object and redirects most calls to +/// underlying matcher. +/// It checks whether the \c DynTypedNode is convertible into the type of the +/// underlying matcher and then do the actual match on the actual node, or +/// return false if it is not convertible. +class DynTypedMatcher { +public: + /// \brief Construct from a \c Matcher. Copies the matcher. + template inline DynTypedMatcher(const Matcher &M); + + /// \brief Construct from a bindable \c Matcher. Copies the matcher. + /// + /// This version enables \c tryBind() on the \c DynTypedMatcher. + template inline DynTypedMatcher(const BindableMatcher &M); + + /// \brief Returns true if the matcher matches the given \c DynNode. + bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { + return Storage->matches(DynNode, Finder, Builder); + } + + /// \brief Bind the specified \p ID to the matcher. + /// \return A new matcher with the \p ID bound to it if this matcher supports + /// binding. Otherwise, returns an empty \c Optional<>. + llvm::Optional tryBind(StringRef ID) const { + return Storage->tryBind(ID); + } + + /// \brief Returns a unique \p ID for the matcher. + uint64_t getID() const { return Storage->getID(); } + + /// \brief Returns the type this matcher works on. + /// + /// \c matches() will always return false unless the node passed is of this + /// or a derived type. + ast_type_traits::ASTNodeKind getSupportedKind() const { + return Storage->getSupportedKind(); + } + + /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted + /// to a \c Matcher. + /// + /// This method verifies that the underlying matcher in \c Other can process + /// nodes of types T. + template bool canConvertTo() const { + return getSupportedKind().isBaseOf( + ast_type_traits::ASTNodeKind::getFromNodeKind()); + } + + /// \brief Construct a \c Matcher interface around the dynamic matcher. + /// + /// This method asserts that \c canConvertTo() is \c true. Callers + /// should call \c canConvertTo() first to make sure that \c this is + /// compatible with T. + template Matcher convertTo() const { + assert(canConvertTo()); + return unconditionalConvertTo(); + } + + /// \brief Same as \c convertTo(), but does not check that the underlying + /// matcher can handle a value of T. + /// + /// If it is not compatible, then this matcher will never match anything. + template Matcher unconditionalConvertTo() const { + return Matcher(new WrappedMatcher(*this)); + } + +private: + class MatcherStorage : public RefCountedBaseVPTR { + public: + MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID) + : SupportedKind(SupportedKind), ID(ID) {} + virtual ~MatcherStorage(); + + virtual bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; + + virtual llvm::Optional tryBind(StringRef ID) const = 0; + + ast_type_traits::ASTNodeKind getSupportedKind() const { + return SupportedKind; + } + + uint64_t getID() const { return ID; } + + private: + const ast_type_traits::ASTNodeKind SupportedKind; + const uint64_t ID; + }; + + /// \brief Typed implementation of \c MatcherStorage. + template class TypedMatcherStorage; + + /// \brief Simple MatcherInterface wrapper around a DynTypedMatcher. + template class WrappedMatcher; + + IntrusiveRefCntPtr Storage; +}; + +template +class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage { +public: + TypedMatcherStorage(const Matcher &Other, bool AllowBind) + : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind(), + Other.getID()), + InnerMatcher(Other), AllowBind(AllowBind) {} + + bool matches(const ast_type_traits::DynTypedNode DynNode, + ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const + LLVM_OVERRIDE { + if (const T *Node = DynNode.get()) { + return InnerMatcher.matches(*Node, Finder, Builder); + } + return false; + } + + llvm::Optional tryBind(StringRef ID) const LLVM_OVERRIDE { + if (!AllowBind) + return llvm::Optional(); + return DynTypedMatcher(BindableMatcher(InnerMatcher).bind(ID)); + } + +private: + const Matcher InnerMatcher; + const bool AllowBind; +}; + +template +inline DynTypedMatcher::DynTypedMatcher(const Matcher &M) + : Storage(new TypedMatcherStorage(M, false)) {} + +template +inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher &M) + : Storage(new TypedMatcherStorage(M, true)) {} + +template +class DynTypedMatcher::WrappedMatcher : public MatcherInterface { +public: + explicit WrappedMatcher(const DynTypedMatcher &Matcher) : Inner(Matcher) {} + virtual ~WrappedMatcher() {} + + bool matches(const T &Node, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return Inner.matches(ast_type_traits::DynTypedNode::create(Node), Finder, + Builder); + } + +private: + const DynTypedMatcher Inner; +}; + +/// \brief Specialization of the conversion functions for QualType. +/// +/// These specializations provide the Matcher->Matcher +/// conversion that the static API does. +template <> inline bool DynTypedMatcher::canConvertTo() const { + const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind(); + return SourceKind.isSame( + ast_type_traits::ASTNodeKind::getFromNodeKind()) || + SourceKind.isSame( + ast_type_traits::ASTNodeKind::getFromNodeKind()); +} + +template <> +inline Matcher DynTypedMatcher::convertTo() const { + assert(canConvertTo()); + const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind(); + if (SourceKind.isSame( + ast_type_traits::ASTNodeKind::getFromNodeKind())) { + // We support implicit conversion from Matcher to Matcher + return unconditionalConvertTo(); + } + return unconditionalConvertTo(); +} + +/// \brief Finds the first node in a range that matches the given matcher. +template +bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start, + IteratorT End, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) { + for (IteratorT I = Start; I != End; ++I) { + BoundNodesTreeBuilder Result(*Builder); + if (Matcher.matches(*I, Finder, &Result)) { + *Builder = Result; + return true; + } + } + return false; +} + +/// \brief Finds the first node in a pointer range that matches the given +/// matcher. +template +bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, + IteratorT End, ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) { + for (IteratorT I = Start; I != End; ++I) { + BoundNodesTreeBuilder Result(*Builder); + if (Matcher.matches(**I, Finder, &Result)) { + *Builder = Result; + return true; + } + } + return false; +} + /// \brief Metafunction to determine if type T has a member called getDecl. template struct has_getDecl { struct Default { int getDecl; }; @@ -632,6 +802,94 @@ protected: AncestorMatchMode MatchMode) = 0; }; +/// \brief A type-list implementation. +/// +/// A list is declared as a tree of type list nodes, where the leafs are the +/// types. +/// However, it is used as a "linked list" of types, by using the ::head and +/// ::tail typedefs. +/// Each node supports up to 4 children (instead of just 2) to reduce the +/// nesting required by large lists. +template +struct TypeList { + /// \brief Implementation detail. Combined with the specializations below, + /// this typedef allows for flattening of nested structures. + typedef TypeList self; + + /// \brief The first type on the list. + typedef T1 head; + + /// \brief A sub list with the tail. ie everything but the head. + /// + /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the + /// end of the list. + typedef typename TypeList::self tail; +}; + +/// \brief Template specialization to allow nested lists. +/// +/// First element is a typelist. Pop its first element. +template +struct TypeList, T2, T3, + T4> : public TypeList::self, + typename TypeList::self> {}; + +/// \brief Template specialization to allow nested lists. +/// +/// First element is an empty typelist. Skip it. +template +struct TypeList, T2, T3, T4> : public TypeList { +}; + +/// \brief The empty type list. +typedef TypeList<> EmptyTypeList; + +/// \brief Helper meta-function to determine if some type \c T is present or +/// a parent type in the list. +template +struct TypeListContainsSuperOf { + static const bool value = + llvm::is_base_of::value || + TypeListContainsSuperOf::value; +}; +template +struct TypeListContainsSuperOf { + static const bool value = false; +}; + +/// \brief A "type list" that contains all types. +/// +/// Useful for matchers like \c anything and \c unless. +typedef TypeList< + TypeList, + TypeList > AllNodeBaseTypes; + +/// \brief Helper meta-function to extract the argument out of a function of +/// type void(Arg). +/// +/// See AST_POLYMORPHIC_SUPPORTED_TYPES_* for details. +template struct ExtractFunctionArgMeta; +template struct ExtractFunctionArgMeta { + typedef T type; +}; + +/// \brief Default type lists for ArgumentAdaptingMatcher matchers. +typedef AllNodeBaseTypes AdaptativeDefaultFromTypes; +typedef TypeList, + TypeList > +AdaptativeDefaultToTypes; + +/// \brief All types that are supported by HasDeclarationMatcher above. +typedef TypeList, + TypeList, + TypeList, + TypeList > +HasDeclarationSupportedTypes; + /// \brief Converts a \c Matcher to a matcher of desired type \c To by /// "adapting" a \c To into a \c T. /// @@ -646,19 +904,33 @@ protected: /// If a matcher does not need knowledge about the inner type, prefer to use /// PolymorphicMatcherWithParam1. template