From 2b6b257f4e5503a7a2675bdb8735693db769f75c Mon Sep 17 00:00:00 2001 From: Dimitry Andric Date: Sat, 23 Jul 2016 20:44:14 +0000 Subject: Vendor import of clang release_39 branch r276489: https://llvm.org/svn/llvm-project/cfe/branches/release_39@276489 --- include/Makefile | 4 - include/clang-c/Index.h | 210 +++- include/clang-c/Makefile | 38 - include/clang/ARCMigrate/ARCMTActions.h | 11 +- include/clang/AST/ASTConsumer.h | 25 +- include/clang/AST/ASTContext.h | 92 +- include/clang/AST/ASTImporter.h | 9 + include/clang/AST/ASTMutationListener.h | 9 + include/clang/AST/ASTTypeTraits.h | 4 +- include/clang/AST/Attr.h | 62 +- include/clang/AST/Availability.h | 63 + include/clang/AST/BaseSubobject.h | 3 +- include/clang/AST/BuiltinTypes.def | 17 +- include/clang/AST/CanonicalType.h | 3 + include/clang/AST/CharUnits.h | 17 +- include/clang/AST/Decl.h | 290 +++-- include/clang/AST/DeclBase.h | 36 +- include/clang/AST/DeclCXX.h | 409 +++++-- include/clang/AST/DeclFriend.h | 2 +- include/clang/AST/DeclObjC.h | 462 +++---- include/clang/AST/DeclOpenMP.h | 110 +- include/clang/AST/DeclTemplate.h | 166 ++- include/clang/AST/DeclarationName.h | 5 +- include/clang/AST/Expr.h | 102 +- include/clang/AST/ExprCXX.h | 196 ++- include/clang/AST/ExprObjC.h | 47 +- include/clang/AST/ExprOpenMP.h | 2 +- include/clang/AST/GlobalDecl.h | 2 + include/clang/AST/LambdaCapture.h | 32 +- include/clang/AST/LocInfoType.h | 61 + include/clang/AST/Makefile | 79 -- include/clang/AST/Mangle.h | 5 +- include/clang/AST/OpenMPClause.h | 1294 ++++++++++++++++++-- include/clang/AST/OperationKinds.def | 406 ++++++ include/clang/AST/OperationKinds.h | 321 +---- include/clang/AST/PrettyPrinter.h | 58 +- include/clang/AST/RecordLayout.h | 29 +- include/clang/AST/RecursiveASTVisitor.h | 313 ++++- include/clang/AST/Stmt.h | 32 +- include/clang/AST/StmtCXX.h | 19 +- include/clang/AST/StmtObjC.h | 2 +- include/clang/AST/StmtOpenMP.h | 715 ++++++++++- include/clang/AST/TemplateBase.h | 6 + include/clang/AST/TemplateName.h | 1 + include/clang/AST/Type.h | 431 ++++--- include/clang/AST/TypeLoc.h | 10 +- include/clang/AST/UnresolvedSet.h | 9 +- include/clang/ASTMatchers/ASTMatchFinder.h | 15 + include/clang/ASTMatchers/ASTMatchers.h | 839 ++++++++++++- include/clang/ASTMatchers/ASTMatchersInternal.h | 212 +++- include/clang/Analysis/Analyses/FormatString.h | 12 +- include/clang/Analysis/Analyses/ThreadSafetyUtil.h | 11 +- include/clang/Analysis/AnalysisContext.h | 4 + include/clang/Analysis/ProgramPoint.h | 7 + include/clang/Basic/AddressSpaces.h | 2 +- include/clang/Basic/Attr.td | 306 ++++- include/clang/Basic/AttrDocs.td | 669 +++++++++- include/clang/Basic/AttrKinds.h | 6 +- include/clang/Basic/Builtins.def | 65 + include/clang/Basic/Builtins.h | 25 +- include/clang/Basic/BuiltinsAArch64.def | 1 - include/clang/Basic/BuiltinsAMDGPU.def | 107 +- include/clang/Basic/BuiltinsARM.def | 21 +- include/clang/Basic/BuiltinsHexagon.def | 839 +++++++++++-- include/clang/Basic/BuiltinsNVPTX.def | 138 ++- include/clang/Basic/BuiltinsPPC.def | 3 + include/clang/Basic/BuiltinsSystemZ.def | 447 +++---- include/clang/Basic/BuiltinsWebAssembly.def | 4 +- include/clang/Basic/BuiltinsX86.def | 926 +++++++++++--- include/clang/Basic/Cuda.h | 77 ++ include/clang/Basic/DebugInfoOptions.h | 39 + include/clang/Basic/DeclNodes.td | 5 + include/clang/Basic/Diagnostic.h | 15 +- include/clang/Basic/DiagnosticASTKinds.td | 11 + include/clang/Basic/DiagnosticCommonKinds.td | 7 +- include/clang/Basic/DiagnosticDriverKinds.td | 37 +- include/clang/Basic/DiagnosticFrontendKinds.td | 15 +- include/clang/Basic/DiagnosticGroups.td | 35 +- include/clang/Basic/DiagnosticIDs.h | 2 +- include/clang/Basic/DiagnosticLexKinds.td | 35 +- include/clang/Basic/DiagnosticParseKinds.td | 73 +- include/clang/Basic/DiagnosticSemaKinds.td | 690 ++++++++--- include/clang/Basic/FileManager.h | 2 + include/clang/Basic/IdentifierTable.h | 17 +- include/clang/Basic/Lambda.h | 3 +- include/clang/Basic/LangOptions.def | 67 +- include/clang/Basic/LangOptions.h | 30 +- include/clang/Basic/Makefile | 70 -- include/clang/Basic/ObjCRuntime.h | 17 + include/clang/Basic/OpenCLExtensions.def | 80 +- include/clang/Basic/OpenCLImageTypes.def | 82 ++ include/clang/Basic/OpenCLOptions.h | 68 + include/clang/Basic/OpenMPKinds.def | 215 +++- include/clang/Basic/OpenMPKinds.h | 55 +- include/clang/Basic/PragmaKinds.h | 31 + include/clang/Basic/Sanitizers.def | 7 + include/clang/Basic/Sanitizers.h | 4 +- include/clang/Basic/SourceLocation.h | 8 +- include/clang/Basic/SourceManager.h | 10 +- include/clang/Basic/Specifiers.h | 39 +- include/clang/Basic/StmtNodes.td | 11 + include/clang/Basic/TargetCXXABI.h | 2 +- include/clang/Basic/TargetInfo.h | 94 +- include/clang/Basic/TargetOptions.h | 13 +- include/clang/Basic/TokenKinds.def | 12 + include/clang/Basic/TypeTraits.h | 1 + include/clang/Basic/VersionTuple.h | 35 +- include/clang/Basic/VirtualFileSystem.h | 28 +- include/clang/Basic/arm_neon.td | 22 +- include/clang/CMakeLists.txt | 1 + include/clang/CodeGen/BackendUtil.h | 11 +- include/clang/CodeGen/CGFunctionInfo.h | 217 +++- include/clang/CodeGen/CodeGenABITypes.h | 49 +- include/clang/CodeGen/ModuleBuilder.h | 89 +- .../CodeGen/ObjectFilePCHContainerOperations.h | 10 +- include/clang/CodeGen/SwiftCallingConv.h | 168 +++ include/clang/Config/config.h.cmake | 9 + include/clang/Config/config.h.in | 40 - include/clang/Driver/Action.h | 219 +++- include/clang/Driver/CC1Options.td | 87 +- include/clang/Driver/CLCompatOptions.td | 59 +- include/clang/Driver/Compilation.h | 66 +- include/clang/Driver/Driver.h | 82 +- include/clang/Driver/Job.h | 14 + include/clang/Driver/Makefile | 10 - include/clang/Driver/Multilib.h | 12 +- include/clang/Driver/Options.td | 184 ++- include/clang/Driver/SanitizerArgs.h | 25 +- include/clang/Driver/ToolChain.h | 23 +- include/clang/Driver/Types.def | 2 + include/clang/Format/Format.h | 293 +++-- include/clang/Frontend/ASTConsumers.h | 2 +- include/clang/Frontend/ASTUnit.h | 4 +- include/clang/Frontend/CodeGenOptions.def | 62 +- include/clang/Frontend/CodeGenOptions.h | 80 +- include/clang/Frontend/CompilerInstance.h | 46 +- include/clang/Frontend/CompilerInvocation.h | 6 +- include/clang/Frontend/DependencyOutputOptions.h | 3 + include/clang/Frontend/FrontendAction.h | 19 +- include/clang/Frontend/FrontendActions.h | 15 +- include/clang/Frontend/FrontendOptions.h | 19 +- include/clang/Frontend/LangStandards.def | 25 +- include/clang/Frontend/MultiplexConsumer.h | 8 +- include/clang/Frontend/PCHContainerOperations.h | 20 +- include/clang/Frontend/TextDiagnosticPrinter.h | 2 +- include/clang/Frontend/Utils.h | 35 +- include/clang/Index/CodegenNameGenerator.h | 52 + include/clang/Index/IndexDataConsumer.h | 64 + include/clang/Index/IndexSymbol.h | 129 ++ include/clang/Index/IndexingAction.h | 48 + include/clang/Index/USRGeneration.h | 2 +- include/clang/Lex/DirectoryLookup.h | 4 + include/clang/Lex/HeaderMap.h | 72 +- include/clang/Lex/HeaderMapTypes.h | 43 + include/clang/Lex/HeaderSearch.h | 20 +- include/clang/Lex/Lexer.h | 20 + include/clang/Lex/LiteralSupport.h | 10 + include/clang/Lex/MacroArgs.h | 2 +- include/clang/Lex/MacroInfo.h | 6 +- include/clang/Lex/ModuleMap.h | 33 +- include/clang/Lex/Preprocessor.h | 58 +- include/clang/Lex/Token.h | 43 +- include/clang/Makefile | 44 - include/clang/Parse/Makefile | 13 - include/clang/Parse/Parser.h | 111 +- include/clang/Rewrite/Frontend/ASTConsumers.h | 7 +- include/clang/Rewrite/Frontend/FrontendActions.h | 4 +- include/clang/Sema/AttributeList.h | 129 +- include/clang/Sema/CleanupInfo.h | 47 + include/clang/Sema/CodeCompleteConsumer.h | 6 +- include/clang/Sema/DeclSpec.h | 70 +- include/clang/Sema/ExternalSemaSource.h | 8 +- include/clang/Sema/Initialization.h | 21 +- include/clang/Sema/LocInfoType.h | 62 - include/clang/Sema/Lookup.h | 71 +- include/clang/Sema/Makefile | 39 - include/clang/Sema/MultiplexExternalSemaSource.h | 6 +- include/clang/Sema/ObjCMethodList.h | 4 + include/clang/Sema/Overload.h | 33 +- include/clang/Sema/Ownership.h | 5 +- include/clang/Sema/ParsedTemplate.h | 17 +- include/clang/Sema/Scope.h | 5 +- include/clang/Sema/ScopeInfo.h | 94 +- include/clang/Sema/Sema.h | 831 +++++++++---- include/clang/Sema/SemaInternal.h | 12 +- include/clang/Sema/SemaLambda.h | 2 +- include/clang/Sema/TemplateDeduction.h | 7 +- include/clang/Serialization/ASTBitCodes.h | 135 +- include/clang/Serialization/ASTReader.h | 77 +- include/clang/Serialization/ASTWriter.h | 448 +++---- include/clang/Serialization/Makefile | 19 - include/clang/Serialization/Module.h | 14 - .../clang/StaticAnalyzer/Checkers/CMakeLists.txt | 4 + include/clang/StaticAnalyzer/Checkers/Checkers.td | 659 ++++++++++ .../clang/StaticAnalyzer/Checkers/SValExplainer.h | 233 ++++ .../Core/BugReporter/BugReporterVisitor.h | 1 + .../Core/BugReporter/PathDiagnostic.h | 4 +- include/clang/StaticAnalyzer/Core/Checker.h | 14 + include/clang/StaticAnalyzer/Core/CheckerManager.h | 20 +- .../StaticAnalyzer/Core/PathSensitive/CallEvent.h | 41 +- .../Core/PathSensitive/CheckerContext.h | 4 + .../StaticAnalyzer/Core/PathSensitive/CoreEngine.h | 3 + .../Core/PathSensitive/Environment.h | 1 + .../Core/PathSensitive/ExplodedGraph.h | 14 +- .../StaticAnalyzer/Core/PathSensitive/ExprEngine.h | 17 +- .../StaticAnalyzer/Core/PathSensitive/MemRegion.h | 78 +- .../Core/PathSensitive/ProgramState.h | 6 +- .../StaticAnalyzer/Core/PathSensitive/Regions.def | 89 ++ .../Core/PathSensitive/SValBuilder.h | 3 +- .../Core/PathSensitive/SValVisitor.h | 151 +++ .../StaticAnalyzer/Core/PathSensitive/SVals.def | 74 ++ .../StaticAnalyzer/Core/PathSensitive/SVals.h | 23 +- .../StaticAnalyzer/Core/PathSensitive/SubEngine.h | 14 +- .../StaticAnalyzer/Core/PathSensitive/SymExpr.h | 123 ++ .../Core/PathSensitive/SymbolManager.h | 96 +- .../StaticAnalyzer/Core/PathSensitive/Symbols.def | 55 + include/clang/Tooling/CommonOptionsParser.h | 2 +- include/clang/Tooling/Core/QualTypeNames.h | 79 ++ include/clang/Tooling/Core/Replacement.h | 53 +- include/clang/Tooling/FixIt.h | 72 ++ include/clang/Tooling/Refactoring.h | 18 + include/clang/Tooling/Tooling.h | 7 +- include/clang/module.modulemap | 5 + 223 files changed, 15487 insertions(+), 4381 deletions(-) delete mode 100644 include/Makefile delete mode 100644 include/clang-c/Makefile create mode 100644 include/clang/AST/Availability.h create mode 100644 include/clang/AST/LocInfoType.h delete mode 100644 include/clang/AST/Makefile create mode 100644 include/clang/AST/OperationKinds.def create mode 100644 include/clang/Basic/Cuda.h create mode 100644 include/clang/Basic/DebugInfoOptions.h delete mode 100644 include/clang/Basic/Makefile create mode 100644 include/clang/Basic/OpenCLImageTypes.def create mode 100644 include/clang/Basic/OpenCLOptions.h create mode 100644 include/clang/Basic/PragmaKinds.h create mode 100644 include/clang/CodeGen/SwiftCallingConv.h delete mode 100644 include/clang/Config/config.h.in delete mode 100644 include/clang/Driver/Makefile create mode 100644 include/clang/Index/CodegenNameGenerator.h create mode 100644 include/clang/Index/IndexDataConsumer.h create mode 100644 include/clang/Index/IndexSymbol.h create mode 100644 include/clang/Index/IndexingAction.h create mode 100644 include/clang/Lex/HeaderMapTypes.h delete mode 100644 include/clang/Makefile delete mode 100644 include/clang/Parse/Makefile create mode 100644 include/clang/Sema/CleanupInfo.h delete mode 100644 include/clang/Sema/LocInfoType.h delete mode 100644 include/clang/Sema/Makefile delete mode 100644 include/clang/Serialization/Makefile create mode 100644 include/clang/StaticAnalyzer/Checkers/CMakeLists.txt create mode 100644 include/clang/StaticAnalyzer/Checkers/Checkers.td create mode 100644 include/clang/StaticAnalyzer/Checkers/SValExplainer.h create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/Regions.def create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SVals.def create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h create mode 100644 include/clang/StaticAnalyzer/Core/PathSensitive/Symbols.def create mode 100644 include/clang/Tooling/Core/QualTypeNames.h create mode 100644 include/clang/Tooling/FixIt.h (limited to 'include') diff --git a/include/Makefile b/include/Makefile deleted file mode 100644 index 79b9adfb7282c..0000000000000 --- a/include/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -CLANG_LEVEL := .. -DIRS := clang clang-c - -include $(CLANG_LEVEL)/Makefile diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index 09e216082630c..13db2085ba69b 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 32 +#define CINDEX_VERSION_MINOR 35 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -326,7 +326,7 @@ clang_isFileMultipleIncludeGuarded(CXTranslationUnit tu, CXFile file); * * \param tu the translation unit * - * \param file_name the name of the file. +* \param file_name the name of the file. * * \returns the file handle for the named file in the translation unit \p tu, * or a NULL file handle if the file was not a part of this translation unit. @@ -1208,7 +1208,18 @@ enum CXTranslationUnit_Flags { * trades runtime on the first parse (serializing the preamble takes time) for * reduced runtime on the second parse (can now reuse the preamble). */ - CXTranslationUnit_CreatePreambleOnFirstParse = 0x100 + CXTranslationUnit_CreatePreambleOnFirstParse = 0x100, + + /** + * \brief Do not stop processing when fatal errors are encountered. + * + * When fatal errors are encountered while parsing a translation unit, + * semantic analysis is typically stopped early when compiling code. A common + * source for fatal errors are unresolvable include files. For the + * purposes of an IDE, this is undesirable behavior and as much information + * as possible should be reported. Use this flag to enable this behavior. + */ + CXTranslationUnit_KeepGoing = 0x200 }; /** @@ -1921,7 +1932,7 @@ enum CXCursorKind { */ CXCursor_CXXDeleteExpr = 135, - /** \brief A unary expression. + /** \brief A unary expression. (noexcept, sizeof, or other traits) */ CXCursor_UnaryExpr = 136, @@ -2003,7 +2014,11 @@ enum CXCursorKind { */ CXCursor_OMPArraySectionExpr = 147, - CXCursor_LastExpr = CXCursor_OMPArraySectionExpr, + /** \brief Represents an @available(...) check. + */ + CXCursor_ObjCAvailabilityCheckExpr = 148, + + CXCursor_LastExpr = CXCursor_ObjCAvailabilityCheckExpr, /* Statements */ CXCursor_FirstStmt = 200, @@ -2270,11 +2285,47 @@ enum CXCursorKind { */ CXCursor_OMPTaskLoopSimdDirective = 259, - /** \brief OpenMP distribute directive. + /** \brief OpenMP distribute directive. */ CXCursor_OMPDistributeDirective = 260, - CXCursor_LastStmt = CXCursor_OMPDistributeDirective, + /** \brief OpenMP target enter data directive. + */ + CXCursor_OMPTargetEnterDataDirective = 261, + + /** \brief OpenMP target exit data directive. + */ + CXCursor_OMPTargetExitDataDirective = 262, + + /** \brief OpenMP target parallel directive. + */ + CXCursor_OMPTargetParallelDirective = 263, + + /** \brief OpenMP target parallel for directive. + */ + CXCursor_OMPTargetParallelForDirective = 264, + + /** \brief OpenMP target update directive. + */ + CXCursor_OMPTargetUpdateDirective = 265, + + /** \brief OpenMP distribute parallel for directive. + */ + CXCursor_OMPDistributeParallelForDirective = 266, + + /** \brief OpenMP distribute parallel for simd directive. + */ + CXCursor_OMPDistributeParallelForSimdDirective = 267, + + /** \brief OpenMP distribute simd directive. + */ + CXCursor_OMPDistributeSimdDirective = 268, + + /** \brief OpenMP target parallel for simd directive. + */ + CXCursor_OMPTargetParallelForSimdDirective = 269, + + CXCursor_LastStmt = CXCursor_OMPTargetParallelForSimdDirective, /** * \brief Cursor that represents the translation unit itself. @@ -2328,8 +2379,12 @@ enum CXCursorKind { */ CXCursor_ModuleImportDecl = 600, CXCursor_TypeAliasTemplateDecl = 601, + /** + * \brief A static_assert or _Static_assert node + */ + CXCursor_StaticAssert = 602, CXCursor_FirstExtraDecl = CXCursor_ModuleImportDecl, - CXCursor_LastExtraDecl = CXCursor_TypeAliasTemplateDecl, + CXCursor_LastExtraDecl = CXCursor_StaticAssert, /** * \brief A code completion overload candidate. @@ -2430,6 +2485,11 @@ CINDEX_LINKAGE unsigned clang_isStatement(enum CXCursorKind); */ CINDEX_LINKAGE unsigned clang_isAttribute(enum CXCursorKind); +/** + * \brief Determine whether the given cursor has any attributes. + */ +CINDEX_LINKAGE unsigned clang_Cursor_hasAttrs(CXCursor C); + /** * \brief Determine whether the given cursor kind represents an invalid * cursor. @@ -2526,7 +2586,7 @@ typedef struct CXPlatformAvailability { * \brief A string that describes the platform for which this structure * provides availability information. * - * Possible values are "ios" or "macosx". + * Possible values are "ios" or "macos". */ CXString Platform; /** @@ -2897,6 +2957,7 @@ enum CXTypeKind { CXType_ObjCId = 27, CXType_ObjCClass = 28, CXType_ObjCSel = 29, + CXType_Float128 = 30, CXType_FirstBuiltin = CXType_Void, CXType_LastBuiltin = CXType_ObjCSel, @@ -2918,7 +2979,14 @@ enum CXTypeKind { CXType_VariableArray = 115, CXType_DependentSizedArray = 116, CXType_MemberPointer = 117, - CXType_Auto = 118 + CXType_Auto = 118, + + /** + * \brief Represents a type that was referred to using an elaborated type keyword. + * + * E.g., struct S, or via a qualified name, e.g., N::M::type, or both. + */ + CXType_Elaborated = 119 }; /** @@ -2938,6 +3006,9 @@ enum CXCallingConv { CXCallingConv_X86_64Win64 = 10, CXCallingConv_X86_64SysV = 11, CXCallingConv_X86VectorCall = 12, + CXCallingConv_Swift = 13, + CXCallingConv_PreserveMost = 14, + CXCallingConv_PreserveAll = 15, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 @@ -3169,6 +3240,24 @@ CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T); */ CINDEX_LINKAGE unsigned clang_isConstQualifiedType(CXType T); +/** + * \brief Determine whether a CXCursor that is a macro, is + * function like. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isMacroFunctionLike(CXCursor C); + +/** + * \brief Determine whether a CXCursor that is a macro, is a + * builtin one. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isMacroBuiltin(CXCursor C); + +/** + * \brief Determine whether a CXCursor that is a function declaration, is an + * inline declaration. + */ +CINDEX_LINKAGE unsigned clang_Cursor_isFunctionInlined(CXCursor C); + /** * \brief Determine whether a CXType has the "volatile" qualifier set, * without looking through typedefs that may have added "volatile" at @@ -3198,6 +3287,11 @@ CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T); */ CINDEX_LINKAGE CXString clang_getDeclObjCTypeEncoding(CXCursor C); +/** + * Returns the Objective-C type encoding for the specified CXType. + */ +CINDEX_LINKAGE CXString clang_Type_getObjCEncoding(CXType type); + /** * \brief Retrieve the spelling of a given CXTypeKind. */ @@ -3281,6 +3375,13 @@ CINDEX_LINKAGE CXType clang_getArrayElementType(CXType T); */ CINDEX_LINKAGE long long clang_getArraySize(CXType T); +/** + * \brief Retrieve the type named by the qualified-id. + * + * If a non-elaborated type is passed in, an invalid type is returned. + */ +CINDEX_LINKAGE CXType clang_Type_getNamedType(CXType T); + /** * \brief List the possible error codes for \c clang_Type_getSizeOf, * \c clang_Type_getAlignOf, \c clang_Type_getOffsetOf and @@ -3612,8 +3713,8 @@ typedef enum CXChildVisitResult * Visits the children of a cursor using the specified block. Behaves * identically to clang_visitChildren() in all other respects. */ -unsigned clang_visitChildrenWithBlock(CXCursor parent, - CXCursorVisitorBlock block); +CINDEX_LINKAGE unsigned clang_visitChildrenWithBlock(CXCursor parent, + CXCursorVisitorBlock block); # endif #endif @@ -3834,7 +3935,8 @@ typedef enum { CXObjCPropertyAttr_atomic = 0x100, CXObjCPropertyAttr_weak = 0x200, CXObjCPropertyAttr_strong = 0x400, - CXObjCPropertyAttr_unsafe_unretained = 0x800 + CXObjCPropertyAttr_unsafe_unretained = 0x800, + CXObjCPropertyAttr_class = 0x1000 } CXObjCPropertyAttrKind; /** @@ -4015,11 +4117,36 @@ CXFile clang_Module_getTopLevelHeader(CXTranslationUnit, * @{ */ +/** + * \brief Determine if a C++ constructor is a converting constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isConvertingConstructor(CXCursor C); + +/** + * \brief Determine if a C++ constructor is a copy constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isCopyConstructor(CXCursor C); + +/** + * \brief Determine if a C++ constructor is the default constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isDefaultConstructor(CXCursor C); + +/** + * \brief Determine if a C++ constructor is a move constructor. + */ +CINDEX_LINKAGE unsigned clang_CXXConstructor_isMoveConstructor(CXCursor C); + /** * \brief Determine if a C++ field is declared 'mutable'. */ CINDEX_LINKAGE unsigned clang_CXXField_isMutable(CXCursor C); +/** + * \brief Determine if a C++ method is declared '= default'. + */ +CINDEX_LINKAGE unsigned clang_CXXMethod_isDefaulted(CXCursor C); + /** * \brief Determine if a C++ member function or member function template is * pure virtual. @@ -4900,7 +5027,7 @@ CINDEX_LINKAGE unsigned clang_defaultCodeCompleteOptions(void); * Note that the column should point just after the syntactic construct that * initiated code completion, and not in the middle of a lexical token. * - * \param unsaved_files the Tiles that have not yet been saved to disk + * \param unsaved_files the Files that have not yet been saved to disk * but may be required for parsing or code completion, including the * contents of those files. The contents and name of these files (as * specified by CXUnsavedFile) are copied when necessary, so the @@ -5077,6 +5204,59 @@ CINDEX_LINKAGE void clang_getInclusions(CXTranslationUnit tu, CXInclusionVisitor visitor, CXClientData client_data); +typedef enum { + CXEval_Int = 1 , + CXEval_Float = 2, + CXEval_ObjCStrLiteral = 3, + CXEval_StrLiteral = 4, + CXEval_CFStr = 5, + CXEval_Other = 6, + + CXEval_UnExposed = 0 + +} CXEvalResultKind ; + +/** + * \brief Evaluation result of a cursor + */ +typedef void * CXEvalResult; + +/** + * \brief If cursor is a statement declaration tries to evaluate the + * statement and if its variable, tries to evaluate its initializer, + * into its corresponding type. + */ +CINDEX_LINKAGE CXEvalResult clang_Cursor_Evaluate(CXCursor C); + +/** + * \brief Returns the kind of the evaluated result. + */ +CINDEX_LINKAGE CXEvalResultKind clang_EvalResult_getKind(CXEvalResult E); + +/** + * \brief Returns the evaluation result as integer if the + * kind is Int. + */ +CINDEX_LINKAGE int clang_EvalResult_getAsInt(CXEvalResult E); + +/** + * \brief Returns the evaluation result as double if the + * kind is double. + */ +CINDEX_LINKAGE double clang_EvalResult_getAsDouble(CXEvalResult E); + +/** + * \brief Returns the evaluation result as a constant string if the + * kind is other than Int or float. User must not free this pointer, + * instead call clang_EvalResult_dispose on the CXEvalResult returned + * by clang_Cursor_Evaluate. + */ +CINDEX_LINKAGE const char* clang_EvalResult_getAsStr(CXEvalResult E); + +/** + * \brief Disposes the created Eval memory. + */ +CINDEX_LINKAGE void clang_EvalResult_dispose(CXEvalResult E); /** * @} */ @@ -5150,7 +5330,7 @@ enum CXVisitorResult { CXVisit_Continue }; -typedef struct { +typedef struct CXCursorAndRangeVisitor { void *context; enum CXVisitorResult (*visit)(void *context, CXCursor, CXSourceRange); } CXCursorAndRangeVisitor; diff --git a/include/clang-c/Makefile b/include/clang-c/Makefile deleted file mode 100644 index b29e29ea1ef8e..0000000000000 --- a/include/clang-c/Makefile +++ /dev/null @@ -1,38 +0,0 @@ -CLANG_LEVEL := ../.. -DIRS := - -include $(CLANG_LEVEL)/Makefile - -IntIncludeDir = $(DESTDIR)$(PROJ_internal_prefix)/include - -install-local:: - $(Echo) Installing Clang C API include files - $(Verb) $(MKDIR) $(IntIncludeDir) - $(Verb) if test -d "$(PROJ_SRC_DIR)" ; then \ - cd $(PROJ_SRC_DIR)/.. && \ - for hdr in `find clang-c -type f '!' '(' -name '*~' \ - -o -name '.#*' -o -name '*.in' -o -name '*.txt' \ - -o -name 'Makefile' -o -name '*.td' ')' -print \ - | grep -v CVS | grep -v .svn | grep -v .dir` ; do \ - instdir=`dirname "$(IntIncludeDir)/$$hdr"` ; \ - if test \! -d "$$instdir" ; then \ - $(EchoCmd) Making install directory $$instdir ; \ - $(MKDIR) $$instdir ;\ - fi ; \ - $(DataInstall) $$hdr $(IntIncludeDir)/$$hdr ; \ - done ; \ - fi -ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT)) - $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/clang/include/clang-c" ; then \ - cd $(PROJ_OBJ_ROOT)/tools/clang/include && \ - for hdr in `find clang-c -type f '!' '(' -name 'Makefile' ')' -print \ - | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \ - instdir=`dirname "$(IntIncludeDir)/$$hdr"` ; \ - if test \! -d "$$instdir" ; then \ - $(EchoCmd) Making install directory $$instdir ; \ - $(MKDIR) $$instdir ;\ - fi ; \ - $(DataInstall) $$hdr $(IntIncludeDir)/$$hdr ; \ - done ; \ - fi -endif diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h index c830aa3d78744..554e0c0c6d028 100644 --- a/include/clang/ARCMigrate/ARCMTActions.h +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -22,7 +22,7 @@ protected: bool BeginInvocation(CompilerInstance &CI) override; public: - CheckAction(FrontendAction *WrappedAction); + CheckAction(std::unique_ptr WrappedAction); }; class ModifyAction : public WrapperFrontendAction { @@ -30,7 +30,7 @@ protected: bool BeginInvocation(CompilerInstance &CI) override; public: - ModifyAction(FrontendAction *WrappedAction); + ModifyAction(std::unique_ptr WrappedAction); }; class MigrateSourceAction : public ASTFrontendAction { @@ -49,7 +49,8 @@ protected: bool BeginInvocation(CompilerInstance &CI) override; public: - MigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, + MigrateAction(std::unique_ptr WrappedAction, + StringRef migrateDir, StringRef plistOut, bool emitPremigrationARCErrors); }; @@ -61,8 +62,8 @@ class ObjCMigrateAction : public WrapperFrontendAction { FileRemapper Remapper; CompilerInstance *CompInst; public: - ObjCMigrateAction(FrontendAction *WrappedAction, StringRef migrateDir, - unsigned migrateAction); + ObjCMigrateAction(std::unique_ptr WrappedAction, + StringRef migrateDir, unsigned migrateAction); protected: std::unique_ptr CreateASTConsumer(CompilerInstance &CI, diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index b2730e4622287..0b1f0068fa6f0 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -55,9 +55,9 @@ public: /// \returns true to continue parsing, or false to abort parsing. virtual bool HandleTopLevelDecl(DeclGroupRef D); - /// \brief This callback is invoked each time an inline method definition is - /// completed. - virtual void HandleInlineMethodDefinition(CXXMethodDecl *D) {} + /// \brief This callback is invoked each time an inline (method or friend) + /// function definition in a class is completed. + virtual void HandleInlineFunctionDefinition(FunctionDecl *D) {} /// HandleInterestingDecl - Handle the specified interesting declaration. This /// is called by the AST reader when deserializing things that might interest @@ -94,21 +94,6 @@ 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. @@ -120,6 +105,10 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} + /// \brief Callback invoked when an MSInheritanceAttr has been attached to a + /// CXXRecordDecl. + virtual void AssignInheritanceModel(CXXRecordDecl *RD) {} + /// HandleCXXStaticMemberVarInstantiation - Tell the consumer that this // variable has been instantiated. virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {} diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index abf92948bb42e..1d223f47a9aec 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -36,6 +36,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" @@ -128,6 +129,8 @@ class ASTContext : public RefCountedBase { llvm::FoldingSet PackExpansionTypes; mutable llvm::FoldingSet ObjCObjectTypes; mutable llvm::FoldingSet ObjCObjectPointerTypes; + mutable llvm::FoldingSet + DependentUnaryTransformTypes; mutable llvm::FoldingSet AutoTypes; mutable llvm::FoldingSet AtomicTypes; llvm::FoldingSet AttributedTypes; @@ -212,9 +215,6 @@ 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. mutable TypedefDecl *BuiltinVaListDecl; @@ -243,6 +243,9 @@ class ASTContext : public RefCountedBase { QualType ObjCClassRedefinitionType; QualType ObjCSelRedefinitionType; + /// The identifier 'bool'. + mutable IdentifierInfo *BoolName = nullptr; + /// The identifier 'NSObject'. IdentifierInfo *NSObjectName = nullptr; @@ -252,9 +255,13 @@ class ASTContext : public RefCountedBase { /// The identifier '__make_integer_seq'. mutable IdentifierInfo *MakeIntegerSeqName = nullptr; + /// The identifier '__type_pack_element'. + mutable IdentifierInfo *TypePackElementName = nullptr; + QualType ObjCConstantStringType; - mutable RecordDecl *CFConstantStringTypeDecl; - + mutable RecordDecl *CFConstantStringTagDecl; + mutable TypedefDecl *CFConstantStringTypeDecl; + mutable QualType ObjCSuperType; QualType ObjCNSStringType; @@ -392,8 +399,8 @@ private: /// \brief Side-table of mangling numbers for declarations which rarely /// need them (like static local vars). - llvm::DenseMap MangleNumbers; - llvm::DenseMap StaticLocalNumbers; + llvm::MapVector MangleNumbers; + llvm::MapVector StaticLocalNumbers; /// \brief Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. @@ -406,6 +413,7 @@ private: TranslationUnitDecl *TUDecl; mutable ExternCContextDecl *ExternCContext; mutable BuiltinTemplateDecl *MakeIntegerSeqDecl; + mutable BuiltinTemplateDecl *TypePackElementDecl; /// \brief The associated SourceManager object.a SourceManager &SourceMgr; @@ -817,6 +825,9 @@ public: overridden_methods_end(const CXXMethodDecl *Method) const; unsigned overridden_methods_size(const CXXMethodDecl *Method) const; + typedef llvm::iterator_range + overridden_method_range; + overridden_method_range overridden_methods(const CXXMethodDecl *Method) const; /// \brief Note that the given C++ \p Method overrides the given \p /// Overridden method. @@ -876,6 +887,7 @@ public: ExternCContextDecl *getExternCContextDecl() const; BuiltinTemplateDecl *getMakeIntegerSeqDecl() const; + BuiltinTemplateDecl *getTypePackElementDecl() const; // Builtin Types. CanQualType VoidTy; @@ -889,20 +901,19 @@ public: CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; - CanQualType FloatTy, DoubleTy, LongDoubleTy; + CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; + CanQualType Float128ComplexTy; CanQualType VoidPtrTy, NullPtrTy; CanQualType DependentTy, OverloadTy, BoundMemberTy, UnknownAnyTy; CanQualType BuiltinFnTy; CanQualType PseudoObjectTy, ARCUnbridgedCastTy; CanQualType ObjCBuiltinIdTy, ObjCBuiltinClassTy, ObjCBuiltinSelTy; CanQualType ObjCBuiltinBoolTy; - CanQualType OCLImage1dTy, OCLImage1dArrayTy, OCLImage1dBufferTy; - CanQualType OCLImage2dTy, OCLImage2dArrayTy, OCLImage2dDepthTy; - CanQualType OCLImage2dArrayDepthTy, OCLImage2dMSAATy, OCLImage2dArrayMSAATy; - CanQualType OCLImage2dMSAADepthTy, OCLImage2dArrayMSAADepthTy; - CanQualType OCLImage3dTy; +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + CanQualType SingletonId; +#include "clang/Basic/OpenCLImageTypes.def" CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy; CanQualType OCLQueueTy, OCLNDRangeTy, OCLReserveIDTy; CanQualType OMPArraySectionTy; @@ -966,9 +977,6 @@ 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 //===--------------------------------------------------------------------===// @@ -1229,13 +1237,12 @@ public: TemplateTypeParmDecl *ParmDecl = nullptr) const; QualType getTemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, QualType Canon = QualType()) const; - QualType getCanonicalTemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs) const; + QualType + getCanonicalTemplateSpecializationType(TemplateName T, + ArrayRef Args) const; QualType getTemplateSpecializationType(TemplateName T, const TemplateArgumentListInfo &Args, @@ -1260,11 +1267,9 @@ public: NestedNameSpecifier *NNS, const IdentifierInfo *Name, const TemplateArgumentListInfo &Args) const; - QualType getDependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args) const; + QualType getDependentTemplateSpecializationType( + ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, + const IdentifierInfo *Name, ArrayRef Args) const; QualType getPackExpansionType(QualType Pattern, Optional NumExpansions); @@ -1381,10 +1386,12 @@ public: /// if it hasn't yet been built. QualType getRawCFConstantStringType() const { if (CFConstantStringTypeDecl) - return getTagDeclType(CFConstantStringTypeDecl); + return getTypedefType(CFConstantStringTypeDecl); return QualType(); } void setCFConstantStringType(QualType T); + TypedefDecl *getCFConstantStringDecl() const; + RecordDecl *getCFConstantStringTagDecl() const; // This setter/getter represents the ObjC type for an NSConstantString. void setObjCConstantStringInterface(ObjCInterfaceDecl *Decl); @@ -1458,12 +1465,25 @@ public: return NSCopyingName; } + /// Retrieve the identifier 'bool'. + IdentifierInfo *getBoolName() const { + if (!BoolName) + BoolName = &Idents.get("bool"); + return BoolName; + } + IdentifierInfo *getMakeIntegerSeqName() const { if (!MakeIntegerSeqName) MakeIntegerSeqName = &Idents.get("__make_integer_seq"); return MakeIntegerSeqName; } + IdentifierInfo *getTypePackElementName() const { + if (!TypePackElementName) + TypePackElementName = &Idents.get("__type_pack_element"); + return TypePackElementName; + } + /// \brief Retrieve the Objective-C "instancetype" type, if already known; /// otherwise, returns a NULL type; QualType getObjCInstanceType() { @@ -2257,7 +2277,7 @@ public: QualType mergeObjCGCQualifiers(QualType, QualType); - bool FunctionTypesMatchOnNSConsumedAttrs( + bool doFunctionTypesMatchOnExtParameterInfos( const FunctionProtoType *FromFunctionType, const FunctionProtoType *ToFunctionType); @@ -2508,7 +2528,21 @@ public: /// \brief Returns true if this is an inline-initialized static data member /// which is treated as a definition for MSVC compatibility. bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const; - + + enum class InlineVariableDefinitionKind { + None, ///< Not an inline variable. + Weak, ///< Weak definition of inline variable. + WeakUnknown, ///< Weak for now, might become strong later in this TU. + Strong ///< Strong definition. + }; + /// \brief Determine whether a definition of this inline variable should + /// be treated as a weak or strong definition. For compatibility with + /// C++14 and before, for a constexpr static data member, if there is an + /// out-of-line declaration of the member, we may promote it from weak to + /// strong. + InlineVariableDefinitionKind + getInlineVariableDefinitionKind(const VarDecl *VD) const; + private: const ASTRecordLayout & getObjCLayout(const ObjCInterfaceDecl *D, diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index ee48955ca6362..e116abaef7970 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -23,6 +23,7 @@ namespace clang { class ASTContext; + class CXXCtorInitializer; class Decl; class DeclContext; class DiagnosticsEngine; @@ -204,6 +205,14 @@ namespace clang { /// \returns the equivalent file ID in the source manager of the "to" /// context. FileID Import(FileID); + + /// \brief Import the given C++ constructor initializer from the "from" + /// context into the "to" context. + /// + /// \returns the equivalent initializer in the "to" context. + CXXCtorInitializer *Import(CXXCtorInitializer *FromInit); + + /// \brief Import the definition of the given declaration, including all of /// the declarations it contains. diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index cf3b55d7b2c74..e2d184d654e3a 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -17,6 +17,7 @@ namespace clang { class Attr; class ClassTemplateDecl; class ClassTemplateSpecializationDecl; + class ConstructorUsingShadowDecl; class CXXDestructorDecl; class CXXRecordDecl; class Decl; @@ -107,6 +108,14 @@ public: /// \param D the declaration marked OpenMP threadprivate. virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {} + /// \brief A declaration is marked as OpenMP declaretarget which was not + /// previously marked as declaretarget. + /// + /// \param D the declaration marked OpenMP declaretarget. + /// \param Attr the added attribute. + virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, + const Attr *Attr) {} + /// \brief A definition has been made visible by being redefined locally. /// /// \param D The definition that was previously not visible. diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index dcaac802c110a..ad301b14829e5 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -62,7 +62,9 @@ public: /// \} /// \brief Returns \c true if \c this and \c Other represent the same kind. - bool isSame(ASTNodeKind Other) const; + bool isSame(ASTNodeKind Other) const { + return KindId != NKI_None && KindId == Other.KindId; + } /// \brief Returns \c true only for the default \c ASTNodeKind() bool isNone() const { return KindId == NKI_None; } diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index 8b80e9f6396ec..a94b161a04bc8 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -20,6 +20,7 @@ #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/VersionTuple.h" @@ -50,11 +51,11 @@ protected: /// An index into the spelling list of an /// attribute defined in Attr.td file. unsigned SpellingListIndex : 4; - bool Inherited : 1; - bool IsPackExpansion : 1; - bool Implicit : 1; - bool IsLateParsed : 1; - bool DuplicatesAllowed : 1; + unsigned Inherited : 1; + unsigned IsPackExpansion : 1; + unsigned Implicit : 1; + unsigned IsLateParsed : 1; + unsigned DuplicatesAllowed : 1; void *operator new(size_t bytes) LLVM_NOEXCEPT { llvm_unreachable("Attrs cannot be allocated with regular 'new'."); @@ -118,6 +119,19 @@ public: bool duplicatesAllowed() const { return DuplicatesAllowed; } }; +class StmtAttr : public Attr { +protected: + StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, + bool IsLateParsed, bool DuplicatesAllowed) + : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} + +public: + static bool classof(const Attr *A) { + return A->getKind() >= attr::FirstStmtAttr && + A->getKind() <= attr::LastStmtAttr; + } +}; + class InheritableAttr : public Attr { protected: InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, @@ -129,7 +143,8 @@ public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - return A->getKind() <= attr::LAST_INHERITABLE; + return A->getKind() >= attr::FirstInheritableAttr && + A->getKind() <= attr::LastInheritableAttr; } }; @@ -143,12 +158,41 @@ protected: public: // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { - // Relies on relative order of enum emission with respect to MS inheritance - // attrs. - return A->getKind() <= attr::LAST_INHERITABLE_PARAM; + return A->getKind() >= attr::FirstInheritableParamAttr && + A->getKind() <= attr::LastInheritableParamAttr; } }; +/// A parameter attribute which changes the argument-passing ABI rule +/// for the parameter. +class ParameterABIAttr : public InheritableParamAttr { +protected: + ParameterABIAttr(attr::Kind AK, SourceRange R, + unsigned SpellingListIndex, bool IsLateParsed, + bool DuplicatesAllowed) + : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed, + DuplicatesAllowed) {} + +public: + ParameterABI getABI() const { + switch (getKind()) { + case attr::SwiftContext: + return ParameterABI::SwiftContext; + case attr::SwiftErrorResult: + return ParameterABI::SwiftErrorResult; + case attr::SwiftIndirectResult: + return ParameterABI::SwiftIndirectResult; + default: + llvm_unreachable("bad parameter ABI attribute kind"); + } + } + + static bool classof(const Attr *A) { + return A->getKind() >= attr::FirstParameterABIAttr && + A->getKind() <= attr::LastParameterABIAttr; + } +}; + #include "clang/AST/Attrs.inc" inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/Availability.h b/include/clang/AST/Availability.h new file mode 100644 index 0000000000000..5ed8313784567 --- /dev/null +++ b/include/clang/AST/Availability.h @@ -0,0 +1,63 @@ +//===--- Availability.h - Classes for availability --------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This files defines some classes that implement availability checking. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_AVAILABILITY_H +#define LLVM_CLANG_AST_AVAILABILITY_H + +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/VersionTuple.h" +#include "llvm/ADT/StringRef.h" + +namespace clang { + +/// \brief One specifier in an @available expression. +/// +/// \code +/// @available(macos 10.10, *) +/// \endcode +/// +/// Here, 'macos 10.10' and '*' both map to an instance of this type. +/// +class AvailabilitySpec { + /// Represents the version that this specifier requires. If the host OS + /// version is greater than or equal to Version, the @available will evaluate + /// to true. + VersionTuple Version; + + /// Name of the platform that Version corresponds to. + StringRef Platform; + + SourceLocation BeginLoc, EndLoc; + +public: + AvailabilitySpec(VersionTuple Version, StringRef Platform, + SourceLocation BeginLoc, SourceLocation EndLoc) + : Version(Version), Platform(Platform), BeginLoc(BeginLoc), + EndLoc(EndLoc) {} + + /// This constructor is used when representing the '*' case. + AvailabilitySpec(SourceLocation StarLoc) + : BeginLoc(StarLoc), EndLoc(StarLoc) {} + + VersionTuple getVersion() const { return Version; } + StringRef getPlatform() const { return Platform; } + SourceLocation getBeginLoc() const { return BeginLoc; } + SourceLocation getEndLoc() const { return EndLoc; } + + /// Returns true when this represents the '*' case. + bool isOtherPlatformSpec() const { return Version.empty(); } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/BaseSubobject.h b/include/clang/AST/BaseSubobject.h index da538e3566a7a..66af023c828e4 100644 --- a/include/clang/AST/BaseSubobject.h +++ b/include/clang/AST/BaseSubobject.h @@ -15,13 +15,12 @@ #define LLVM_CLANG_AST_BASESUBOBJECT_H #include "clang/AST/CharUnits.h" +#include "clang/AST/DeclCXX.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/DataTypes.h" #include "llvm/Support/type_traits.h" namespace clang { - class CXXRecordDecl; - // BaseSubobject - Uniquely identifies a direct or indirect base class. // Stores both the base class decl and the offset from the most derived class to // the base class. Used for vtable and VTT generation. diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index a08a6839024b4..c0c6819280d24 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -133,6 +133,9 @@ FLOATING_TYPE(Double, DoubleTy) // 'long double' FLOATING_TYPE(LongDouble, LongDoubleTy) +// '__float128' +FLOATING_TYPE(Float128, Float128Ty) + //===- Language-specific types --------------------------------------------===// // This is the type of C++0x 'nullptr'. @@ -154,20 +157,6 @@ BUILTIN_TYPE(ObjCClass, ObjCBuiltinClassTy) // type is a typedef of a PointerType to this. BUILTIN_TYPE(ObjCSel, ObjCBuiltinSelTy) -// OpenCL image types. -BUILTIN_TYPE(OCLImage1d, OCLImage1dTy) -BUILTIN_TYPE(OCLImage1dArray, OCLImage1dArrayTy) -BUILTIN_TYPE(OCLImage1dBuffer, OCLImage1dBufferTy) -BUILTIN_TYPE(OCLImage2d, OCLImage2dTy) -BUILTIN_TYPE(OCLImage2dArray, OCLImage2dArrayTy) -BUILTIN_TYPE(OCLImage2dDepth, OCLImage2dDepthTy) -BUILTIN_TYPE(OCLImage2dArrayDepth, OCLImage2dArrayDepthTy) -BUILTIN_TYPE(OCLImage2dMSAA, OCLImage2dMSAATy) -BUILTIN_TYPE(OCLImage2dArrayMSAA, OCLImage2dArrayMSAATy) -BUILTIN_TYPE(OCLImage2dMSAADepth, OCLImage2dMSAADepthTy) -BUILTIN_TYPE(OCLImage2dArrayMSAADepth, OCLImage2dArrayMSAADepthTy) -BUILTIN_TYPE(OCLImage3d, OCLImage3dTy) - // OpenCL sampler_t. BUILTIN_TYPE(OCLSampler, OCLSamplerTy) diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index b25800bfedb91..77510afeec1b9 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -484,6 +484,9 @@ struct CanProxyAdaptor LLVM_CLANG_CANPROXY_TYPE_ACCESSOR(getReturnType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(FunctionType::ExtInfo, getExtInfo) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(unsigned, getNumParams) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, hasExtParameterInfos) + LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR( + ArrayRef, getExtParameterInfos) CanQualType getParamType(unsigned i) const { return CanQualType::CreateUnsafe(this->getTypePtr()->getParamType(i)); } diff --git a/include/clang/AST/CharUnits.h b/include/clang/AST/CharUnits.h index 1d22bccd2e896..564c8ec9b9ea0 100644 --- a/include/clang/AST/CharUnits.h +++ b/include/clang/AST/CharUnits.h @@ -133,7 +133,7 @@ namespace clang { /// Test whether this is a multiple of the other value. /// /// Among other things, this promises that - /// self.RoundUpToAlignment(N) will just return self. + /// self.alignTo(N) will just return self. bool isMultipleOf(CharUnits N) const { return (*this % N) == 0; } @@ -142,9 +142,17 @@ namespace clang { CharUnits operator* (QuantityType N) const { return CharUnits(Quantity * N); } + CharUnits &operator*= (QuantityType N) { + Quantity *= N; + return *this; + } CharUnits operator/ (QuantityType N) const { return CharUnits(Quantity / N); } + CharUnits &operator/= (QuantityType N) { + Quantity /= N; + return *this; + } QuantityType operator/ (const CharUnits &Other) const { return Quantity / Other.Quantity; } @@ -170,12 +178,11 @@ namespace clang { /// getQuantity - Get the raw integer representation of this quantity. QuantityType getQuantity() const { return Quantity; } - /// RoundUpToAlignment - Returns the next integer (mod 2**64) that is + /// alignTo - Returns the next integer (mod 2**64) that is /// greater than or equal to this quantity and is a multiple of \p Align. /// Align must be non-zero. - CharUnits RoundUpToAlignment(const CharUnits &Align) const { - return CharUnits(llvm::RoundUpToAlignment(Quantity, - Align.Quantity)); + CharUnits alignTo(const CharUnits &Align) const { + return CharUnits(llvm::alignTo(Quantity, Align.Quantity)); } /// Given that this is a non-zero alignment value, what is the diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 029c1182f26e6..109036f9588ea 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -23,6 +23,7 @@ #include "clang/Basic/Linkage.h" #include "clang/Basic/Module.h" #include "clang/Basic/OperatorKinds.h" +#include "clang/Basic/PragmaKinds.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/Compiler.h" @@ -103,6 +104,73 @@ public: } }; +/// \brief Represents a `#pragma comment` line. Always a child of +/// TranslationUnitDecl. +class PragmaCommentDecl final + : public Decl, + private llvm::TrailingObjects { + virtual void anchor(); + + PragmaMSCommentKind CommentKind; + + friend TrailingObjects; + friend class ASTDeclReader; + friend class ASTDeclWriter; + + PragmaCommentDecl(TranslationUnitDecl *TU, SourceLocation CommentLoc, + PragmaMSCommentKind CommentKind) + : Decl(PragmaComment, TU, CommentLoc), CommentKind(CommentKind) {} + +public: + static PragmaCommentDecl *Create(const ASTContext &C, TranslationUnitDecl *DC, + SourceLocation CommentLoc, + PragmaMSCommentKind CommentKind, + StringRef Arg); + static PragmaCommentDecl *CreateDeserialized(ASTContext &C, unsigned ID, + unsigned ArgSize); + + PragmaMSCommentKind getCommentKind() const { return CommentKind; } + + StringRef getArg() const { return getTrailingObjects(); } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == PragmaComment; } +}; + +/// \brief Represents a `#pragma detect_mismatch` line. Always a child of +/// TranslationUnitDecl. +class PragmaDetectMismatchDecl final + : public Decl, + private llvm::TrailingObjects { + virtual void anchor(); + + size_t ValueStart; + + friend TrailingObjects; + friend class ASTDeclReader; + friend class ASTDeclWriter; + + PragmaDetectMismatchDecl(TranslationUnitDecl *TU, SourceLocation Loc, + size_t ValueStart) + : Decl(PragmaDetectMismatch, TU, Loc), ValueStart(ValueStart) {} + +public: + static PragmaDetectMismatchDecl *Create(const ASTContext &C, + TranslationUnitDecl *DC, + SourceLocation Loc, StringRef Name, + StringRef Value); + static PragmaDetectMismatchDecl * + CreateDeserialized(ASTContext &C, unsigned ID, unsigned NameValueSize); + + StringRef getName() const { return getTrailingObjects(); } + StringRef getValue() const { return getTrailingObjects() + ValueStart; } + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == PragmaDetectMismatch; } +}; + /// \brief Declaration context for names declared as extern "C" in C++. This /// is neither the semantic nor lexical context for such declarations, but is /// used to check for conflicts with other extern "C" declarations. Example: @@ -319,6 +387,7 @@ public: NamedDecl *getUnderlyingDecl() { // Fast-path the common case. if (this->getKind() != UsingShadow && + this->getKind() != ConstructorUsingShadow && this->getKind() != ObjCCompatibleAlias && this->getKind() != NamespaceAlias) return this; @@ -813,12 +882,15 @@ protected: /// variable; see isARCPseudoStrong() for details. unsigned ARCPseudoStrong : 1; + /// \brief Whether this variable is (C++1z) inline. + unsigned IsInline : 1; + + /// \brief Whether this variable has (C++1z) inline explicitly specified. + unsigned IsInlineSpecified : 1; + /// \brief Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; - /// \brief Whether this variable is a (C++ Concepts TS) concept. - unsigned IsConcept : 1; - /// \brief Whether this variable is the implicit variable for a lambda /// init-capture. unsigned IsInitCapture : 1; @@ -1037,9 +1109,6 @@ public: /// definition of a static data member. bool isOutOfLine() const override; - /// \brief If this is a static data member, find its out-of-line definition. - VarDecl *getOutOfLineDefinition(); - /// isFileVarDecl - Returns true for file scoped variable declaration. bool isFileVarDecl() const { Kind K = getKind(); @@ -1185,6 +1254,24 @@ public: NonParmVarDeclBits.ARCPseudoStrong = ps; } + /// Whether this variable is (C++1z) inline. + bool isInline() const { + return isa(this) ? false : NonParmVarDeclBits.IsInline; + } + bool isInlineSpecified() const { + return isa(this) ? false + : NonParmVarDeclBits.IsInlineSpecified; + } + void setInlineSpecified() { + assert(!isa(this)); + NonParmVarDeclBits.IsInline = true; + NonParmVarDeclBits.IsInlineSpecified = true; + } + void setImplicitlyInline() { + assert(!isa(this)); + NonParmVarDeclBits.IsInline = true; + } + /// Whether this variable is (C++11) constexpr. bool isConstexpr() const { return isa(this) ? false : NonParmVarDeclBits.IsConstexpr; @@ -1194,15 +1281,6 @@ public: NonParmVarDeclBits.IsConstexpr = IC; } - /// Whether this variable is (C++ Concepts TS) concept. - bool isConcept() const { - return isa(this) ? false : NonParmVarDeclBits.IsConcept; - } - void setConcept(bool IC) { - assert(!isa(this)); - NonParmVarDeclBits.IsConcept = IC; - } - /// Whether this variable is the implicit variable for a lambda init-capture. bool isInitCapture() const { return isa(this) ? false : NonParmVarDeclBits.IsInitCapture; @@ -1702,6 +1780,17 @@ public: return isDefined(Definition); } + /// \brief Get the definition for this declaration. + FunctionDecl *getDefinition() { + const FunctionDecl *Definition; + if (isDefined(Definition)) + return const_cast(Definition); + return nullptr; + } + const FunctionDecl *getDefinition() const { + return const_cast(this)->getDefinition(); + } + /// getBody - Retrieve the body (definition) of the function. The /// function body might be in any of the (re-)declarations of this /// function. The variant that accepts a FunctionDecl pointer will @@ -1896,29 +1985,24 @@ public: unsigned getBuiltinID() const; - // Iterator access to formal parameters. - unsigned param_size() const { return getNumParams(); } - typedef ParmVarDecl **param_iterator; - typedef ParmVarDecl * const *param_const_iterator; - typedef llvm::iterator_range param_range; - typedef llvm::iterator_range param_const_range; - - param_iterator param_begin() { return param_iterator(ParamInfo); } - param_iterator param_end() { - return param_iterator(ParamInfo + param_size()); - } - param_range params() { return param_range(param_begin(), param_end()); } - - param_const_iterator param_begin() const { - return param_const_iterator(ParamInfo); + // ArrayRef interface to parameters. + ArrayRef parameters() const { + return {ParamInfo, getNumParams()}; } - param_const_iterator param_end() const { - return param_const_iterator(ParamInfo + param_size()); - } - param_const_range params() const { - return param_const_range(param_begin(), param_end()); + MutableArrayRef parameters() { + return {ParamInfo, getNumParams()}; } + // Iterator access to formal parameters. + typedef MutableArrayRef::iterator param_iterator; + typedef ArrayRef::const_iterator param_const_iterator; + bool param_empty() const { return parameters().empty(); } + param_iterator param_begin() { return parameters().begin(); } + param_iterator param_end() { return parameters().end(); } + param_const_iterator param_begin() const { return parameters().begin(); } + param_const_iterator param_end() const { return parameters().end(); } + size_t param_size() const { return parameters().size(); } + /// getNumParams - Return the number of parameters this function must have /// based on its FunctionType. This is the length of the ParamInfo array /// after it has been created. @@ -1936,12 +2020,6 @@ public: setParams(getASTContext(), NewParamInfo); } - // ArrayRef iterface to parameters. - // FIXME: Should one day replace iterator interface. - ArrayRef parameters() const { - return llvm::makeArrayRef(ParamInfo, getNumParams()); - } - ArrayRef getDeclsInPrototypeScope() const { return DeclsInPrototypeScope; } @@ -1954,6 +2032,7 @@ public: unsigned getMinRequiredArguments() const; QualType getReturnType() const { + assert(getType()->getAs() && "Expected a FunctionType!"); return getType()->getAs()->getReturnType(); } @@ -1964,15 +2043,20 @@ public: /// \brief Determine the type of an expression that calls this function. QualType getCallResultType() const { + assert(getType()->getAs() && "Expected a FunctionType!"); return getType()->getAs()->getCallResultType(getASTContext()); } + /// \brief Returns the WarnUnusedResultAttr that is either declared on this + /// function, or its return type declaration. + const Attr *getUnusedResultAttr() const; + /// \brief Returns true if this function or its return type has the /// warn_unused_result attribute. If the return type has the attribute and /// this function is a method of the return type's class, then false will be /// returned to avoid spurious warnings on member methods such as assignment /// operators. - bool hasUnusedResultAttr() const; + bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; } /// \brief Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. @@ -2208,7 +2292,7 @@ public: /// represent a member of a struct/union/class. class FieldDecl : public DeclaratorDecl, public Mergeable { // FIXME: This can be packed into the bitfields in Decl. - bool Mutable : 1; + unsigned Mutable : 1; mutable unsigned CachedFieldIndex : 31; /// The kinds of value we can store in InitializerOrBitWidth. @@ -2442,34 +2526,33 @@ class IndirectFieldDecl : public ValueDecl, IndirectFieldDecl(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName N, QualType T, - NamedDecl **CH, unsigned CHS); + MutableArrayRef CH); public: static IndirectFieldDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - QualType T, NamedDecl **CH, unsigned CHS); + QualType T, llvm::MutableArrayRef CH); static IndirectFieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - typedef NamedDecl * const *chain_iterator; - typedef llvm::iterator_range chain_range; - chain_range chain() const { return chain_range(chain_begin(), chain_end()); } - chain_iterator chain_begin() const { return chain_iterator(Chaining); } - chain_iterator chain_end() const { - return chain_iterator(Chaining + ChainingSize); + typedef ArrayRef::const_iterator chain_iterator; + + ArrayRef chain() const { + return llvm::makeArrayRef(Chaining, ChainingSize); } + chain_iterator chain_begin() const { return chain().begin(); } + chain_iterator chain_end() const { return chain().end(); } unsigned getChainingSize() const { return ChainingSize; } FieldDecl *getAnonField() const { - assert(ChainingSize >= 2); - return cast(Chaining[ChainingSize - 1]); + assert(chain().size() >= 2); + return cast(chain().back()); } VarDecl *getVarDecl() const { - assert(ChainingSize >= 2); - return dyn_cast(*chain_begin()); + assert(chain().size() >= 2); + return dyn_cast(chain().front()); } IndirectFieldDecl *getCanonicalDecl() override { return getFirstDecl(); } @@ -2655,20 +2738,20 @@ private: /// IsCompleteDefinition - True if this is a definition ("struct foo /// {};"), false if it is a declaration ("struct foo;"). It is not /// a definition until the definition has been fully processed. - bool IsCompleteDefinition : 1; + unsigned IsCompleteDefinition : 1; protected: /// IsBeingDefined - True if this is currently being defined. - bool IsBeingDefined : 1; + unsigned IsBeingDefined : 1; private: /// IsEmbeddedInDeclarator - True if this tag declaration is /// "embedded" (i.e., defined or declared for the very first time) /// in the syntax of a declarator. - bool IsEmbeddedInDeclarator : 1; + unsigned IsEmbeddedInDeclarator : 1; /// \brief True if this tag is free standing, e.g. "struct foo;". - bool IsFreeStanding : 1; + unsigned IsFreeStanding : 1; protected: // These are used by (and only defined for) EnumDecl. @@ -2677,28 +2760,28 @@ protected: /// IsScoped - True if this tag declaration is a scoped enumeration. Only /// possible in C++11 mode. - bool IsScoped : 1; + unsigned IsScoped : 1; /// IsScopedUsingClassTag - If this tag declaration is a scoped enum, /// then this is true if the scoped enum was declared using the class /// tag, false if it was declared with the struct tag. No meaning is /// associated if this tag declaration is not a scoped enum. - bool IsScopedUsingClassTag : 1; + unsigned IsScopedUsingClassTag : 1; /// IsFixed - True if this is an enumeration with fixed underlying type. Only /// possible in C++11, Microsoft extensions, or Objective C mode. - bool IsFixed : 1; + unsigned IsFixed : 1; /// \brief Indicates whether it is possible for declarations of this kind /// to have an out-of-date definition. /// /// This option is only enabled when modules are enabled. - bool MayHaveOutOfDateDef : 1; + unsigned MayHaveOutOfDateDef : 1; /// Has the full definition of this type been required by a use somewhere in /// the TU. - bool IsCompleteDefinitionRequired : 1; + unsigned IsCompleteDefinitionRequired : 1; private: - SourceLocation RBraceLoc; + SourceRange BraceRange; // A struct representing syntactic qualifier info, // to be used for the (uncommon) case of out-of-line declarations. @@ -2760,8 +2843,8 @@ public: using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; - SourceLocation getRBraceLoc() const { return RBraceLoc; } - void setRBraceLoc(SourceLocation L) { RBraceLoc = L; } + SourceRange getBraceRange() const { return BraceRange; } + void setBraceRange(SourceRange R) { BraceRange = R; } /// getInnerLocStart - Return SourceLocation representing start of source /// range ignoring outer template declarations. @@ -3122,6 +3205,10 @@ public: return isCompleteDefinition() || isFixed(); } + /// \brief Retrieve the enum definition from which this enumeration could + /// be instantiated, if it is an instantiation (rather than a non-template). + EnumDecl *getTemplateInstantiationPattern() const; + /// \brief Returns the enumeration (declared within the template) /// from which this enumeration type was instantiated, or NULL if /// this enumeration was not instantiated from any template. @@ -3452,35 +3539,23 @@ public: void setSignatureAsWritten(TypeSourceInfo *Sig) { SignatureAsWritten = Sig; } TypeSourceInfo *getSignatureAsWritten() const { return SignatureAsWritten; } - // Iterator access to formal parameters. - unsigned param_size() const { return getNumParams(); } - typedef ParmVarDecl **param_iterator; - typedef ParmVarDecl * const *param_const_iterator; - typedef llvm::iterator_range param_range; - typedef llvm::iterator_range param_const_range; - // ArrayRef access to formal parameters. - // FIXME: Should eventual replace iterator access. - ArrayRef parameters() const { - return llvm::makeArrayRef(ParamInfo, param_size()); + ArrayRef parameters() const { + return {ParamInfo, getNumParams()}; } - - bool param_empty() const { return NumParams == 0; } - param_range params() { return param_range(param_begin(), param_end()); } - param_iterator param_begin() { return param_iterator(ParamInfo); } - param_iterator param_end() { - return param_iterator(ParamInfo + param_size()); + MutableArrayRef parameters() { + return {ParamInfo, getNumParams()}; } - param_const_range params() const { - return param_const_range(param_begin(), param_end()); - } - param_const_iterator param_begin() const { - return param_const_iterator(ParamInfo); - } - param_const_iterator param_end() const { - return param_const_iterator(ParamInfo + param_size()); - } + // Iterator access to formal parameters. + typedef MutableArrayRef::iterator param_iterator; + typedef ArrayRef::const_iterator param_const_iterator; + bool param_empty() const { return parameters().empty(); } + param_iterator param_begin() { return parameters().begin(); } + param_iterator param_end() { return parameters().end(); } + param_const_iterator param_begin() const { return parameters().begin(); } + param_const_iterator param_end() const { return parameters().end(); } + size_t param_size() const { return parameters().size(); } unsigned getNumParams() const { return NumParams; } const ParmVarDecl *getParamDecl(unsigned i) const { @@ -3501,22 +3576,12 @@ public: /// Does not include an entry for 'this'. unsigned getNumCaptures() const { return NumCaptures; } - typedef const Capture *capture_iterator; - typedef const Capture *capture_const_iterator; - typedef llvm::iterator_range capture_range; - typedef llvm::iterator_range capture_const_range; + typedef ArrayRef::const_iterator capture_const_iterator; - capture_range captures() { - return capture_range(capture_begin(), capture_end()); - } - capture_const_range captures() const { - return capture_const_range(capture_begin(), capture_end()); - } + ArrayRef captures() const { return {Captures, NumCaptures}; } - capture_iterator capture_begin() { return Captures; } - capture_iterator capture_end() { return Captures + NumCaptures; } - capture_const_iterator capture_begin() const { return Captures; } - capture_const_iterator capture_end() const { return Captures + NumCaptures; } + capture_const_iterator capture_begin() const { return captures().begin(); } + capture_const_iterator capture_end() const { return captures().end(); } bool capturesCXXThis() const { return CapturesCXXThis; } bool blockMissingReturnType() const { return BlockMissingReturnType; } @@ -3607,6 +3672,14 @@ public: getParams()[i] = P; } + // ArrayRef interface to parameters. + ArrayRef parameters() const { + return {getParams(), getNumParams()}; + } + MutableArrayRef parameters() { + return {getParams(), getNumParams()}; + } + /// \brief Retrieve the parameter containing captured variables. ImplicitParamDecl *getContextParam() const { assert(ContextParam < NumParams); @@ -3627,9 +3700,6 @@ public: /// \brief Retrieve an iterator one past the last parameter decl. param_iterator param_end() const { return getParams() + NumParams; } - /// \brief Retrieve an iterator range for the parameter declarations. - param_range params() const { return param_range(param_begin(), param_end()); } - // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Captured; } diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 2d6e84a68aa5b..ec8bb3aaa305e 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -52,6 +52,7 @@ struct PrintingPolicy; class RecordDecl; class Stmt; class StoredDeclsMap; +class TemplateDecl; class TranslationUnitDecl; class UsingDirectiveDecl; } @@ -72,13 +73,10 @@ namespace clang { /// /// Note: There are objects tacked on before the *beginning* of Decl /// (and its subclasses) in its Decl::operator new(). Proper alignment -/// of all subclasses (not requiring more than DeclObjAlignment) is +/// of all subclasses (not requiring more than the alignment of Decl) is /// asserted in DeclBase.cpp. -class Decl { +class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl { public: - /// \brief Alignment guaranteed when allocating Decl and any subtypes. - enum { DeclObjAlignment = llvm::AlignOf::Alignment }; - /// \brief Lists the kind of concrete classes of Decl. enum Kind { #define DECL(DERIVED, BASE) DERIVED, @@ -166,7 +164,10 @@ public: /// has been declared outside any function. These act mostly like /// invisible friend declarations, but are also visible to unqualified /// lookup within the scope of the declaring function. - IDNS_LocalExtern = 0x0800 + IDNS_LocalExtern = 0x0800, + + /// This declaration is an OpenMP user defined reduction construction. + IDNS_OMPReduction = 0x1000 }; /// ObjCDeclQualifier - 'Qualifiers' written next to the return and @@ -256,7 +257,7 @@ private: SourceLocation Loc; /// DeclKind - This indicates which class this is. - unsigned DeclKind : 8; + unsigned DeclKind : 7; /// InvalidDecl - This indicates a semantic error occurred. unsigned InvalidDecl : 1; @@ -296,7 +297,7 @@ protected: unsigned Hidden : 1; /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. - unsigned IdentifierNamespace : 12; + unsigned IdentifierNamespace : 13; /// \brief If 0, we have not computed the linkage of this declaration. /// Otherwise, it is the linkage + 1. @@ -514,8 +515,8 @@ public: bool isImplicit() const { return Implicit; } void setImplicit(bool I = true) { Implicit = I; } - /// \brief Whether this declaration was used, meaning that a definition - /// is required. + /// \brief Whether *any* (re-)declaration of the entity was used, meaning that + /// a definition is required. /// /// \param CheckUsedAttr When true, also consider the "used" attribute /// (in addition to the "used" bit set by \c setUsed()) when determining @@ -525,7 +526,8 @@ public: /// \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; } + /// It intentionally doesn't notify any listeners. + void setIsUsed() { getCanonicalDecl()->Used = true; } /// \brief Mark the declaration used, in the sense of odr-use. /// @@ -564,6 +566,13 @@ public: return NextInContextAndBits.getInt() & ModulePrivateFlag; } + /// Return true if this declaration has an attribute which acts as + /// definition of the entity, such as 'alias' or 'ifunc'. + bool hasDefiningAttr() const; + + /// Return this declaration's defining attribute if it has one. + const Attr *getDefiningAttr() const; + protected: /// \brief Specify whether this declaration was marked as being private /// to the module in which it was defined. @@ -895,6 +904,10 @@ public: DeclKind == FunctionTemplate; } + /// \brief If this is a declaration that describes some template, this + /// method returns that template declaration. + TemplateDecl *getDescribedTemplate() const; + /// \brief Returns the function itself, or the templated function if this is a /// function template. FunctionDecl *getAsFunction() LLVM_READONLY; @@ -1117,6 +1130,7 @@ public: /// ObjCContainerDecl /// LinkageSpecDecl /// BlockDecl +/// OMPDeclareReductionDecl /// class DeclContext { /// DeclKind - This indicates which class this is. diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 7c54901be3ea5..66acfee60db05 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -16,6 +16,7 @@ #ifndef LLVM_CLANG_AST_DECLCXX_H #define LLVM_CLANG_AST_DECLCXX_H +#include "clang/AST/ASTContext.h" #include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" @@ -29,6 +30,7 @@ namespace clang { class ClassTemplateDecl; class ClassTemplateSpecializationDecl; +class ConstructorUsingShadowDecl; class CXXBasePath; class CXXBasePaths; class CXXConstructorDecl; @@ -165,13 +167,13 @@ class CXXBaseSpecifier { SourceLocation EllipsisLoc; /// \brief Whether this is a virtual base class or not. - bool Virtual : 1; + unsigned Virtual : 1; /// \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; + unsigned BaseOfClass : 1; /// \brief Access specifier as written in the source code (may be AS_none). /// @@ -181,7 +183,7 @@ class CXXBaseSpecifier { /// \brief Whether the class contains a using declaration /// to inherit the named class's constructors. - bool InheritConstructors : 1; + unsigned InheritConstructors : 1; /// \brief The type of the base class. /// @@ -257,30 +259,6 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; -/// \brief A lazy pointer to the definition data for a declaration. -/// FIXME: This is a little CXXRecordDecl-specific that the moment. -template class LazyDefinitionDataPtr { - llvm::PointerUnion DataOrCanonicalDecl; - - LazyDefinitionDataPtr update() { - if (Decl *Canon = DataOrCanonicalDecl.template dyn_cast()) { - if (Canon->isCanonicalDecl()) - Canon->getMostRecentDecl(); - else - // Declaration isn't canonical any more; - // update it and perform path compression. - *this = Canon->getPreviousDecl()->DefinitionData.update(); - } - return *this; - } - -public: - LazyDefinitionDataPtr(Decl *Canon) : DataOrCanonicalDecl(Canon) {} - LazyDefinitionDataPtr(T *Data) : DataOrCanonicalDecl(Data) {} - T *getNotUpdated() { return DataOrCanonicalDecl.template dyn_cast(); } - T *get() { return update().getNotUpdated(); } -}; - /// \brief Represents a C++ struct/union/class. class CXXRecordDecl : public RecordDecl { @@ -301,30 +279,30 @@ class CXXRecordDecl : public RecordDecl { DefinitionData(CXXRecordDecl *D); /// \brief True if this class has any user-declared constructors. - bool UserDeclaredConstructor : 1; + unsigned UserDeclaredConstructor : 1; /// \brief The user-declared special members which this class has. unsigned UserDeclaredSpecialMembers : 6; /// \brief True when this class is an aggregate. - bool Aggregate : 1; + unsigned Aggregate : 1; /// \brief True when this class is a POD-type. - bool PlainOldData : 1; + unsigned PlainOldData : 1; /// 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; + unsigned Empty : 1; /// \brief True when this class is polymorphic, i.e., has at /// least one virtual member or derives from a polymorphic class. - bool Polymorphic : 1; + unsigned Polymorphic : 1; /// \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; + unsigned Abstract : 1; /// \brief True when this class has standard layout. /// @@ -340,58 +318,70 @@ class CXXRecordDecl : public RecordDecl { /// classes with non-static data members, and /// * has no base classes of the same type as the first non-static data /// member. - bool IsStandardLayout : 1; + unsigned IsStandardLayout : 1; /// \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; + unsigned HasNoNonEmptyBases : 1; /// \brief True when there are private non-static data members. - bool HasPrivateFields : 1; + unsigned HasPrivateFields : 1; /// \brief True when there are protected non-static data members. - bool HasProtectedFields : 1; + unsigned HasProtectedFields : 1; /// \brief True when there are private non-static data members. - bool HasPublicFields : 1; + unsigned HasPublicFields : 1; /// \brief True if this class (or any subobject) has mutable fields. - bool HasMutableFields : 1; + unsigned HasMutableFields : 1; /// \brief True if this class (or any nested anonymous struct or union) /// has variant members. - bool HasVariantMembers : 1; + unsigned HasVariantMembers : 1; /// \brief True if there no non-field members declared by the user. - bool HasOnlyCMembers : 1; + unsigned HasOnlyCMembers : 1; /// \brief True if any field has an in-class initializer, including those /// within anonymous unions or structs. - bool HasInClassInitializer : 1; + unsigned 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. - bool HasUninitializedReferenceMember : 1; + unsigned HasUninitializedReferenceMember : 1; + + /// \brief True if any non-mutable field whose type doesn't have a user- + /// provided default ctor also doesn't have an in-class initializer. + unsigned HasUninitializedFields : 1; + + /// \brief True if there are any member using-declarations that inherit + /// constructors from a base class. + unsigned HasInheritedConstructor : 1; + + /// \brief True if there are any member using-declarations named + /// 'operator='. + unsigned HasInheritedAssignment : 1; /// \brief These flags are \c true if a defaulted corresponding special /// member can't be fully analyzed without performing overload resolution. /// @{ - bool NeedOverloadResolutionForMoveConstructor : 1; - bool NeedOverloadResolutionForMoveAssignment : 1; - bool NeedOverloadResolutionForDestructor : 1; + unsigned NeedOverloadResolutionForMoveConstructor : 1; + unsigned NeedOverloadResolutionForMoveAssignment : 1; + unsigned NeedOverloadResolutionForDestructor : 1; /// @} /// \brief These flags are \c true if an implicit defaulted corresponding /// special member would be defined as deleted. /// @{ - bool DefaultedMoveConstructorIsDeleted : 1; - bool DefaultedMoveAssignmentIsDeleted : 1; - bool DefaultedDestructorIsDeleted : 1; + unsigned DefaultedMoveConstructorIsDeleted : 1; + unsigned DefaultedMoveAssignmentIsDeleted : 1; + unsigned DefaultedDestructorIsDeleted : 1; /// @} /// \brief The trivial special members which this class has, per @@ -411,33 +401,37 @@ class CXXRecordDecl : public RecordDecl { unsigned DeclaredNonTrivialSpecialMembers : 6; /// \brief True when this class has a destructor with no semantic effect. - bool HasIrrelevantDestructor : 1; + unsigned HasIrrelevantDestructor : 1; /// \brief True when this class has at least one user-declared constexpr /// constructor which is neither the copy nor move constructor. - bool HasConstexprNonCopyMoveConstructor : 1; + unsigned HasConstexprNonCopyMoveConstructor : 1; + + /// \brief True if this class has a (possibly implicit) defaulted default + /// constructor. + unsigned HasDefaultedDefaultConstructor : 1; /// \brief True if a defaulted default constructor for this class would /// be constexpr. - bool DefaultedDefaultConstructorIsConstexpr : 1; + unsigned DefaultedDefaultConstructorIsConstexpr : 1; /// \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; + unsigned HasConstexprDefaultConstructor : 1; /// \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; + unsigned HasNonLiteralTypeFieldsOrBases : 1; /// \brief True when visible conversion functions are already computed /// and are available. - bool ComputedVisibleConversions : 1; + unsigned ComputedVisibleConversions : 1; /// \brief Whether we have a C++11 user-provided default constructor (not /// explicitly deleted or defaulted). - bool UserProvidedDefaultConstructor : 1; + unsigned UserProvidedDefaultConstructor : 1; /// \brief The special members which have been declared for this class, /// either by the user or implicitly. @@ -445,25 +439,25 @@ class CXXRecordDecl : public RecordDecl { /// \brief Whether an implicit copy constructor would have a const-qualified /// parameter. - bool ImplicitCopyConstructorHasConstParam : 1; + unsigned ImplicitCopyConstructorHasConstParam : 1; /// \brief Whether an implicit copy assignment operator would have a /// const-qualified parameter. - bool ImplicitCopyAssignmentHasConstParam : 1; + unsigned ImplicitCopyAssignmentHasConstParam : 1; /// \brief Whether any declared copy constructor has a const-qualified /// parameter. - bool HasDeclaredCopyConstructorWithConstParam : 1; + unsigned HasDeclaredCopyConstructorWithConstParam : 1; /// \brief Whether any declared copy assignment operator has either a /// const-qualified reference parameter or a non-reference parameter. - bool HasDeclaredCopyAssignmentWithConstParam : 1; + unsigned HasDeclaredCopyAssignmentWithConstParam : 1; /// \brief Whether this class describes a C++ lambda. - bool IsLambda : 1; + unsigned IsLambda : 1; /// \brief Whether we are currently parsing base specifiers. - bool IsParsingBaseSpecifiers : 1; + unsigned IsParsingBaseSpecifiers : 1; /// \brief The number of base class specifiers in Bases. unsigned NumBases; @@ -515,16 +509,19 @@ class CXXRecordDecl : public RecordDecl { return getVBasesSlowCase(); } + ArrayRef bases() const { + return llvm::makeArrayRef(getBases(), NumBases); + } + ArrayRef vbases() const { + return llvm::makeArrayRef(getVBases(), NumVBases); + } + private: CXXBaseSpecifier *getBasesSlowCase() const; CXXBaseSpecifier *getVBasesSlowCase() const; }; - typedef LazyDefinitionDataPtr - DefinitionDataPtr; - friend class LazyDefinitionDataPtr; - - mutable DefinitionDataPtr DefinitionData; + struct DefinitionData *DefinitionData; /// \brief Describes a C++ closure type (generated by a lambda expression). struct LambdaDefinitionData : public DefinitionData { @@ -587,8 +584,14 @@ class CXXRecordDecl : public RecordDecl { }; + struct DefinitionData *dataPtr() const { + // Complete the redecl chain (if necessary). + getMostRecentDecl(); + return DefinitionData; + } + struct DefinitionData &data() const { - auto *DD = DefinitionData.get(); + auto *DD = dataPtr(); assert(DD && "queried property of class with no definition"); return *DD; } @@ -596,7 +599,7 @@ class CXXRecordDecl : public RecordDecl { struct LambdaDefinitionData &getLambdaData() const { // No update required: a merged definition cannot change any lambda // properties. - auto *DD = DefinitionData.getNotUpdated(); + auto *DD = DefinitionData; assert(DD && DD->IsLambda && "queried lambda property of non-lambda class"); return static_cast(*DD); } @@ -673,11 +676,13 @@ public: } CXXRecordDecl *getDefinition() const { - auto *DD = DefinitionData.get(); + // We only need an update if we don't already know which + // declaration is the definition. + auto *DD = DefinitionData ? DefinitionData : dataPtr(); return DD ? DD->Definition : nullptr; } - bool hasDefinition() const { return DefinitionData.get(); } + bool hasDefinition() const { return DefinitionData || dataPtr(); } static CXXRecordDecl *Create(const ASTContext &C, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, @@ -1021,7 +1026,7 @@ public: /// \brief Determine whether this class describes a lambda function object. bool isLambda() const { // An update record can't turn a non-lambda into a lambda. - auto *DD = DefinitionData.getNotUpdated(); + auto *DD = DefinitionData; return DD && DD->IsLambda; } @@ -1136,9 +1141,10 @@ public: /// \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. + /// The CXXRecordDecl is a class type, but not a union type, + /// with no non-static data members other than bit-fields of length 0, + /// no virtual member functions, no virtual base classes, + /// and no base class B for which is_empty::value is false. /// /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } @@ -1270,6 +1276,14 @@ public: return !(data().HasTrivialSpecialMembers & SMF_Destructor); } + /// \brief Determine whether declaring a const variable with this type is ok + /// per core issue 253. + bool allowConstDefaultInit() const { + return !data().HasUninitializedFields || + !(data().HasDefaultedDefaultConstructor || + needsImplicitDefaultConstructor()); + } + /// \brief Determine whether this class has a destructor which has no /// semantic effect. /// @@ -1285,6 +1299,18 @@ public: return data().HasNonLiteralTypeFieldsOrBases; } + /// \brief Determine whether this class has a using-declaration that names + /// a user-declared base class constructor. + bool hasInheritedConstructor() const { + return data().HasInheritedConstructor; + } + + /// \brief Determine whether this class has a using-declaration that names + /// a base class assignment operator. + bool hasInheritedAssignment() const { + return data().HasInheritedAssignment; + } + /// \brief Determine whether this class is considered trivially copyable per /// (C++11 [class]p6). bool isTriviallyCopyable() const; @@ -1554,6 +1580,14 @@ public: static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); + /// \brief Base-class lookup callback that determines whether there exists + /// an OpenMP declare reduction member with the given name. + /// + /// This callback can be used with \c lookupInBases() to find members + /// of the given name within a C++ class hierarchy. + static bool FindOMPReductionMember(const CXXBaseSpecifier *Specifier, + CXXBasePath &Path, DeclarationName Name); + /// \brief Base-class lookup callback that determines whether there exists /// a member with the given name that can be used in a nested-name-specifier. /// @@ -1690,6 +1724,7 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend class ASTRecordWriter; friend class ASTReader; friend class ASTWriter; }; @@ -1795,6 +1830,8 @@ public: method_iterator begin_overridden_methods() const; method_iterator end_overridden_methods() const; unsigned size_overridden_methods() const; + typedef ASTContext::overridden_method_range overridden_method_range; + overridden_method_range overridden_methods() const; /// Returns the parent of this method declaration, which /// is the class in which this method is defined. @@ -1910,15 +1947,15 @@ class CXXCtorInitializer final /// \brief If the initializee is a type, whether that type makes this /// a delegating initialization. - bool IsDelegating : 1; + unsigned IsDelegating : 1; /// \brief If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. - bool IsVirtual : 1; + unsigned IsVirtual : 1; /// \brief Whether or not the initializer is explicitly written /// in the sources. - bool IsWritten : 1; + unsigned IsWritten : 1; /// If IsWritten is true, then this number keeps track of the textual order /// of this initializer in the original sources, counting from 0; otherwise, @@ -2109,8 +2146,7 @@ public: assert(I < getNumArrayIndices() && "Out of bounds member array index"); getTrailingObjects()[I] = Index; } - ArrayRef getArrayIndexes() { - assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init"); + ArrayRef getArrayIndices() { return llvm::makeArrayRef(getTrailingObjects(), getNumArrayIndices()); } @@ -2121,6 +2157,23 @@ public: friend TrailingObjects; }; +/// Description of a constructor that was inherited from a base class. +class InheritedConstructor { + ConstructorUsingShadowDecl *Shadow; + CXXConstructorDecl *BaseCtor; + +public: + InheritedConstructor() : Shadow(), BaseCtor() {} + InheritedConstructor(ConstructorUsingShadowDecl *Shadow, + CXXConstructorDecl *BaseCtor) + : Shadow(Shadow), BaseCtor(BaseCtor) {} + + explicit operator bool() const { return Shadow; } + + ConstructorUsingShadowDecl *getShadowDecl() const { return Shadow; } + CXXConstructorDecl *getConstructor() const { return BaseCtor; } +}; + /// \brief Represents a C++ constructor within a class. /// /// For example: @@ -2131,40 +2184,51 @@ public: /// explicit X(int); // represented by a CXXConstructorDecl. /// }; /// \endcode -class CXXConstructorDecl : public CXXMethodDecl { +class CXXConstructorDecl final + : public CXXMethodDecl, + private llvm::TrailingObjects { void anchor() override; - /// \brief Whether this constructor declaration has the \c explicit keyword - /// specified. - bool IsExplicitSpecified : 1; /// \name Support for base and member initializers. /// \{ /// \brief The arguments used to initialize the base or member. LazyCXXCtorInitializersPtr CtorInitializers; - unsigned NumCtorInitializers; + unsigned NumCtorInitializers : 30; /// \} + /// \brief Whether this constructor declaration has the \c explicit keyword + /// specified. + unsigned IsExplicitSpecified : 1; + + /// \brief Whether this constructor declaration is an implicitly-declared + /// inheriting constructor. + unsigned IsInheritingConstructor : 1; + CXXConstructorDecl(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, bool isExplicitSpecified, bool isInline, - bool isImplicitlyDeclared, bool isConstexpr) + bool isImplicitlyDeclared, bool isConstexpr, + InheritedConstructor Inherited) : CXXMethodDecl(CXXConstructor, C, RD, StartLoc, NameInfo, T, TInfo, SC_None, isInline, isConstexpr, SourceLocation()), - IsExplicitSpecified(isExplicitSpecified), CtorInitializers(nullptr), - NumCtorInitializers(0) { + CtorInitializers(nullptr), NumCtorInitializers(0), + IsExplicitSpecified(isExplicitSpecified), + IsInheritingConstructor((bool)Inherited) { setImplicit(isImplicitlyDeclared); + if (Inherited) + *getTrailingObjects() = Inherited; } public: - static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID); - static CXXConstructorDecl *Create(ASTContext &C, CXXRecordDecl *RD, - SourceLocation StartLoc, - const DeclarationNameInfo &NameInfo, - QualType T, TypeSourceInfo *TInfo, - bool isExplicit, - bool isInline, bool isImplicitlyDeclared, - bool isConstexpr); + static CXXConstructorDecl *CreateDeserialized(ASTContext &C, unsigned ID, + bool InheritsConstructor); + static CXXConstructorDecl * + Create(ASTContext &C, CXXRecordDecl *RD, SourceLocation StartLoc, + const DeclarationNameInfo &NameInfo, QualType T, TypeSourceInfo *TInfo, + bool isExplicit, bool isInline, bool isImplicitlyDeclared, + bool isConstexpr, + InheritedConstructor Inherited = InheritedConstructor()); /// \brief Determine whether this constructor declaration has the /// \c explicit keyword specified. @@ -2311,11 +2375,15 @@ public: /// an object. bool isSpecializationCopyingObject() const; - /// \brief Get the constructor that this inheriting constructor is based on. - const CXXConstructorDecl *getInheritedConstructor() const; + /// \brief Determine whether this is an implicit constructor synthesized to + /// model a call to a constructor inherited from a base class. + bool isInheritingConstructor() const { return IsInheritingConstructor; } - /// \brief Set the constructor that this inheriting constructor is based on. - void setInheritedConstructor(const CXXConstructorDecl *BaseCtor); + /// \brief Get the constructor that this inheriting constructor is based on. + InheritedConstructor getInheritedConstructor() const { + return IsInheritingConstructor ? *getTrailingObjects() + : InheritedConstructor(); + } CXXConstructorDecl *getCanonicalDecl() override { return cast(FunctionDecl::getCanonicalDecl()); @@ -2330,6 +2398,7 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; + friend TrailingObjects; }; /// \brief Represents a C++ destructor within a class. @@ -2774,18 +2843,6 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable { NamedDecl *UsingOrNextShadow; friend class UsingDecl; - UsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, - UsingDecl *Using, NamedDecl *Target) - : NamedDecl(UsingShadow, DC, Loc, DeclarationName()), - redeclarable_base(C), Underlying(Target), - UsingOrNextShadow(reinterpret_cast(Using)) { - if (Target) { - setDeclName(Target->getDeclName()); - IdentifierNamespace = Target->getIdentifierNamespace(); - } - setImplicit(); - } - typedef Redeclarable redeclarable_base; UsingShadowDecl *getNextRedeclarationImpl() override { return getNextRedeclaration(); @@ -2797,11 +2854,16 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable { return getMostRecentDecl(); } +protected: + UsingShadowDecl(Kind K, ASTContext &C, DeclContext *DC, SourceLocation Loc, + UsingDecl *Using, NamedDecl *Target); + UsingShadowDecl(Kind K, ASTContext &C, EmptyShell); + public: static UsingShadowDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation Loc, UsingDecl *Using, NamedDecl *Target) { - return new (C, DC) UsingShadowDecl(C, DC, Loc, Using, Target); + return new (C, DC) UsingShadowDecl(UsingShadow, C, DC, Loc, Using, Target); } static UsingShadowDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2813,6 +2875,7 @@ public: using redeclarable_base::redecls; using redeclarable_base::getPreviousDecl; using redeclarable_base::getMostRecentDecl; + using redeclarable_base::isFirstDecl; UsingShadowDecl *getCanonicalDecl() override { return getFirstDecl(); @@ -2843,7 +2906,125 @@ public: } static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == Decl::UsingShadow; } + static bool classofKind(Kind K) { + return K == Decl::UsingShadow || K == Decl::ConstructorUsingShadow; + } + + friend class ASTDeclReader; + friend class ASTDeclWriter; +}; + +/// \brief Represents a shadow constructor declaration introduced into a +/// class by a C++11 using-declaration that names a constructor. +/// +/// For example: +/// \code +/// struct Base { Base(int); }; +/// struct Derived { +/// using Base::Base; // creates a UsingDecl and a ConstructorUsingShadowDecl +/// }; +/// \endcode +class ConstructorUsingShadowDecl final : public UsingShadowDecl { + void anchor() override; + + /// \brief If this constructor using declaration inherted the constructor + /// from an indirect base class, this is the ConstructorUsingShadowDecl + /// in the named direct base class from which the declaration was inherited. + ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl; + + /// \brief If this constructor using declaration inherted the constructor + /// from an indirect base class, this is the ConstructorUsingShadowDecl + /// that will be used to construct the unique direct or virtual base class + /// that receives the constructor arguments. + ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl; + + /// \brief \c true if the constructor ultimately named by this using shadow + /// declaration is within a virtual base class subobject of the class that + /// contains this declaration. + unsigned IsVirtual : 1; + + ConstructorUsingShadowDecl(ASTContext &C, DeclContext *DC, SourceLocation Loc, + UsingDecl *Using, NamedDecl *Target, + bool TargetInVirtualBase) + : UsingShadowDecl(ConstructorUsingShadow, C, DC, Loc, Using, + Target->getUnderlyingDecl()), + NominatedBaseClassShadowDecl( + dyn_cast(Target)), + ConstructedBaseClassShadowDecl(NominatedBaseClassShadowDecl), + IsVirtual(TargetInVirtualBase) { + // If we found a constructor for a non-virtual base class, but it chains to + // a constructor for a virtual base, we should directly call the virtual + // base constructor instead. + // FIXME: This logic belongs in Sema. + if (!TargetInVirtualBase && NominatedBaseClassShadowDecl && + NominatedBaseClassShadowDecl->constructsVirtualBase()) { + ConstructedBaseClassShadowDecl = + NominatedBaseClassShadowDecl->ConstructedBaseClassShadowDecl; + IsVirtual = true; + } + } + ConstructorUsingShadowDecl(ASTContext &C, EmptyShell Empty) + : UsingShadowDecl(ConstructorUsingShadow, C, Empty) {} + +public: + static ConstructorUsingShadowDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation Loc, + UsingDecl *Using, NamedDecl *Target, + bool IsVirtual); + static ConstructorUsingShadowDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + /// Returns the parent of this using shadow declaration, which + /// is the class in which this is declared. + //@{ + const CXXRecordDecl *getParent() const { + return cast(getDeclContext()); + } + CXXRecordDecl *getParent() { + return cast(getDeclContext()); + } + //@} + + /// \brief Get the inheriting constructor declaration for the direct base + /// class from which this using shadow declaration was inherited, if there is + /// one. This can be different for each redeclaration of the same shadow decl. + ConstructorUsingShadowDecl *getNominatedBaseClassShadowDecl() const { + return NominatedBaseClassShadowDecl; + } + + /// \brief Get the inheriting constructor declaration for the base class + /// for which we don't have an explicit initializer, if there is one. + ConstructorUsingShadowDecl *getConstructedBaseClassShadowDecl() const { + return ConstructedBaseClassShadowDecl; + } + + /// \brief Get the base class that was named in the using declaration. This + /// can be different for each redeclaration of this same shadow decl. + CXXRecordDecl *getNominatedBaseClass() const; + + /// \brief Get the base class whose constructor or constructor shadow + /// declaration is passed the constructor arguments. + CXXRecordDecl *getConstructedBaseClass() const { + return cast((ConstructedBaseClassShadowDecl + ? ConstructedBaseClassShadowDecl + : getTargetDecl()) + ->getDeclContext()); + } + + /// \brief Returns \c true if the constructed base class is a virtual base + /// class subobject of this declaration's class. + bool constructsVirtualBase() const { + return IsVirtual; + } + + /// \brief Get the constructor or constructor template in the derived class + /// correspnding to this using shadow declaration, if it has been implicitly + /// declared already. + CXXConstructorDecl *getConstructor() const; + void setConstructor(NamedDecl *Ctor); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == ConstructorUsingShadow; } friend class ASTDeclReader; friend class ASTDeclWriter; diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 27b0388007a1c..5b2e2d9915eb1 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -57,7 +57,7 @@ private: /// True if this 'friend' declaration is unsupported. Eventually we /// will support every possible friend declaration, but for now we /// silently ignore some and set this flag to authorize all access. - bool UnsupportedFriend : 1; + unsigned UnsupportedFriend : 1; // The number of "outer" template parameter lists in non-templatic // (currently unsupported) friend type declarations, such as diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index f46078f28a7d8..ad9b5a26b7c86 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -351,11 +351,6 @@ public: typedef llvm::iterator_range param_range; typedef llvm::iterator_range param_const_range; - param_range params() { return param_range(param_begin(), param_end()); } - param_const_range params() const { - return param_const_range(param_begin(), param_end()); - } - param_const_iterator param_begin() const { return param_const_iterator(getParams()); } @@ -689,6 +684,216 @@ public: friend TrailingObjects; }; +enum class ObjCPropertyQueryKind : uint8_t { + OBJC_PR_query_unknown = 0x00, + OBJC_PR_query_instance, + OBJC_PR_query_class +}; + +/// \brief Represents one property declaration in an Objective-C interface. +/// +/// For example: +/// \code{.mm} +/// \@property (assign, readwrite) int MyProperty; +/// \endcode +class ObjCPropertyDecl : public NamedDecl { + void anchor() override; +public: + enum PropertyAttributeKind { + OBJC_PR_noattr = 0x00, + OBJC_PR_readonly = 0x01, + OBJC_PR_getter = 0x02, + OBJC_PR_assign = 0x04, + OBJC_PR_readwrite = 0x08, + OBJC_PR_retain = 0x10, + OBJC_PR_copy = 0x20, + OBJC_PR_nonatomic = 0x40, + OBJC_PR_setter = 0x80, + OBJC_PR_atomic = 0x100, + OBJC_PR_weak = 0x200, + OBJC_PR_strong = 0x400, + OBJC_PR_unsafe_unretained = 0x800, + /// Indicates that the nullability of the type was spelled with a + /// property attribute rather than a type qualifier. + OBJC_PR_nullability = 0x1000, + OBJC_PR_null_resettable = 0x2000, + OBJC_PR_class = 0x4000 + // Adding a property should change NumPropertyAttrsBits + }; + + enum { + /// \brief Number of bits fitting all the property attributes. + NumPropertyAttrsBits = 15 + }; + + enum SetterKind { Assign, Retain, Copy, Weak }; + enum PropertyControl { None, Required, Optional }; +private: + SourceLocation AtLoc; // location of \@property + SourceLocation LParenLoc; // location of '(' starting attribute list or null. + QualType DeclType; + TypeSourceInfo *DeclTypeSourceInfo; + unsigned PropertyAttributes : NumPropertyAttrsBits; + unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; + // \@required/\@optional + unsigned PropertyImplementation : 2; + + Selector GetterName; // getter name of NULL if no getter + Selector SetterName; // setter name of NULL if no setter + + ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method + ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method + ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property + + ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, + SourceLocation AtLocation, SourceLocation LParenLocation, + QualType T, TypeSourceInfo *TSI, + PropertyControl propControl) + : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), + LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), + PropertyAttributes(OBJC_PR_noattr), + PropertyAttributesAsWritten(OBJC_PR_noattr), + PropertyImplementation(propControl), + GetterName(Selector()), + SetterName(Selector()), + GetterMethodDecl(nullptr), SetterMethodDecl(nullptr), + PropertyIvarDecl(nullptr) {} + +public: + static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation L, + IdentifierInfo *Id, SourceLocation AtLocation, + SourceLocation LParenLocation, + QualType T, + TypeSourceInfo *TSI, + PropertyControl propControl = None); + + static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + SourceLocation getAtLoc() const { return AtLoc; } + void setAtLoc(SourceLocation L) { AtLoc = L; } + + SourceLocation getLParenLoc() const { return LParenLoc; } + void setLParenLoc(SourceLocation L) { LParenLoc = L; } + + TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; } + + QualType getType() const { return DeclType; } + + void setType(QualType T, TypeSourceInfo *TSI) { + DeclType = T; + DeclTypeSourceInfo = TSI; + } + + /// Retrieve the type when this property is used with a specific base object + /// type. + QualType getUsageType(QualType objectType) const; + + PropertyAttributeKind getPropertyAttributes() const { + return PropertyAttributeKind(PropertyAttributes); + } + void setPropertyAttributes(PropertyAttributeKind PRVal) { + PropertyAttributes |= PRVal; + } + void overwritePropertyAttributes(unsigned PRVal) { + PropertyAttributes = PRVal; + } + + PropertyAttributeKind getPropertyAttributesAsWritten() const { + return PropertyAttributeKind(PropertyAttributesAsWritten); + } + + void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { + PropertyAttributesAsWritten = PRVal; + } + + // Helper methods for accessing attributes. + + /// isReadOnly - Return true iff the property has a setter. + bool isReadOnly() const { + return (PropertyAttributes & OBJC_PR_readonly); + } + + /// isAtomic - Return true if the property is atomic. + bool isAtomic() const { + return (PropertyAttributes & OBJC_PR_atomic); + } + + /// isRetaining - Return true if the property retains its value. + bool isRetaining() const { + return (PropertyAttributes & + (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy)); + } + + bool isInstanceProperty() const { return !isClassProperty(); } + bool isClassProperty() const { return PropertyAttributes & OBJC_PR_class; } + ObjCPropertyQueryKind getQueryKind() const { + return isClassProperty() ? ObjCPropertyQueryKind::OBJC_PR_query_class : + ObjCPropertyQueryKind::OBJC_PR_query_instance; + } + static ObjCPropertyQueryKind getQueryKind(bool isClassProperty) { + return isClassProperty ? ObjCPropertyQueryKind::OBJC_PR_query_class : + ObjCPropertyQueryKind::OBJC_PR_query_instance; + } + + /// getSetterKind - Return the method used for doing assignment in + /// the property setter. This is only valid if the property has been + /// defined to have a setter. + SetterKind getSetterKind() const { + if (PropertyAttributes & OBJC_PR_strong) + return getType()->isBlockPointerType() ? Copy : Retain; + if (PropertyAttributes & OBJC_PR_retain) + return Retain; + if (PropertyAttributes & OBJC_PR_copy) + return Copy; + if (PropertyAttributes & OBJC_PR_weak) + return Weak; + return Assign; + } + + Selector getGetterName() const { return GetterName; } + void setGetterName(Selector Sel) { GetterName = Sel; } + + Selector getSetterName() const { return SetterName; } + void setSetterName(Selector Sel) { SetterName = Sel; } + + ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } + void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } + + ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } + void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } + + // Related to \@optional/\@required declared in \@protocol + void setPropertyImplementation(PropertyControl pc) { + PropertyImplementation = pc; + } + PropertyControl getPropertyImplementation() const { + return PropertyControl(PropertyImplementation); + } + + void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { + PropertyIvarDecl = Ivar; + } + ObjCIvarDecl *getPropertyIvarDecl() const { + return PropertyIvarDecl; + } + + SourceRange getSourceRange() const override LLVM_READONLY { + return SourceRange(AtLoc, getLocation()); + } + + /// Get the default name of the synthesized ivar. + IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const; + + /// Lookup a property by name in the specified DeclContext. + static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, + const IdentifierInfo *propertyID, + ObjCPropertyQueryKind queryKind); + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == ObjCProperty; } +}; + /// ObjCContainerDecl - Represents a container for method declarations. /// Current sub-classes are ObjCInterfaceDecl, ObjCCategoryDecl, /// ObjCProtocolDecl, and ObjCImplDecl. @@ -708,7 +913,7 @@ public: SourceLocation atStartLoc) : NamedDecl(DK, DC, nameLoc, Id), DeclContext(DK), AtStart(atStartLoc) {} - // Iterator access to properties. + // Iterator access to instance/class properties. typedef specific_decl_iterator prop_iterator; typedef llvm::iterator_range> prop_range; @@ -721,6 +926,36 @@ public: return prop_iterator(decls_end()); } + typedef filtered_decl_iterator + instprop_iterator; + typedef llvm::iterator_range instprop_range; + + instprop_range instance_properties() const { + return instprop_range(instprop_begin(), instprop_end()); + } + instprop_iterator instprop_begin() const { + return instprop_iterator(decls_begin()); + } + instprop_iterator instprop_end() const { + return instprop_iterator(decls_end()); + } + + typedef filtered_decl_iterator + classprop_iterator; + typedef llvm::iterator_range classprop_range; + + classprop_range class_properties() const { + return classprop_range(classprop_begin(), classprop_end()); + } + classprop_iterator classprop_begin() const { + return classprop_iterator(decls_begin()); + } + classprop_iterator classprop_end() const { + return classprop_iterator(decls_end()); + } + // Iterator access to instance/class methods. typedef specific_decl_iterator method_iterator; typedef llvm::iterator_range> @@ -780,9 +1015,12 @@ public: ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; ObjCPropertyDecl * - FindPropertyDeclaration(const IdentifierInfo *PropertyId) const; + FindPropertyDeclaration(const IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const; - typedef llvm::DenseMap PropertyMap; + typedef llvm::DenseMap, + ObjCPropertyDecl*> PropertyMap; typedef llvm::DenseMap ProtocolPropertyMap; @@ -886,15 +1124,15 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// \brief Indicates that the contents of this Objective-C class will be /// completed by the external AST source when required. - mutable bool ExternallyCompleted : 1; + mutable unsigned ExternallyCompleted : 1; /// \brief Indicates that the ivar cache does not yet include ivars /// declared in the implementation. - mutable bool IvarListMissingImplementation : 1; + mutable unsigned IvarListMissingImplementation : 1; /// Indicates that this interface decl contains at least one initializer /// marked with the 'objc_designated_initializer' attribute. - bool HasDesignatedInitializers : 1; + unsigned HasDesignatedInitializers : 1; enum InheritedDesignatedInitializersState { /// We didn't calculate whether the designated initializers should be @@ -1463,7 +1701,8 @@ public: } ObjCPropertyDecl - *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId) const; + *FindPropertyVisibleInPrimaryClass(IdentifierInfo *PropertyId, + ObjCPropertyQueryKind QueryKind) const; void collectPropertiesToImplement(PropertyMap &PM, PropertyDeclOrder &PO) const override; @@ -1529,8 +1768,9 @@ public: /// including in all categories except for category passed /// as argument. ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, - const ObjCCategoryDecl *Cat) const { - return lookupMethod(Sel, true/*isInstance*/, + const ObjCCategoryDecl *Cat, + bool IsClassProperty) const { + return lookupMethod(Sel, !IsClassProperty/*isInstance*/, false/*shallowCategoryLookup*/, true /* followsSuper */, Cat); @@ -2099,7 +2339,8 @@ public: void addPropertyImplementation(ObjCPropertyImplDecl *property); - ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId) const; + ObjCPropertyImplDecl *FindPropertyImplDecl(IdentifierInfo *propertyId, + ObjCPropertyQueryKind queryKind) const; ObjCPropertyImplDecl *FindPropertyImplIvarDecl(IdentifierInfo *ivarId) const; // Iterator access to properties. @@ -2407,197 +2648,6 @@ public: }; -/// \brief Represents one property declaration in an Objective-C interface. -/// -/// For example: -/// \code{.mm} -/// \@property (assign, readwrite) int MyProperty; -/// \endcode -class ObjCPropertyDecl : public NamedDecl { - void anchor() override; -public: - enum PropertyAttributeKind { - OBJC_PR_noattr = 0x00, - OBJC_PR_readonly = 0x01, - OBJC_PR_getter = 0x02, - OBJC_PR_assign = 0x04, - OBJC_PR_readwrite = 0x08, - OBJC_PR_retain = 0x10, - OBJC_PR_copy = 0x20, - OBJC_PR_nonatomic = 0x40, - OBJC_PR_setter = 0x80, - OBJC_PR_atomic = 0x100, - OBJC_PR_weak = 0x200, - OBJC_PR_strong = 0x400, - OBJC_PR_unsafe_unretained = 0x800, - /// Indicates that the nullability of the type was spelled with a - /// property attribute rather than a type qualifier. - OBJC_PR_nullability = 0x1000, - OBJC_PR_null_resettable = 0x2000 - // Adding a property should change NumPropertyAttrsBits - }; - - enum { - /// \brief Number of bits fitting all the property attributes. - NumPropertyAttrsBits = 14 - }; - - enum SetterKind { Assign, Retain, Copy, Weak }; - enum PropertyControl { None, Required, Optional }; -private: - SourceLocation AtLoc; // location of \@property - SourceLocation LParenLoc; // location of '(' starting attribute list or null. - QualType DeclType; - TypeSourceInfo *DeclTypeSourceInfo; - unsigned PropertyAttributes : NumPropertyAttrsBits; - unsigned PropertyAttributesAsWritten : NumPropertyAttrsBits; - // \@required/\@optional - unsigned PropertyImplementation : 2; - - Selector GetterName; // getter name of NULL if no getter - Selector SetterName; // setter name of NULL if no setter - - ObjCMethodDecl *GetterMethodDecl; // Declaration of getter instance method - ObjCMethodDecl *SetterMethodDecl; // Declaration of setter instance method - ObjCIvarDecl *PropertyIvarDecl; // Synthesize ivar for this property - - ObjCPropertyDecl(DeclContext *DC, SourceLocation L, IdentifierInfo *Id, - SourceLocation AtLocation, SourceLocation LParenLocation, - QualType T, TypeSourceInfo *TSI, - PropertyControl propControl) - : NamedDecl(ObjCProperty, DC, L, Id), AtLoc(AtLocation), - LParenLoc(LParenLocation), DeclType(T), DeclTypeSourceInfo(TSI), - PropertyAttributes(OBJC_PR_noattr), - PropertyAttributesAsWritten(OBJC_PR_noattr), - PropertyImplementation(propControl), - GetterName(Selector()), - SetterName(Selector()), - GetterMethodDecl(nullptr), SetterMethodDecl(nullptr), - PropertyIvarDecl(nullptr) {} - -public: - static ObjCPropertyDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation L, - IdentifierInfo *Id, SourceLocation AtLocation, - SourceLocation LParenLocation, - QualType T, - TypeSourceInfo *TSI, - PropertyControl propControl = None); - - static ObjCPropertyDecl *CreateDeserialized(ASTContext &C, unsigned ID); - - SourceLocation getAtLoc() const { return AtLoc; } - void setAtLoc(SourceLocation L) { AtLoc = L; } - - SourceLocation getLParenLoc() const { return LParenLoc; } - void setLParenLoc(SourceLocation L) { LParenLoc = L; } - - TypeSourceInfo *getTypeSourceInfo() const { return DeclTypeSourceInfo; } - - QualType getType() const { return DeclType; } - - void setType(QualType T, TypeSourceInfo *TSI) { - DeclType = T; - DeclTypeSourceInfo = TSI; - } - - /// Retrieve the type when this property is used with a specific base object - /// type. - QualType getUsageType(QualType objectType) const; - - PropertyAttributeKind getPropertyAttributes() const { - return PropertyAttributeKind(PropertyAttributes); - } - void setPropertyAttributes(PropertyAttributeKind PRVal) { - PropertyAttributes |= PRVal; - } - void overwritePropertyAttributes(unsigned PRVal) { - PropertyAttributes = PRVal; - } - - PropertyAttributeKind getPropertyAttributesAsWritten() const { - return PropertyAttributeKind(PropertyAttributesAsWritten); - } - - void setPropertyAttributesAsWritten(PropertyAttributeKind PRVal) { - PropertyAttributesAsWritten = PRVal; - } - - // Helper methods for accessing attributes. - - /// isReadOnly - Return true iff the property has a setter. - bool isReadOnly() const { - return (PropertyAttributes & OBJC_PR_readonly); - } - - /// isAtomic - Return true if the property is atomic. - bool isAtomic() const { - return (PropertyAttributes & OBJC_PR_atomic); - } - - /// isRetaining - Return true if the property retains its value. - bool isRetaining() const { - return (PropertyAttributes & - (OBJC_PR_retain | OBJC_PR_strong | OBJC_PR_copy)); - } - - /// getSetterKind - Return the method used for doing assignment in - /// the property setter. This is only valid if the property has been - /// defined to have a setter. - SetterKind getSetterKind() const { - if (PropertyAttributes & OBJC_PR_strong) - return getType()->isBlockPointerType() ? Copy : Retain; - if (PropertyAttributes & OBJC_PR_retain) - return Retain; - if (PropertyAttributes & OBJC_PR_copy) - return Copy; - if (PropertyAttributes & OBJC_PR_weak) - return Weak; - return Assign; - } - - Selector getGetterName() const { return GetterName; } - void setGetterName(Selector Sel) { GetterName = Sel; } - - Selector getSetterName() const { return SetterName; } - void setSetterName(Selector Sel) { SetterName = Sel; } - - ObjCMethodDecl *getGetterMethodDecl() const { return GetterMethodDecl; } - void setGetterMethodDecl(ObjCMethodDecl *gDecl) { GetterMethodDecl = gDecl; } - - ObjCMethodDecl *getSetterMethodDecl() const { return SetterMethodDecl; } - void setSetterMethodDecl(ObjCMethodDecl *gDecl) { SetterMethodDecl = gDecl; } - - // Related to \@optional/\@required declared in \@protocol - void setPropertyImplementation(PropertyControl pc) { - PropertyImplementation = pc; - } - PropertyControl getPropertyImplementation() const { - return PropertyControl(PropertyImplementation); - } - - void setPropertyIvarDecl(ObjCIvarDecl *Ivar) { - PropertyIvarDecl = Ivar; - } - ObjCIvarDecl *getPropertyIvarDecl() const { - return PropertyIvarDecl; - } - - SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(AtLoc, getLocation()); - } - - /// Get the default name of the synthesized ivar. - IdentifierInfo *getDefaultSynthIvarName(ASTContext &Ctx) const; - - /// Lookup a property by name in the specified DeclContext. - static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, - const IdentifierInfo *propertyID); - - static bool classof(const Decl *D) { return classofKind(D->getKind()); } - static bool classofKind(Kind K) { return K == ObjCProperty; } -}; - /// ObjCPropertyImplDecl - Represents implementation declaration of a property /// in a class or category implementation block. For example: /// \@synthesize prop1 = ivar1; diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index 598f418f7e355..1975bc551ca52 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -15,11 +15,14 @@ #ifndef LLVM_CLANG_AST_DECLOPENMP_H #define LLVM_CLANG_AST_DECLOPENMP_H -#include "clang/AST/DeclBase.h" +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/Type.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/TrailingObjects.h" namespace clang { -class Expr; /// \brief This represents '#pragma omp threadprivate ...' directive. /// For example, in the following, both 'a' and 'A::b' are threadprivate: @@ -86,6 +89,107 @@ public: static bool classofKind(Kind K) { return K == OMPThreadPrivate; } }; -} // end namespace clang +/// \brief This represents '#pragma omp declare reduction ...' directive. +/// For example, in the following, declared reduction 'foo' for types 'int' and +/// 'float': +/// +/// \code +/// #pragma omp declare reduction (foo : int,float : omp_out += omp_in) \ +/// initializer (omp_priv = 0) +/// \endcode +/// +/// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. +class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { +private: + friend class ASTDeclReader; + /// \brief Combiner for declare reduction construct. + Expr *Combiner; + /// \brief Initializer for declare reduction construct. + Expr *Initializer; + /// \brief Reference to the previous declare reduction construct in the same + /// scope with the same name. Required for proper templates instantiation if + /// the declare reduction construct is declared inside compound statement. + LazyDeclPtr PrevDeclInScope; + + virtual void anchor(); + + OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L, + DeclarationName Name, QualType Ty, + OMPDeclareReductionDecl *PrevDeclInScope) + : ValueDecl(DK, DC, L, Name, Ty), DeclContext(DK), Combiner(nullptr), + Initializer(nullptr), PrevDeclInScope(PrevDeclInScope) {} + + void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { + PrevDeclInScope = Prev; + } + +public: + /// \brief Create declare reduction node. + static OMPDeclareReductionDecl * + Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, + QualType T, OMPDeclareReductionDecl *PrevDeclInScope); + /// \brief Create deserialized declare reduction node. + static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, + unsigned ID); + + /// \brief Get combiner expression of the declare reduction construct. + Expr *getCombiner() { return Combiner; } + const Expr *getCombiner() const { return Combiner; } + /// \brief Set combiner expression for the declare reduction construct. + void setCombiner(Expr *E) { Combiner = E; } + + /// \brief Get initializer expression (if specified) of the declare reduction + /// construct. + Expr *getInitializer() { return Initializer; } + const Expr *getInitializer() const { return Initializer; } + /// \brief Set initializer expression for the declare reduction construct. + void setInitializer(Expr *E) { Initializer = E; } + + /// \brief Get reference to previous declare reduction construct in the same + /// scope with the same name. + OMPDeclareReductionDecl *getPrevDeclInScope(); + const OMPDeclareReductionDecl *getPrevDeclInScope() const; + + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == OMPDeclareReduction; } + static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) { + return static_cast(const_cast(D)); + } + static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast( + const_cast(DC)); + } +}; + +/// Pseudo declaration for capturing expressions. Also is used for capturing of +/// non-static data members in non-static member functions. +/// +/// Clang supports capturing of variables only, but OpenMP 4.5 allows to +/// privatize non-static members of current class in non-static member +/// functions. This pseudo-declaration allows properly handle this kind of +/// capture by wrapping captured expression into a variable-like declaration. +class OMPCapturedExprDecl final : public VarDecl { + friend class ASTDeclReader; + void anchor() override; + + OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, + QualType Type) + : VarDecl(OMPCapturedExpr, C, DC, SourceLocation(), SourceLocation(), Id, + Type, nullptr, SC_None) { + setImplicit(); + } + +public: + static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC, + IdentifierInfo *Id, QualType T); + + static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + // Implement isa/cast/dyncast/etc. + static bool classof(const Decl *D) { return classofKind(D->getKind()); } + static bool classofKind(Kind K) { return K == OMPCapturedExpr; } +}; + +} // end namespace clang #endif diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index a9109ef114264..4ac8cdc9beeb1 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -22,6 +22,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" #include +#include namespace clang { @@ -183,7 +184,7 @@ class TemplateArgumentList final // Constructs an instance with an internal Argument list, containing // a copy of the Args array. (Called by CreateCopy) - TemplateArgumentList(const TemplateArgument *Args, unsigned NumArgs); + TemplateArgumentList(ArrayRef Args); public: /// \brief Type used to indicate that the template argument list itself is a @@ -193,16 +194,14 @@ public: /// \brief Create a new template argument list that copies the given set of /// template arguments. static TemplateArgumentList *CreateCopy(ASTContext &Context, - const TemplateArgument *Args, - unsigned NumArgs); + ArrayRef Args); /// \brief Construct a new, temporary template argument list on the stack. /// /// The template argument list does not own the template arguments /// provided. - explicit TemplateArgumentList(OnStackType, const TemplateArgument *Args, - unsigned NumArgs) - : Arguments(Args), NumArguments(NumArgs) {} + explicit TemplateArgumentList(OnStackType, ArrayRef Args) + : Arguments(Args.data()), NumArguments(Args.size()) {} /// \brief Produces a shallow copy of the given template argument list. /// @@ -332,24 +331,23 @@ class TemplateDecl : public NamedDecl { void anchor() override; protected: // This is probably never used. - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), - TemplateParams(nullptr) {} + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), + TemplateParams(nullptr) {} // Construct a template decl with the given name and parameters. // Used when there is not templated element (tt-params). - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr), - TemplateParams(Params) {} + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(nullptr, false), + TemplateParams(Params) {} // Construct a template decl with name, parameters, and templated element. - TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, - DeclarationName Name, TemplateParameterList *Params, - NamedDecl *Decl) - : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl), - TemplateParams(Params) { } + TemplateDecl(Kind DK, DeclContext *DC, SourceLocation L, DeclarationName Name, + TemplateParameterList *Params, NamedDecl *Decl) + : NamedDecl(DK, DC, L, Name), TemplatedDecl(Decl, false), + TemplateParams(Params) {} + public: /// Get the list of template parameters TemplateParameterList *getTemplateParameters() const { @@ -357,7 +355,7 @@ public: } /// Get the underlying, templated declaration. - NamedDecl *getTemplatedDecl() const { return TemplatedDecl; } + NamedDecl *getTemplatedDecl() const { return TemplatedDecl.getPointer(); } // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -367,20 +365,30 @@ public: SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(TemplateParams->getTemplateLoc(), - TemplatedDecl->getSourceRange().getEnd()); + TemplatedDecl.getPointer()->getSourceRange().getEnd()); } + /// Whether this is a (C++ Concepts TS) function or variable concept. + bool isConcept() const { return TemplatedDecl.getInt(); } + void setConcept() { TemplatedDecl.setInt(true); } + protected: - NamedDecl *TemplatedDecl; + /// \brief The named declaration from which this template was instantiated. + /// (or null). + /// + /// The boolean value will be true to indicate that this template + /// (function or variable) is a concept. + llvm::PointerIntPair TemplatedDecl; + TemplateParameterList* TemplateParams; public: /// \brief Initialize the underlying templated declaration and /// template parameters. void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { - assert(!TemplatedDecl && "TemplatedDecl already set!"); + assert(!TemplatedDecl.getPointer() && "TemplatedDecl already set!"); assert(!TemplateParams && "TemplateParams already set!"); - TemplatedDecl = templatedDecl; + TemplatedDecl.setPointer(templatedDecl); TemplateParams = templateParams; } }; @@ -481,8 +489,8 @@ public: Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); - for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) - TemplateArgs[Arg].Profile(ID, Context); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); } }; @@ -889,7 +897,7 @@ public: /// Get the underlying function declaration of the template. FunctionDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl); + return static_cast(TemplatedDecl.getPointer()); } /// Returns whether this template declaration defines the primary @@ -1171,9 +1179,8 @@ class NonTypeTemplateParmDecl final SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, QualType T, TypeSourceInfo *TInfo, - const QualType *ExpandedTypes, - unsigned NumExpandedTypes, - TypeSourceInfo **ExpandedTInfos); + ArrayRef ExpandedTypes, + ArrayRef ExpandedTInfos); friend class ASTDeclReader; friend TrailingObjects; @@ -1187,9 +1194,8 @@ public: static NonTypeTemplateParmDecl * Create(const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, unsigned D, unsigned P, IdentifierInfo *Id, - QualType T, TypeSourceInfo *TInfo, - const QualType *ExpandedTypes, unsigned NumExpandedTypes, - TypeSourceInfo **ExpandedTInfos); + QualType T, TypeSourceInfo *TInfo, ArrayRef ExpandedTypes, + ArrayRef ExpandedTInfos); static NonTypeTemplateParmDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -1352,8 +1358,7 @@ class TemplateTemplateParmDecl final TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, unsigned D, unsigned P, IdentifierInfo *Id, TemplateParameterList *Params, - unsigned NumExpansions, - TemplateParameterList * const *Expansions); + ArrayRef Expansions); public: static TemplateTemplateParmDecl *Create(const ASTContext &C, DeclContext *DC, @@ -1480,8 +1485,8 @@ public: }; /// \brief Represents the builtin template declaration which is used to -/// implement __make_integer_seq. It serves no real purpose beyond existing as -/// a place to hold template parameters. +/// implement __make_integer_seq and other builtin templates. It serves +/// no real purpose beyond existing as a place to hold template parameters. class BuiltinTemplateDecl : public TemplateDecl { void anchor() override; @@ -1573,8 +1578,7 @@ protected: DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, ClassTemplateSpecializationDecl *PrevDecl); explicit ClassTemplateSpecializationDecl(ASTContext &C, Kind DK); @@ -1584,8 +1588,7 @@ public: Create(ASTContext &Context, TagKind TK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, ClassTemplateSpecializationDecl *PrevDecl); static ClassTemplateSpecializationDecl * CreateDeserialized(ASTContext &C, unsigned ID); @@ -1762,8 +1765,8 @@ public: Profile(llvm::FoldingSetNodeID &ID, ArrayRef TemplateArgs, ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); - for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) - TemplateArgs[Arg].Profile(ID, Context); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); } static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1801,8 +1804,7 @@ class ClassTemplatePartialSpecializationDecl SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, const ASTTemplateArgumentListInfo *ArgsAsWritten, ClassTemplatePartialSpecializationDecl *PrevDecl); @@ -1817,8 +1819,7 @@ public: SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, ClassTemplateDecl *SpecializedTemplate, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, const TemplateArgumentListInfo &ArgInfos, QualType CanonInjectedType, ClassTemplatePartialSpecializationDecl *PrevDecl); @@ -1867,6 +1868,10 @@ public: cast(getFirstDecl()); return First->InstantiatedFromMember.getPointer(); } + ClassTemplatePartialSpecializationDecl * + getInstantiatedFromMemberTemplate() const { + return getInstantiatedFromMember(); + } void setInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *PartialSpec) { @@ -1982,7 +1987,7 @@ public: /// \brief Get the underlying class declarations of the template. CXXRecordDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl); + return static_cast(TemplatedDecl.getPointer()); } /// \brief Returns whether this template declaration defines the primary @@ -2154,18 +2159,11 @@ private: // Location of the 'friend' specifier. SourceLocation FriendLoc; - FriendTemplateDecl(DeclContext *DC, SourceLocation Loc, - unsigned NParams, - TemplateParameterList **Params, - FriendUnion Friend, - SourceLocation FriendLoc) - : Decl(Decl::FriendTemplate, DC, Loc), - NumParams(NParams), - Params(Params), - Friend(Friend), - FriendLoc(FriendLoc) - {} + MutableArrayRef Params, + FriendUnion Friend, SourceLocation FriendLoc) + : Decl(Decl::FriendTemplate, DC, Loc), NumParams(Params.size()), + Params(Params.data()), Friend(Friend), FriendLoc(FriendLoc) {} FriendTemplateDecl(EmptyShell Empty) : Decl(Decl::FriendTemplate, Empty), @@ -2174,12 +2172,10 @@ private: {} public: - static FriendTemplateDecl *Create(ASTContext &Context, - DeclContext *DC, SourceLocation Loc, - unsigned NParams, - TemplateParameterList **Params, - FriendUnion Friend, - SourceLocation FriendLoc); + static FriendTemplateDecl * + Create(ASTContext &Context, DeclContext *DC, SourceLocation Loc, + MutableArrayRef Params, FriendUnion Friend, + SourceLocation FriendLoc); static FriendTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2245,7 +2241,7 @@ protected: public: /// Get the underlying function declaration of the template. TypeAliasDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl); + return static_cast(TemplatedDecl.getPointer()); } @@ -2319,9 +2315,9 @@ class ClassScopeFunctionSpecializationDecl : public Decl { ClassScopeFunctionSpecializationDecl(DeclContext *DC, SourceLocation Loc, CXXMethodDecl *FD, bool Args, TemplateArgumentListInfo TemplArgs) - : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), - Specialization(FD), HasExplicitTemplateArgs(Args), - TemplateArgs(TemplArgs) {} + : Decl(Decl::ClassScopeFunctionSpecialization, DC, Loc), + Specialization(FD), HasExplicitTemplateArgs(Args), + TemplateArgs(std::move(TemplArgs)) {} ClassScopeFunctionSpecializationDecl(EmptyShell Empty) : Decl(Decl::ClassScopeFunctionSpecialization, Empty) {} @@ -2342,7 +2338,7 @@ public: bool HasExplicitTemplateArgs, TemplateArgumentListInfo TemplateArgs) { return new (C, DC) ClassScopeFunctionSpecializationDecl( - DC, Loc, FD, HasExplicitTemplateArgs, TemplateArgs); + DC, Loc, FD, HasExplicitTemplateArgs, std::move(TemplateArgs)); } static ClassScopeFunctionSpecializationDecl * @@ -2428,8 +2424,8 @@ protected: SourceLocation StartLoc, SourceLocation IdLoc, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, const TemplateArgument *Args, - unsigned NumArgs); + StorageClass S, + ArrayRef Args); explicit VarTemplateSpecializationDecl(Kind DK, ASTContext &Context); @@ -2437,8 +2433,8 @@ 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); + TypeSourceInfo *TInfo, StorageClass S, + ArrayRef Args); static VarTemplateSpecializationDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2502,17 +2498,11 @@ public: /// it was instantiated. llvm::PointerUnion getInstantiatedFrom() const { - if (getSpecializationKind() != TSK_ImplicitInstantiation && - getSpecializationKind() != TSK_ExplicitInstantiationDefinition && - getSpecializationKind() != TSK_ExplicitInstantiationDeclaration) + if (!isTemplateInstantiation(getSpecializationKind())) return llvm::PointerUnion(); - if (SpecializedPartialSpecialization *PartialSpec = - SpecializedTemplate.dyn_cast()) - return PartialSpec->PartialSpecialization; - - return SpecializedTemplate.get(); + return getSpecializedTemplateOrPartial(); } /// \brief Retrieve the variable template or variable template partial @@ -2610,8 +2600,8 @@ public: ArrayRef TemplateArgs, ASTContext &Context) { ID.AddInteger(TemplateArgs.size()); - for (unsigned Arg = 0; Arg != TemplateArgs.size(); ++Arg) - TemplateArgs[Arg].Profile(ID, Context); + for (const TemplateArgument &TemplateArg : TemplateArgs) + TemplateArg.Profile(ID, Context); } static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -2647,7 +2637,7 @@ class VarTemplatePartialSpecializationDecl ASTContext &Context, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, TemplateParameterList *Params, VarTemplateDecl *SpecializedTemplate, QualType T, TypeSourceInfo *TInfo, - StorageClass S, const TemplateArgument *Args, unsigned NumArgs, + StorageClass S, ArrayRef Args, const ASTTemplateArgumentListInfo *ArgInfos); VarTemplatePartialSpecializationDecl(ASTContext &Context) @@ -2660,8 +2650,8 @@ public: 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); + TypeSourceInfo *TInfo, StorageClass S, ArrayRef Args, + const TemplateArgumentListInfo &ArgInfos); static VarTemplatePartialSpecializationDecl *CreateDeserialized(ASTContext &C, unsigned ID); @@ -2808,7 +2798,7 @@ public: /// \brief Get the underlying variable declarations of the template. VarDecl *getTemplatedDecl() const { - return static_cast(TemplatedDecl); + return static_cast(TemplatedDecl.getPointer()); } /// \brief Returns whether this template declaration defines the primary diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 9482e83e81dc3..2d3cfe27a1659 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -30,6 +30,7 @@ namespace clang { class IdentifierInfo; class MultiKeywordSelector; enum OverloadedOperatorKind : int; + struct PrintingPolicy; class QualType; class Type; class TypeSourceInfo; @@ -302,7 +303,9 @@ public: } static int compare(DeclarationName LHS, DeclarationName RHS); - + + void print(raw_ostream &OS, const PrintingPolicy &Policy); + void dump() const; }; diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index 38733eee82c36..9179c7736a9a4 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -29,6 +29,7 @@ #include "llvm/ADT/APSInt.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/AtomicOrdering.h" #include "llvm/Support/Compiler.h" namespace clang { @@ -593,6 +594,13 @@ public: bool EvaluateAsInt(llvm::APSInt &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; + /// EvaluateAsFloat - Return true if this is a constant which we can fold and + /// convert to a floating point value, using any crazy technique that we + /// want to. + bool + EvaluateAsFloat(llvm::APFloat &Result, const ASTContext &Ctx, + SideEffectsKind AllowSideEffects = SE_NoSideEffects) const; + /// isEvaluatable - Call EvaluateAsRValue to see if this expression can be /// constant folded without side-effects, but discard the result. bool isEvaluatable(const ASTContext &Ctx, @@ -847,10 +855,12 @@ public: ExprObjectKind OK = OK_Ordinary, Expr *SourceExpr = nullptr) : Expr(OpaqueValueExprClass, T, VK, OK, - T->isDependentType(), + T->isDependentType() || + (SourceExpr && SourceExpr->isTypeDependent()), T->isDependentType() || (SourceExpr && SourceExpr->isValueDependent()), - T->isInstantiationDependentType(), + T->isInstantiationDependentType() || + (SourceExpr && SourceExpr->isInstantiationDependent()), false), SourceExpr(SourceExpr), Loc(Loc) { } @@ -1110,6 +1120,10 @@ public: return getTrailingObjects()->NumTemplateArgs; } + ArrayRef template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + /// \brief Returns true if this expression refers to a function that /// was resolved from an overloaded set having size greater than 1. bool hadMultipleCandidates() const { @@ -2137,11 +2151,15 @@ class CallExpr : public Expr { unsigned NumArgs; SourceLocation RParenLoc; + void updateDependenciesFromArg(Expr *Arg); + protected: // These versions of the constructor are for derived classes. - CallExpr(const ASTContext& C, StmtClass SC, Expr *fn, unsigned NumPreArgs, - ArrayRef args, QualType t, ExprValueKind VK, - SourceLocation rparenloc); + CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, + ArrayRef preargs, ArrayRef args, QualType t, + ExprValueKind VK, SourceLocation rparenloc); + CallExpr(const ASTContext &C, StmtClass SC, Expr *fn, ArrayRef args, + QualType t, ExprValueKind VK, SourceLocation rparenloc); CallExpr(const ASTContext &C, StmtClass SC, unsigned NumPreArgs, EmptyShell Empty); @@ -2477,6 +2495,10 @@ public: return getTrailingObjects()->NumTemplateArgs; } + ArrayRef template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + /// \brief Retrieve the member declaration name info. DeclarationNameInfo getMemberNameInfo() const { return DeclarationNameInfo(MemberDecl->getDeclName(), @@ -3942,7 +3964,7 @@ private: /// Whether this designated initializer used the GNU deprecated /// syntax rather than the C99 '=' syntax. - bool GNUSyntax : 1; + unsigned GNUSyntax : 1; /// The number of designators in this initializer expression. unsigned NumDesignators : 15; @@ -3956,11 +3978,10 @@ private: /// expression. Designator *Designators; - - DesignatedInitExpr(const ASTContext &C, QualType Ty, unsigned NumDesignators, - const Designator *Designators, + DesignatedInitExpr(const ASTContext &C, QualType Ty, + llvm::ArrayRef Designators, SourceLocation EqualOrColonLoc, bool GNUSyntax, - ArrayRef IndexExprs, Expr *Init); + ArrayRef IndexExprs, Expr *Init); explicit DesignatedInitExpr(unsigned NumSubExprs) : Expr(DesignatedInitExprClass, EmptyShell()), @@ -4120,8 +4141,7 @@ public: }; static DesignatedInitExpr *Create(const ASTContext &C, - Designator *Designators, - unsigned NumDesignators, + llvm::ArrayRef Designators, ArrayRef IndexExprs, SourceLocation EqualOrColonLoc, bool GNUSyntax, Expr *Init); @@ -4133,48 +4153,15 @@ public: unsigned size() const { return NumDesignators; } // Iterator access to the designators. - typedef Designator *designators_iterator; - designators_iterator designators_begin() { return Designators; } - designators_iterator designators_end() { - return Designators + NumDesignators; - } - - typedef const Designator *const_designators_iterator; - const_designators_iterator designators_begin() const { return Designators; } - const_designators_iterator designators_end() const { - return Designators + NumDesignators; - } - - typedef llvm::iterator_range designators_range; - designators_range designators() { - return designators_range(designators_begin(), designators_end()); - } - - typedef llvm::iterator_range - designators_const_range; - designators_const_range designators() const { - return designators_const_range(designators_begin(), designators_end()); + llvm::MutableArrayRef designators() { + return {Designators, NumDesignators}; } - typedef std::reverse_iterator - reverse_designators_iterator; - reverse_designators_iterator designators_rbegin() { - return reverse_designators_iterator(designators_end()); - } - reverse_designators_iterator designators_rend() { - return reverse_designators_iterator(designators_begin()); + llvm::ArrayRef designators() const { + return {Designators, NumDesignators}; } - typedef std::reverse_iterator - const_reverse_designators_iterator; - const_reverse_designators_iterator designators_rbegin() const { - return const_reverse_designators_iterator(designators_end()); - } - const_reverse_designators_iterator designators_rend() const { - return const_reverse_designators_iterator(designators_begin()); - } - - Designator *getDesignator(unsigned Idx) { return &designators_begin()[Idx]; } + Designator *getDesignator(unsigned Idx) { return &designators()[Idx]; } void setDesignators(const ASTContext &C, const Designator *Desigs, unsigned NumDesigs); @@ -4824,16 +4811,6 @@ public: BI_First = 0 }; - // The ABI values for various atomic memory orderings. - enum AtomicOrderingKind { - AO_ABI_memory_order_relaxed = 0, - AO_ABI_memory_order_consume = 1, - AO_ABI_memory_order_acquire = 2, - AO_ABI_memory_order_release = 3, - AO_ABI_memory_order_acq_rel = 4, - AO_ABI_memory_order_seq_cst = 5 - }; - private: enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; Stmt* SubExprs[END_EXPR]; @@ -4882,9 +4859,12 @@ public: } AtomicOp getOp() const { return Op; } - unsigned getNumSubExprs() { return NumSubExprs; } + unsigned getNumSubExprs() const { return NumSubExprs; } Expr **getSubExprs() { return reinterpret_cast(SubExprs); } + const Expr * const *getSubExprs() const { + return reinterpret_cast(SubExprs); + } bool isVolatile() const { return getPtr()->getType()->getPointeeType().isVolatileQualified(); diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 6821274986479..86cbfb2cd0b4c 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_AST_EXPRCXX_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/Expr.h" #include "clang/AST/LambdaCapture.h" #include "clang/AST/TemplateBase.h" @@ -26,9 +27,6 @@ namespace clang { -class CXXConstructorDecl; -class CXXDestructorDecl; -class CXXMethodDecl; class CXXTemporary; class MSPropertyDecl; class TemplateArgumentListInfo; @@ -66,8 +64,7 @@ public: CXXOperatorCallExpr(ASTContext& C, OverloadedOperatorKind Op, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation operatorloc, bool fpContractable) - : CallExpr(C, CXXOperatorCallExprClass, fn, 0, args, t, VK, - operatorloc), + : CallExpr(C, CXXOperatorCallExprClass, fn, args, t, VK, operatorloc), Operator(Op), FPContractable(fpContractable) { Range = getSourceRangeImpl(); } @@ -125,7 +122,7 @@ class CXXMemberCallExpr : public CallExpr { public: CXXMemberCallExpr(ASTContext &C, Expr *fn, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CXXMemberCallExprClass, fn, 0, args, t, VK, RP) {} + : CallExpr(C, CXXMemberCallExprClass, fn, args, t, VK, RP) {} CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) : CallExpr(C, CXXMemberCallExprClass, Empty) { } @@ -146,6 +143,14 @@ public: /// FIXME: Returns 0 for member pointer call exprs. CXXRecordDecl *getRecordDecl() const; + SourceLocation getExprLoc() const LLVM_READONLY { + SourceLocation CLoc = getCallee()->getExprLoc(); + if (CLoc.isValid()) + return CLoc; + + return getLocStart(); + } + static bool classof(const Stmt *T) { return T->getStmtClass() == CXXMemberCallExprClass; } @@ -160,9 +165,7 @@ public: CUDAKernelCallExpr(ASTContext &C, Expr *fn, CallExpr *Config, ArrayRef args, QualType t, ExprValueKind VK, SourceLocation RP) - : CallExpr(C, CUDAKernelCallExprClass, fn, END_PREARG, args, t, VK, RP) { - setConfig(Config); - } + : CallExpr(C, CUDAKernelCallExprClass, fn, Config, args, t, VK, RP) {} CUDAKernelCallExpr(ASTContext &C, EmptyShell Empty) : CallExpr(C, CUDAKernelCallExprClass, END_PREARG, Empty) { } @@ -171,7 +174,20 @@ public: return cast_or_null(getPreArg(CONFIG)); } CallExpr *getConfig() { return cast_or_null(getPreArg(CONFIG)); } - void setConfig(CallExpr *E) { setPreArg(CONFIG, E); } + + /// \brief Sets the kernel configuration expression. + /// + /// Note that this method cannot be called if config has already been set to a + /// non-null value. + void setConfig(CallExpr *E) { + assert(!getConfig() && + "Cannot call setConfig if config is not null"); + setPreArg(CONFIG, E); + setInstantiationDependent(isInstantiationDependent() || + E->isInstantiationDependent()); + setContainsUnexpandedParameterPack(containsUnexpandedParameterPack() || + E->containsUnexpandedParameterPack()); + } static bool classof(const Stmt *T) { return T->getStmtClass() == CUDAKernelCallExprClass; @@ -398,7 +414,7 @@ public: 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), + : CallExpr(C, UserDefinedLiteralClass, Fn, Args, T, VK, LitEndLoc), UDSuffixLoc(SuffixLoc) {} explicit UserDefinedLiteral(const ASTContext &C, EmptyShell Empty) : CallExpr(C, UserDefinedLiteralClass, Empty) {} @@ -768,22 +784,23 @@ public: class CXXUuidofExpr : public Expr { private: llvm::PointerUnion Operand; + StringRef UuidStr; SourceRange Range; public: - CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, SourceRange R) - : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, - false, Operand->getType()->isDependentType(), - Operand->getType()->isInstantiationDependentType(), - Operand->getType()->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } - - CXXUuidofExpr(QualType Ty, Expr *Operand, SourceRange R) - : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, - false, Operand->isTypeDependent(), - Operand->isInstantiationDependent(), - Operand->containsUnexpandedParameterPack()), - Operand(Operand), Range(R) { } + CXXUuidofExpr(QualType Ty, TypeSourceInfo *Operand, StringRef UuidStr, + SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, + Operand->getType()->isDependentType(), + Operand->getType()->isInstantiationDependentType(), + Operand->getType()->containsUnexpandedParameterPack()), + Operand(Operand), UuidStr(UuidStr), Range(R) {} + + CXXUuidofExpr(QualType Ty, Expr *Operand, StringRef UuidStr, SourceRange R) + : Expr(CXXUuidofExprClass, Ty, VK_LValue, OK_Ordinary, false, + Operand->isTypeDependent(), Operand->isInstantiationDependent(), + Operand->containsUnexpandedParameterPack()), + Operand(Operand), UuidStr(UuidStr), Range(R) {} CXXUuidofExpr(EmptyShell Empty, bool isExpr) : Expr(CXXUuidofExprClass, Empty) { @@ -820,7 +837,8 @@ public: Operand = E; } - StringRef getUuidAsStringRef(ASTContext &Context) const; + void setUuidStr(StringRef US) { UuidStr = US; } + StringRef getUuidStr() const { return UuidStr; } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } @@ -831,11 +849,6 @@ public: return T->getStmtClass() == CXXUuidofExprClass; } - /// Grabs __declspec(uuid()) off a type, or returns 0 if we cannot resolve to - /// a single GUID. - static const UuidAttr *GetUuidAttrOfType(QualType QT, - bool *HasMultipleGUIDsPtr = nullptr); - // Iterators child_range children() { if (isTypeOperand()) @@ -1161,18 +1174,21 @@ private: SourceLocation Loc; SourceRange ParenOrBraceRange; unsigned NumArgs : 16; - bool Elidable : 1; - bool HadMultipleCandidates : 1; - bool ListInitialization : 1; - bool StdInitListInitialization : 1; - bool ZeroInitialization : 1; + unsigned Elidable : 1; + unsigned HadMultipleCandidates : 1; + unsigned ListInitialization : 1; + unsigned StdInitListInitialization : 1; + unsigned ZeroInitialization : 1; unsigned ConstructKind : 2; Stmt **Args; + void setConstructor(CXXConstructorDecl *C) { Constructor = C; } + protected: CXXConstructExpr(const ASTContext &C, StmtClass SC, QualType T, SourceLocation Loc, - CXXConstructorDecl *d, bool elidable, + CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, @@ -1191,15 +1207,12 @@ protected: public: /// \brief Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) - : Expr(CXXConstructExprClass, Empty), Constructor(nullptr), - NumArgs(0), Elidable(false), HadMultipleCandidates(false), - ListInitialization(false), ZeroInitialization(false), - ConstructKind(0), Args(nullptr) - { } + : CXXConstructExpr(CXXConstructExprClass, Empty) {} static CXXConstructExpr *Create(const ASTContext &C, QualType T, SourceLocation Loc, - CXXConstructorDecl *D, bool Elidable, + CXXConstructorDecl *Ctor, + bool Elidable, ArrayRef Args, bool HadMultipleCandidates, bool ListInitialization, @@ -1208,8 +1221,8 @@ public: ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); + /// \brief Get the constructor that this expression will (ultimately) call. CXXConstructorDecl *getConstructor() const { return Constructor; } - void setConstructor(CXXConstructorDecl *C) { Constructor = C; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation Loc) { this->Loc = Loc; } @@ -1305,6 +1318,73 @@ public: friend class ASTStmtReader; }; +/// \brief Represents a call to an inherited base class constructor from an +/// inheriting constructor. This call implicitly forwards the arguments from +/// the enclosing context (an inheriting constructor) to the specified inherited +/// base class constructor. +class CXXInheritedCtorInitExpr : public Expr { +private: + CXXConstructorDecl *Constructor; + + /// The location of the using declaration. + SourceLocation Loc; + + /// Whether this is the construction of a virtual base. + unsigned ConstructsVirtualBase : 1; + + /// Whether the constructor is inherited from a virtual base class of the + /// class that we construct. + unsigned InheritedFromVirtualBase : 1; + +public: + /// \brief Construct a C++ inheriting construction expression. + CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, + CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, + bool InheritedFromVirtualBase) + : Expr(CXXInheritedCtorInitExprClass, T, VK_RValue, OK_Ordinary, false, + false, false, false), + Constructor(Ctor), Loc(Loc), + ConstructsVirtualBase(ConstructsVirtualBase), + InheritedFromVirtualBase(InheritedFromVirtualBase) { + assert(!T->isDependentType()); + } + + /// \brief Construct an empty C++ inheriting construction expression. + explicit CXXInheritedCtorInitExpr(EmptyShell Empty) + : Expr(CXXInheritedCtorInitExprClass, Empty), Constructor(nullptr), + ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {} + + /// \brief Get the constructor that this expression will call. + CXXConstructorDecl *getConstructor() const { return Constructor; } + + /// \brief Determine whether this constructor is actually constructing + /// a base class (rather than a complete object). + bool constructsVBase() const { return ConstructsVirtualBase; } + CXXConstructExpr::ConstructionKind getConstructionKind() const { + return ConstructsVirtualBase ? CXXConstructExpr::CK_VirtualBase + : CXXConstructExpr::CK_NonVirtualBase; + } + + /// \brief Determine whether the inherited constructor is inherited from a + /// virtual base of the object we construct. If so, we are not responsible + /// for calling the inherited constructor (the complete object constructor + /// does that), and so we don't need to pass any arguments. + bool inheritedFromVBase() const { return InheritedFromVirtualBase; } + + SourceLocation getLocation() const LLVM_READONLY { return Loc; } + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXInheritedCtorInitExprClass; + } + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + friend class ASTStmtReader; +}; + /// \brief Represents an explicit C++ type conversion that uses "functional" /// notation (C++ [expr.type.conv]). /// @@ -1375,7 +1455,8 @@ class CXXTemporaryObjectExpr : public CXXConstructExpr { TypeSourceInfo *Type; public: - CXXTemporaryObjectExpr(const ASTContext &C, CXXConstructorDecl *Cons, + CXXTemporaryObjectExpr(const ASTContext &C, + CXXConstructorDecl *Cons, TypeSourceInfo *Type, ArrayRef Args, SourceRange ParenOrBraceRange, @@ -1744,12 +1825,12 @@ class CXXNewExpr : public Expr { SourceRange DirectInitRange; /// Was the usage ::new, i.e. is the global new to be used? - bool GlobalNew : 1; + unsigned GlobalNew : 1; /// Do we allocate an array? If so, the first SubExpr is the size expression. - bool Array : 1; + unsigned Array : 1; /// If this is an array allocation, does the usual deallocation /// function for the allocated type want to know the allocated size? - bool UsualArrayDeleteWantsSize : 1; + unsigned UsualArrayDeleteWantsSize : 1; /// The number of placement new arguments. unsigned NumPlacementArgs : 13; /// What kind of initializer do we have? Could be none, parens, or braces. @@ -2348,7 +2429,7 @@ class ExpressionTraitExpr : public Expr { /// \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; + unsigned Value : 1; /// \brief The location of the type trait keyword. SourceLocation Loc; @@ -2557,6 +2638,10 @@ public: return getTrailingASTTemplateKWAndArgsInfo()->NumTemplateArgs; } + ArrayRef template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + /// \brief Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) @@ -2810,6 +2895,10 @@ public: return getTrailingObjects()->NumTemplateArgs; } + ArrayRef template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + /// Note: getLocStart() is the start of the whole DependentScopeDeclRefExpr, /// and differs from getLocation().getStart(). SourceLocation getLocStart() const LLVM_READONLY { @@ -2858,7 +2947,8 @@ private: Stmt *SubExpr; ExprWithCleanups(EmptyShell, unsigned NumObjects); - ExprWithCleanups(Expr *SubExpr, ArrayRef Objects); + ExprWithCleanups(Expr *SubExpr, bool CleanupsHaveSideEffects, + ArrayRef Objects); friend TrailingObjects; friend class ASTStmtReader; @@ -2868,6 +2958,7 @@ public: unsigned numObjects); static ExprWithCleanups *Create(const ASTContext &C, Expr *subexpr, + bool CleanupsHaveSideEffects, ArrayRef objects); ArrayRef getObjects() const { @@ -2884,6 +2975,9 @@ public: Expr *getSubExpr() { return cast(SubExpr); } const Expr *getSubExpr() const { return cast(SubExpr); } + bool cleanupsHaveSideEffects() const { + return ExprWithCleanupsBits.CleanupsHaveSideEffects; + } /// As with any mutator of the AST, be very careful /// when modifying an existing AST to preserve its invariants. @@ -3220,6 +3314,10 @@ public: return getTrailingObjects()->NumTemplateArgs; } + ArrayRef template_arguments() const { + return {getTemplateArgs(), getNumTemplateArgs()}; + } + SourceLocation getLocStart() const LLVM_READONLY { if (!isImplicitAccess()) return Base->getLocStart(); diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 61e6383bffedd..5f9623db24163 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -1562,7 +1562,52 @@ public: return T->getStmtClass() == ObjCBridgedCastExprClass; } }; - + +/// \brief A runtime availability query. +/// +/// There are 2 ways to spell this node: +/// \code +/// @available(macos 10.10, ios 8, *); // Objective-C +/// __builtin_available(macos 10.10, ios 8, *); // C, C++, and Objective-C +/// \endcode +/// +/// Note that we only need to keep track of one \c VersionTuple here, which is +/// the one that corresponds to the current deployment target. This is meant to +/// be used in the condition of an \c if, but it is also usable as top level +/// expressions. +/// +class ObjCAvailabilityCheckExpr : public Expr { + VersionTuple VersionToCheck; + SourceLocation AtLoc, RParen; + + friend class ASTStmtReader; +public: + ObjCAvailabilityCheckExpr(VersionTuple VersionToCheck, SourceLocation AtLoc, + SourceLocation RParen, QualType Ty) + : Expr(ObjCAvailabilityCheckExprClass, Ty, VK_RValue, OK_Ordinary, false, + false, false, false), + VersionToCheck(VersionToCheck), AtLoc(AtLoc), RParen(RParen) {} + + explicit ObjCAvailabilityCheckExpr(EmptyShell Shell) + : Expr(ObjCAvailabilityCheckExprClass, Shell) {} + + SourceLocation getLocStart() const { return AtLoc; } + SourceLocation getLocEnd() const { return RParen; } + SourceRange getSourceRange() const { return {AtLoc, RParen}; } + + /// \brief This may be '*', in which case this should fold to true. + bool hasVersion() const { return !VersionToCheck.empty(); } + VersionTuple getVersion() { return VersionToCheck; } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == ObjCAvailabilityCheckExprClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h index 2d71a3ad47c77..a4ef93ba8b14a 100644 --- a/include/clang/AST/ExprOpenMP.h +++ b/include/clang/AST/ExprOpenMP.h @@ -85,7 +85,7 @@ public: void setBase(Expr *E) { SubExprs[BASE] = E; } /// \brief Return original type of the base expression for array section. - static QualType getBaseOriginalType(Expr *Base); + static QualType getBaseOriginalType(const Expr *Base); /// \brief Get lower bound of array section. Expr *getLowerBound() { return cast_or_null(SubExprs[LOWER_BOUND]); } diff --git a/include/clang/AST/GlobalDecl.h b/include/clang/AST/GlobalDecl.h index 54c9d88c9b2ee..adf63a3aea69c 100644 --- a/include/clang/AST/GlobalDecl.h +++ b/include/clang/AST/GlobalDecl.h @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclOpenMP.h" #include "clang/Basic/ABI.h" namespace clang { @@ -43,6 +44,7 @@ public: GlobalDecl(const BlockDecl *D) { Init(D); } GlobalDecl(const CapturedDecl *D) { Init(D); } GlobalDecl(const ObjCMethodDecl *D) { Init(D); } + GlobalDecl(const OMPDeclareReductionDecl *D) { Init(D); } GlobalDecl(const CXXConstructorDecl *D, CXXCtorType Type) : Value(D, Type) {} diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h index ddefa88a6b697..6517d656878ee 100644 --- a/include/clang/AST/LambdaCapture.h +++ b/include/clang/AST/LambdaCapture.h @@ -33,10 +33,22 @@ class LambdaCapture { /// given capture was by-copy. /// /// This includes the case of a non-reference init-capture. - Capture_ByCopy = 0x02 + Capture_ByCopy = 0x02, + + /// \brief Flag used by the Capture class to distinguish between a capture + /// of '*this' and a capture of a VLA type. + Capture_This = 0x04 }; - llvm::PointerIntPair DeclAndBits; + // Decl could represent: + // - a VarDecl* that represents the variable that was captured or the + // init-capture. + // - or, is a nullptr and Capture_This is set in Bits if this represents a + // capture of '*this' by value or reference. + // - or, is a nullptr and Capture_This is not set in Bits if this represents + // a capture of a VLA type. + llvm::PointerIntPair DeclAndBits; + SourceLocation Loc; SourceLocation EllipsisLoc; @@ -69,8 +81,8 @@ public: /// \brief Determine whether this capture handles the C++ \c this /// pointer. bool capturesThis() const { - return (DeclAndBits.getPointer() == nullptr) && - !(DeclAndBits.getInt() & Capture_ByCopy); + return DeclAndBits.getPointer() == nullptr && + (DeclAndBits.getInt() & Capture_This); } /// \brief Determine whether this capture handles a variable. @@ -81,8 +93,8 @@ public: /// \brief Determine whether this captures a variable length array bound /// expression. bool capturesVLAType() const { - return (DeclAndBits.getPointer() == nullptr) && - (DeclAndBits.getInt() & Capture_ByCopy); + return DeclAndBits.getPointer() == nullptr && + !(DeclAndBits.getInt() & Capture_This); } /// \brief Retrieve the declaration of the local variable being @@ -91,13 +103,15 @@ public: /// 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()); + assert(capturesVariable() && "No variable available for capture"); + return static_cast(DeclAndBits.getPointer()); } /// \brief Determine whether this was an implicit capture (not /// written between the square brackets introducing the lambda). - bool isImplicit() const { return DeclAndBits.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). diff --git a/include/clang/AST/LocInfoType.h b/include/clang/AST/LocInfoType.h new file mode 100644 index 0000000000000..7e573bd7bac44 --- /dev/null +++ b/include/clang/AST/LocInfoType.h @@ -0,0 +1,61 @@ +//===--- LocInfoType.h - Parsed Type with Location Information---*- 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 LocInfoType class, which holds a type and its +// source-location information. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_SEMA_LOCINFOTYPE_H +#define LLVM_CLANG_SEMA_LOCINFOTYPE_H + +#include "clang/AST/Type.h" + +namespace clang { + +class TypeSourceInfo; + +/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator +/// parsing. +/// +/// LocInfoType is a "transient" type, only needed for passing to/from Parser +/// and Sema, when we want to preserve type source info for a parsed type. +/// It will not participate in the type system semantics in any way. +class LocInfoType : public Type { + enum { + // The last number that can fit in Type's TC. + // Avoids conflict with an existing Type class. + LocInfo = Type::TypeLast + 1 + }; + + TypeSourceInfo *DeclInfo; + + LocInfoType(QualType ty, TypeSourceInfo *TInfo) + : Type((TypeClass)LocInfo, ty, ty->isDependentType(), + ty->isInstantiationDependentType(), ty->isVariablyModifiedType(), + ty->containsUnexpandedParameterPack()), + DeclInfo(TInfo) { + assert(getTypeClass() == (TypeClass)LocInfo && "LocInfo didn't fit in TC?"); + } + friend class Sema; + +public: + QualType getType() const { return getCanonicalTypeInternal(); } + TypeSourceInfo *getTypeSourceInfo() const { return DeclInfo; } + + void getAsStringInternal(std::string &Str, + const PrintingPolicy &Policy) const; + + static bool classof(const Type *T) { + return T->getTypeClass() == (TypeClass)LocInfo; + } +}; + +} // end namespace clang + +#endif // LLVM_CLANG_SEMA_LOCINFOTYPE_H diff --git a/include/clang/AST/Makefile b/include/clang/AST/Makefile deleted file mode 100644 index 85e6449c509a2..0000000000000 --- a/include/clang/AST/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -CLANG_LEVEL := ../../.. -TD_SRC_DIR = $(PROJ_SRC_DIR)/../Basic -BUILT_SOURCES = Attrs.inc AttrImpl.inc AttrDump.inc AttrVisitor.inc \ - StmtNodes.inc DeclNodes.inc \ - CommentNodes.inc CommentHTMLTags.inc \ - CommentHTMLTagsProperties.inc \ - CommentHTMLNamedCharacterReferences.inc \ - CommentCommandInfo.inc \ - CommentCommandList.inc - -TABLEGEN_INC_FILES_COMMON = 1 - -include $(CLANG_LEVEL)/Makefile - -$(ObjDir)/Attrs.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute classes with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-classes -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/AttrImpl.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute implementations with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-impl -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/AttrDump.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute dumper with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-dump -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/AttrVisitor.inc.tmp : $(TD_SRC_DIR)/Attr.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang attribute AST visitor with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-attr-ast-visitor -o $(call SYSPATH, $@) \ - -I $(PROJ_SRC_DIR)/../../ $< - -$(ObjDir)/StmtNodes.inc.tmp : $(TD_SRC_DIR)/StmtNodes.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang statement node tables with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-stmt-nodes -o $(call SYSPATH, $@) $< - -$(ObjDir)/DeclNodes.inc.tmp : $(TD_SRC_DIR)/DeclNodes.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang declaration node tables with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-decl-nodes -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentNodes.inc.tmp : $(TD_SRC_DIR)/CommentNodes.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang comment node tables with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-nodes -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentHTMLTags.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td $(CLANG_TBLGEN) \ - $(ObjDir)/.dir - $(Echo) "Building Clang comment HTML tag matchers with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentHTMLTagsProperties.inc.tmp : $(PROJ_SRC_DIR)/CommentHTMLTags.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang comment HTML tag properties with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-html-tags-properties -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentHTMLNamedCharacterReferences.inc.tmp : \ - $(PROJ_SRC_DIR)/CommentHTMLNamedCharacterReferences.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang named character reference translation function with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-html-named-character-references -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentCommandInfo.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang comment command info with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-command-info -o $(call SYSPATH, $@) $< - -$(ObjDir)/CommentCommandList.inc.tmp : $(PROJ_SRC_DIR)/CommentCommands.td \ - $(CLANG_TBLGEN) $(ObjDir)/.dir - $(Echo) "Building Clang list of comment commands with tblgen" - $(Verb) $(ClangTableGen) -gen-clang-comment-command-list -o $(call SYSPATH, $@) $< - diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index 4872738e7a1ea..6e3ef9da0c3d4 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_MANGLE_H #define LLVM_CLANG_AST_MANGLE_H +#include "clang/AST/Decl.h" #include "clang/AST/Type.h" #include "clang/Basic/ABI.h" #include "llvm/ADT/DenseMap.h" @@ -123,6 +124,7 @@ public: void mangleBlock(const DeclContext *DC, const BlockDecl *BD, raw_ostream &Out); + void mangleObjCMethodNameWithoutSize(const ObjCMethodDecl *MD, raw_ostream &); void mangleObjCMethodName(const ObjCMethodDecl *MD, raw_ostream &); virtual void mangleStaticGuardVariable(const VarDecl *D, raw_ostream &) = 0; @@ -206,7 +208,8 @@ public: raw_ostream &Out) = 0; virtual void mangleCXXThrowInfo(QualType T, bool IsConst, bool IsVolatile, - uint32_t NumEntries, raw_ostream &Out) = 0; + bool IsUnaligned, uint32_t NumEntries, + raw_ostream &Out) = 0; virtual void mangleCXXCatchableTypeArray(QualType T, uint32_t NumEntries, raw_ostream &Out) = 0; diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 7632a4b3560a8..43988cd864bb0 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -70,6 +70,51 @@ public: static bool classof(const OMPClause *) { return true; } }; +/// Class that handles pre-initialization statement for some clauses, like +/// 'shedule', 'firstprivate' etc. +class OMPClauseWithPreInit { + friend class OMPClauseReader; + /// Pre-initialization statement for the clause. + Stmt *PreInit; +protected: + /// Set pre-initialization statement for the clause. + void setPreInitStmt(Stmt *S) { PreInit = S; } + OMPClauseWithPreInit(const OMPClause *This) : PreInit(nullptr) { + assert(get(This) && "get is not tuned for pre-init."); + } + +public: + /// Get pre-initialization statement for the clause. + const Stmt *getPreInitStmt() const { return PreInit; } + /// Get pre-initialization statement for the clause. + Stmt *getPreInitStmt() { return PreInit; } + static OMPClauseWithPreInit *get(OMPClause *C); + static const OMPClauseWithPreInit *get(const OMPClause *C); +}; + +/// Class that handles post-update expression for some clauses, like +/// 'lastprivate', 'reduction' etc. +class OMPClauseWithPostUpdate : public OMPClauseWithPreInit { + friend class OMPClauseReader; + /// Post-update expression for the clause. + Expr *PostUpdate; +protected: + /// Set pre-initialization statement for the clause. + void setPostUpdateExpr(Expr *S) { PostUpdate = S; } + OMPClauseWithPostUpdate(const OMPClause *This) + : OMPClauseWithPreInit(This), PostUpdate(nullptr) { + assert(get(This) && "get is not tuned for post-update."); + } + +public: + /// Get post-update expression for the clause. + const Expr *getPostUpdateExpr() const { return PostUpdate; } + /// Get post-update expression for the clause. + Expr *getPostUpdateExpr() { return PostUpdate; } + static OMPClauseWithPostUpdate *get(OMPClause *C); + static const OMPClauseWithPostUpdate *get(const OMPClause *C); +}; + /// \brief This represents clauses with the list of variables like 'private', /// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the /// '#pragma omp ...' directives. @@ -650,7 +695,7 @@ public: /// In this example directive '#pragma omp for' has 'schedule' clause with /// arguments 'static' and '3'. /// -class OMPScheduleClause : public OMPClause { +class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; /// \brief Location of '('. SourceLocation LParenLoc; @@ -665,10 +710,8 @@ class OMPScheduleClause : public OMPClause { SourceLocation KindLoc; /// \brief Location of ',' (if any). SourceLocation CommaLoc; - /// \brief Chunk size and a reference to pseudo variable for combined - /// directives. - enum { CHUNK_SIZE, HELPER_CHUNK_SIZE, NUM_EXPRS }; - Stmt *ChunkSizes[NUM_EXPRS]; + /// \brief Chunk size. + Expr *ChunkSize; /// \brief Set schedule kind. /// @@ -730,12 +773,7 @@ class OMPScheduleClause : public OMPClause { /// /// \param E Chunk size. /// - void setChunkSize(Expr *E) { ChunkSizes[CHUNK_SIZE] = E; } - /// \brief Set helper chunk size. - /// - /// \param E Helper chunk size. - /// - void setHelperChunkSize(Expr *E) { ChunkSizes[HELPER_CHUNK_SIZE] = E; } + void setChunkSize(Expr *E) { ChunkSize = E; } public: /// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size @@ -757,13 +795,13 @@ public: OMPScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KLoc, SourceLocation CommaLoc, SourceLocation EndLoc, OpenMPScheduleClauseKind Kind, - Expr *ChunkSize, Expr *HelperChunkSize, + Expr *ChunkSize, Stmt *HelperChunkSize, OpenMPScheduleClauseModifier M1, SourceLocation M1Loc, OpenMPScheduleClauseModifier M2, SourceLocation M2Loc) - : OMPClause(OMPC_schedule, StartLoc, EndLoc), LParenLoc(LParenLoc), - Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc) { - ChunkSizes[CHUNK_SIZE] = ChunkSize; - ChunkSizes[HELPER_CHUNK_SIZE] = HelperChunkSize; + : OMPClause(OMPC_schedule, StartLoc, EndLoc), OMPClauseWithPreInit(this), + LParenLoc(LParenLoc), Kind(Kind), KindLoc(KLoc), CommaLoc(CommaLoc), + ChunkSize(ChunkSize) { + setPreInitStmt(HelperChunkSize); Modifiers[FIRST] = M1; Modifiers[SECOND] = M2; ModifiersLoc[FIRST] = M1Loc; @@ -774,9 +812,8 @@ public: /// explicit OMPScheduleClause() : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()), - Kind(OMPC_SCHEDULE_unknown) { - ChunkSizes[CHUNK_SIZE] = nullptr; - ChunkSizes[HELPER_CHUNK_SIZE] = nullptr; + OMPClauseWithPreInit(this), Kind(OMPC_SCHEDULE_unknown), + ChunkSize(nullptr) { Modifiers[FIRST] = OMPC_SCHEDULE_MODIFIER_unknown; Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown; } @@ -815,29 +852,18 @@ public: SourceLocation getCommaLoc() { return CommaLoc; } /// \brief Get chunk size. /// - Expr *getChunkSize() { return dyn_cast_or_null(ChunkSizes[CHUNK_SIZE]); } + Expr *getChunkSize() { return ChunkSize; } /// \brief Get chunk size. /// - Expr *getChunkSize() const { - return dyn_cast_or_null(ChunkSizes[CHUNK_SIZE]); - } - /// \brief Get helper chunk size. - /// - Expr *getHelperChunkSize() { - return dyn_cast_or_null(ChunkSizes[HELPER_CHUNK_SIZE]); - } - /// \brief Get helper chunk size. - /// - Expr *getHelperChunkSize() const { - return dyn_cast_or_null(ChunkSizes[HELPER_CHUNK_SIZE]); - } + const Expr *getChunkSize() const { return ChunkSize; } static bool classof(const OMPClause *T) { return T->getClauseKind() == OMPC_schedule; } child_range children() { - return child_range(&ChunkSizes[CHUNK_SIZE], &ChunkSizes[CHUNK_SIZE] + 1); + return child_range(reinterpret_cast(&ChunkSize), + reinterpret_cast(&ChunkSize) + 1); } }; @@ -1250,6 +1276,7 @@ public: /// class OMPFirstprivateClause final : public OMPVarListClause, + public OMPClauseWithPreInit, private llvm::TrailingObjects { friend TrailingObjects; friend OMPVarListClause; @@ -1265,7 +1292,8 @@ class OMPFirstprivateClause final OMPFirstprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause(OMPC_firstprivate, StartLoc, - LParenLoc, EndLoc, N) {} + LParenLoc, EndLoc, N), + OMPClauseWithPreInit(this) {} /// \brief Build an empty clause. /// @@ -1274,7 +1302,8 @@ class OMPFirstprivateClause final explicit OMPFirstprivateClause(unsigned N) : OMPVarListClause( OMPC_firstprivate, SourceLocation(), SourceLocation(), - SourceLocation(), N) {} + SourceLocation(), N), + OMPClauseWithPreInit(this) {} /// \brief Sets the list of references to private copies with initializers for /// new private variables. /// \param VL List of references. @@ -1315,11 +1344,13 @@ public: /// \param InitVL List of references to auto generated variables used for /// initialization of a single array element. Used if firstprivate variable is /// of array type. + /// \param PreInit Statement that must be executed before entering the OpenMP + /// region with this clause. /// static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef PrivateVL, - ArrayRef InitVL); + ArrayRef InitVL, Stmt *PreInit); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -1374,6 +1405,7 @@ public: /// with the variables 'a' and 'b'. class OMPLastprivateClause final : public OMPVarListClause, + public OMPClauseWithPostUpdate, private llvm::TrailingObjects { // There are 4 additional tail-allocated arrays at the end of the class: // 1. Contains list of pseudo variables with the default initialization for @@ -1406,7 +1438,8 @@ class OMPLastprivateClause final OMPLastprivateClause(SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPVarListClause(OMPC_lastprivate, StartLoc, - LParenLoc, EndLoc, N) {} + LParenLoc, EndLoc, N), + OMPClauseWithPostUpdate(this) {} /// \brief Build an empty clause. /// @@ -1415,7 +1448,8 @@ class OMPLastprivateClause final explicit OMPLastprivateClause(unsigned N) : OMPVarListClause( OMPC_lastprivate, SourceLocation(), SourceLocation(), - SourceLocation(), N) {} + SourceLocation(), N), + OMPClauseWithPostUpdate(this) {} /// \brief Get the list of helper expressions for initialization of private /// copies for lastprivate variables. @@ -1488,12 +1522,16 @@ public: /// \endcode /// Required for proper codegen of final assignment performed by the /// lastprivate clause. - /// + /// \param PreInit Statement that must be executed before entering the OpenMP + /// region with this clause. + /// \param PostUpdate Expression that must be executed after exit from the + /// OpenMP region with this clause. /// static OMPLastprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef VL, ArrayRef SrcExprs, - ArrayRef DstExprs, ArrayRef AssignmentOps); + ArrayRef DstExprs, ArrayRef AssignmentOps, + Stmt *PreInit, Expr *PostUpdate); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -1627,6 +1665,7 @@ public: /// class OMPReductionClause final : public OMPVarListClause, + public OMPClauseWithPostUpdate, private llvm::TrailingObjects { friend TrailingObjects; friend OMPVarListClause; @@ -1654,7 +1693,8 @@ class OMPReductionClause final const DeclarationNameInfo &NameInfo) : OMPVarListClause(OMPC_reduction, StartLoc, LParenLoc, EndLoc, N), - ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} + OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc), + QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} /// \brief Build an empty clause. /// @@ -1664,7 +1704,7 @@ class OMPReductionClause final : OMPVarListClause(OMPC_reduction, SourceLocation(), SourceLocation(), SourceLocation(), N), - ColonLoc(), QualifierLoc(), NameInfo() {} + OMPClauseWithPostUpdate(this), ColonLoc(), QualifierLoc(), NameInfo() {} /// \brief Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } @@ -1757,6 +1797,10 @@ public: /// \endcode /// Required for proper codegen of final reduction operation performed by the /// reduction clause. + /// \param PreInit Statement that must be executed before entering the OpenMP + /// region with this clause. + /// \param PostUpdate Expression that must be executed after exit from the + /// OpenMP region with this clause. /// static OMPReductionClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -1764,7 +1808,7 @@ public: NestedNameSpecifierLoc QualifierLoc, const DeclarationNameInfo &NameInfo, ArrayRef Privates, ArrayRef LHSExprs, ArrayRef RHSExprs, - ArrayRef ReductionOps); + ArrayRef ReductionOps, Stmt *PreInit, Expr *PostUpdate); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -1833,6 +1877,7 @@ public: /// class OMPLinearClause final : public OMPVarListClause, + public OMPClauseWithPostUpdate, private llvm::TrailingObjects { friend TrailingObjects; friend OMPVarListClause; @@ -1864,7 +1909,8 @@ class OMPLinearClause final unsigned NumVars) : OMPVarListClause(OMPC_linear, StartLoc, LParenLoc, EndLoc, NumVars), - Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} + OMPClauseWithPostUpdate(this), Modifier(Modifier), + ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} /// \brief Build an empty clause. /// @@ -1874,7 +1920,8 @@ class OMPLinearClause final : OMPVarListClause(OMPC_linear, SourceLocation(), SourceLocation(), SourceLocation(), NumVars), - Modifier(OMPC_LINEAR_val), ModifierLoc(), ColonLoc() {} + OMPClauseWithPostUpdate(this), Modifier(OMPC_LINEAR_val), ModifierLoc(), + ColonLoc() {} /// \brief Gets the list of initial values for linear variables. /// @@ -1943,11 +1990,16 @@ public: /// \param IL List of initial values for the variables. /// \param Step Linear step. /// \param CalcStep Calculation of the linear step. + /// \param PreInit Statement that must be executed before entering the OpenMP + /// region with this clause. + /// \param PostUpdate Expression that must be executed after exit from the + /// OpenMP region with this clause. static OMPLinearClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind Modifier, SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc, ArrayRef VL, - ArrayRef PL, ArrayRef IL, Expr *Step, Expr *CalcStep); + ArrayRef PL, ArrayRef IL, Expr *Step, Expr *CalcStep, + Stmt *PreInit, Expr *PostUpdate); /// \brief Creates an empty clause with the place for \a NumVars variables. /// @@ -2577,7 +2629,6 @@ public: /// \param DepLoc Location of the dependency type. /// \param ColonLoc Colon location. /// \param VL List of references to the variables. - /// static OMPDependClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc, OpenMPDependClauseKind DepKind, @@ -2596,6 +2647,14 @@ public: /// \brief Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } + /// Set the loop counter value for the depend clauses with 'sink|source' kind + /// of dependency. Required for codegen. + void setCounterValue(Expr *V); + /// Get the loop counter value. + Expr *getCounterValue(); + /// Get the loop counter value. + const Expr *getCounterValue() const; + child_range children() { return child_range(reinterpret_cast(varlist_begin()), reinterpret_cast(varlist_end())); @@ -2722,6 +2781,495 @@ public: } }; +/// \brief Struct that defines common infrastructure to handle mappable +/// expressions used in OpenMP clauses. +class OMPClauseMappableExprCommon { +public: + // \brief Class that represents a component of a mappable expression. E.g. + // for an expression S.a, the first component is a declaration reference + // expression associated with 'S' and the second is a member expression + // associated with the field declaration 'a'. If the expression is an array + // subscript it may not have any associated declaration. In that case the + // associated declaration is set to nullptr. + class MappableComponent { + // \brief Expression associated with the component. + Expr *AssociatedExpression = nullptr; + // \brief Declaration associated with the declaration. If the component does + // not have a declaration (e.g. array subscripts or section), this is set to + // nullptr. + ValueDecl *AssociatedDeclaration = nullptr; + + public: + explicit MappableComponent() {} + explicit MappableComponent(Expr *AssociatedExpression, + ValueDecl *AssociatedDeclaration) + : AssociatedExpression(AssociatedExpression), + AssociatedDeclaration( + AssociatedDeclaration + ? cast(AssociatedDeclaration->getCanonicalDecl()) + : nullptr) {} + + Expr *getAssociatedExpression() const { return AssociatedExpression; } + ValueDecl *getAssociatedDeclaration() const { + return AssociatedDeclaration; + } + }; + + // \brief List of components of an expression. This first one is the whole + // expression and the last one is the base expression. + typedef SmallVector MappableExprComponentList; + typedef ArrayRef MappableExprComponentListRef; + + // \brief List of all component lists associated to the same base declaration. + // E.g. if both 'S.a' and 'S.b' are a mappable expressions, each will have + // their component list but the same base declaration 'S'. + typedef SmallVector MappableExprComponentLists; + typedef ArrayRef MappableExprComponentListsRef; + +protected: + // \brief Return the total number of elements in a list of component lists. + static unsigned + getComponentsTotalNumber(MappableExprComponentListsRef ComponentLists); + + // \brief Return the total number of elements in a list of declarations. All + // declarations are expected to be canonical. + static unsigned + getUniqueDeclarationsTotalNumber(ArrayRef Declarations); +}; + +/// \brief This represents clauses with a list of expressions that are mappable. +/// Examples of these clauses are 'map' in +/// '#pragma omp target [enter|exit] [data]...' directives, and 'to' and 'from +/// in '#pragma omp target update...' directives. +template +class OMPMappableExprListClause : public OMPVarListClause, + public OMPClauseMappableExprCommon { + friend class OMPClauseReader; + + /// \brief Number of unique declarations in this clause. + unsigned NumUniqueDeclarations; + + /// \brief Number of component lists in this clause. + unsigned NumComponentLists; + + /// \brief Total number of components in this clause. + unsigned NumComponents; + +protected: + /// \brief Get the unique declarations that are in the trailing objects of the + /// class. + MutableArrayRef getUniqueDeclsRef() { + return MutableArrayRef( + static_cast(this)->template getTrailingObjects(), + NumUniqueDeclarations); + } + + /// \brief Get the unique declarations that are in the trailing objects of the + /// class. + ArrayRef getUniqueDeclsRef() const { + return ArrayRef( + static_cast(this) + ->template getTrailingObjects(), + NumUniqueDeclarations); + } + + /// \brief Set the unique declarations that are in the trailing objects of the + /// class. + void setUniqueDecls(ArrayRef UDs) { + assert(UDs.size() == NumUniqueDeclarations && + "Unexpected amount of unique declarations."); + std::copy(UDs.begin(), UDs.end(), getUniqueDeclsRef().begin()); + } + + /// \brief Get the number of lists per declaration that are in the trailing + /// objects of the class. + MutableArrayRef getDeclNumListsRef() { + return MutableArrayRef( + static_cast(this)->template getTrailingObjects(), + NumUniqueDeclarations); + } + + /// \brief Get the number of lists per declaration that are in the trailing + /// objects of the class. + ArrayRef getDeclNumListsRef() const { + return ArrayRef( + static_cast(this)->template getTrailingObjects(), + NumUniqueDeclarations); + } + + /// \brief Set the number of lists per declaration that are in the trailing + /// objects of the class. + void setDeclNumLists(ArrayRef DNLs) { + assert(DNLs.size() == NumUniqueDeclarations && + "Unexpected amount of list numbers."); + std::copy(DNLs.begin(), DNLs.end(), getDeclNumListsRef().begin()); + } + + /// \brief Get the cumulative component lists sizes that are in the trailing + /// objects of the class. They are appended after the number of lists. + MutableArrayRef getComponentListSizesRef() { + return MutableArrayRef( + static_cast(this)->template getTrailingObjects() + + NumUniqueDeclarations, + NumComponentLists); + } + + /// \brief Get the cumulative component lists sizes that are in the trailing + /// objects of the class. They are appended after the number of lists. + ArrayRef getComponentListSizesRef() const { + return ArrayRef( + static_cast(this)->template getTrailingObjects() + + NumUniqueDeclarations, + NumComponentLists); + } + + /// \brief Set the cumulative component lists sizes that are in the trailing + /// objects of the class. + void setComponentListSizes(ArrayRef CLSs) { + assert(CLSs.size() == NumComponentLists && + "Unexpected amount of component lists."); + std::copy(CLSs.begin(), CLSs.end(), getComponentListSizesRef().begin()); + } + + /// \brief Get the components that are in the trailing objects of the class. + MutableArrayRef getComponentsRef() { + return MutableArrayRef( + static_cast(this) + ->template getTrailingObjects(), + NumComponents); + } + + /// \brief Get the components that are in the trailing objects of the class. + ArrayRef getComponentsRef() const { + return ArrayRef( + static_cast(this) + ->template getTrailingObjects(), + NumComponents); + } + + /// \brief Set the components that are in the trailing objects of the class. + /// This requires the list sizes so that it can also fill the original + /// expressions, which are the first component of each list. + void setComponents(ArrayRef Components, + ArrayRef CLSs) { + assert(Components.size() == NumComponents && + "Unexpected amount of component lists."); + assert(CLSs.size() == NumComponentLists && + "Unexpected amount of list sizes."); + std::copy(Components.begin(), Components.end(), getComponentsRef().begin()); + } + + /// \brief Fill the clause information from the list of declarations and + /// associated component lists. + void setClauseInfo(ArrayRef Declarations, + MappableExprComponentListsRef ComponentLists) { + // Perform some checks to make sure the data sizes are consistent with the + // information available when the clause was created. + assert(getUniqueDeclarationsTotalNumber(Declarations) == + NumUniqueDeclarations && + "Unexpected number of mappable expression info entries!"); + assert(getComponentsTotalNumber(ComponentLists) == NumComponents && + "Unexpected total number of components!"); + assert(Declarations.size() == ComponentLists.size() && + "Declaration and component lists size is not consistent!"); + assert(Declarations.size() == NumComponentLists && + "Unexpected declaration and component lists size!"); + + // Organize the components by declaration and retrieve the original + // expression. Original expressions are always the first component of the + // mappable component list. + llvm::DenseMap> + ComponentListMap; + { + auto CI = ComponentLists.begin(); + for (auto DI = Declarations.begin(), DE = Declarations.end(); DI != DE; + ++DI, ++CI) { + assert(!CI->empty() && "Invalid component list!"); + ComponentListMap[*DI].push_back(*CI); + } + } + + // Iterators of the target storage. + auto UniqueDeclarations = getUniqueDeclsRef(); + auto UDI = UniqueDeclarations.begin(); + + auto DeclNumLists = getDeclNumListsRef(); + auto DNLI = DeclNumLists.begin(); + + auto ComponentListSizes = getComponentListSizesRef(); + auto CLSI = ComponentListSizes.begin(); + + auto Components = getComponentsRef(); + auto CI = Components.begin(); + + // Variable to compute the accumulation of the number of components. + unsigned PrevSize = 0u; + + // Scan all the declarations and associated component lists. + for (auto &M : ComponentListMap) { + // The declaration. + auto *D = M.first; + // The component lists. + auto CL = M.second; + + // Initialize the entry. + *UDI = D; + ++UDI; + + *DNLI = CL.size(); + ++DNLI; + + // Obtain the cumulative sizes and concatenate all the components in the + // reserved storage. + for (auto C : CL) { + // Accumulate with the previous size. + PrevSize += C.size(); + + // Save the size. + *CLSI = PrevSize; + ++CLSI; + + // Append components after the current components iterator. + CI = std::copy(C.begin(), C.end(), CI); + } + } + } + + /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a + /// NumComponentLists total component lists, and \a NumComponents total + /// components. + /// + /// \param K Kind of the clause. + /// \param StartLoc Starting location of the clause (the clause keyword). + /// \param LParenLoc Location of '('. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of expressions listed in the clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause - one + /// list for each expression in the clause. + /// \param NumComponents Total number of expression components in the clause. + /// + OMPMappableExprListClause(OpenMPClauseKind K, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPVarListClause(K, StartLoc, LParenLoc, EndLoc, NumVars), + NumUniqueDeclarations(NumUniqueDeclarations), + NumComponentLists(NumComponentLists), NumComponents(NumComponents) {} + +public: + /// \brief Return the number of unique base declarations in this clause. + unsigned getUniqueDeclarationsNum() const { return NumUniqueDeclarations; } + /// \brief Return the number of lists derived from the clause expressions. + unsigned getTotalComponentListNum() const { return NumComponentLists; } + /// \brief Return the total number of components in all lists derived from the + /// clause. + unsigned getTotalComponentsNum() const { return NumComponents; } + + /// \brief Iterator that browse the components by lists. It also allows + /// browsing components of a single declaration. + class const_component_lists_iterator + : public llvm::iterator_adaptor_base< + const_component_lists_iterator, + MappableExprComponentListRef::const_iterator, + std::forward_iterator_tag, MappableComponent, ptrdiff_t, + MappableComponent, MappableComponent> { + // The declaration the iterator currently refers to. + ArrayRef::iterator DeclCur; + + // The list number associated with the current declaration. + ArrayRef::iterator NumListsCur; + + // Remaining lists for the current declaration. + unsigned RemainingLists; + + // The cumulative size of the previous list, or zero if there is no previous + // list. + unsigned PrevListSize; + + // The cumulative sizes of the current list - it will delimit the remaining + // range of interest. + ArrayRef::const_iterator ListSizeCur; + ArrayRef::const_iterator ListSizeEnd; + + // Iterator to the end of the components storage. + MappableExprComponentListRef::const_iterator End; + + public: + /// \brief Construct an iterator that scans all lists. + explicit const_component_lists_iterator( + ArrayRef UniqueDecls, ArrayRef DeclsListNum, + ArrayRef CumulativeListSizes, + MappableExprComponentListRef Components) + : const_component_lists_iterator::iterator_adaptor_base( + Components.begin()), + DeclCur(UniqueDecls.begin()), NumListsCur(DeclsListNum.begin()), + RemainingLists(0u), PrevListSize(0u), + ListSizeCur(CumulativeListSizes.begin()), + ListSizeEnd(CumulativeListSizes.end()), End(Components.end()) { + assert(UniqueDecls.size() == DeclsListNum.size() && + "Inconsistent number of declarations and list sizes!"); + if (!DeclsListNum.empty()) + RemainingLists = *NumListsCur; + } + + /// \brief Construct an iterator that scan lists for a given declaration \a + /// Declaration. + explicit const_component_lists_iterator( + const ValueDecl *Declaration, ArrayRef UniqueDecls, + ArrayRef DeclsListNum, ArrayRef CumulativeListSizes, + MappableExprComponentListRef Components) + : const_component_lists_iterator(UniqueDecls, DeclsListNum, + CumulativeListSizes, Components) { + + // Look for the desired declaration. While we are looking for it, we + // update the state so that we know the component where a given list + // starts. + for (; DeclCur != UniqueDecls.end(); ++DeclCur, ++NumListsCur) { + if (*DeclCur == Declaration) + break; + + assert(*NumListsCur > 0 && "No lists associated with declaration??"); + + // Skip the lists associated with the current declaration, but save the + // last list size that was skipped. + std::advance(ListSizeCur, *NumListsCur - 1); + PrevListSize = *ListSizeCur; + ++ListSizeCur; + } + + // If we didn't find any declaration, advance the iterator to after the + // last component and set remaining lists to zero. + if (ListSizeCur == CumulativeListSizes.end()) { + this->I = End; + RemainingLists = 0u; + return; + } + + // Set the remaining lists with the total number of lists of the current + // declaration. + RemainingLists = *NumListsCur; + + // Adjust the list size end iterator to the end of the relevant range. + ListSizeEnd = ListSizeCur; + std::advance(ListSizeEnd, RemainingLists); + + // Given that the list sizes are cumulative, the index of the component + // that start the list is the size of the previous list. + std::advance(this->I, PrevListSize); + } + + // Return the array with the current list. The sizes are cumulative, so the + // array size is the difference between the current size and previous one. + std::pair + operator*() const { + assert(ListSizeCur != ListSizeEnd && "Invalid iterator!"); + return std::make_pair( + *DeclCur, + MappableExprComponentListRef(&*this->I, *ListSizeCur - PrevListSize)); + } + std::pair + operator->() const { + return **this; + } + + // Skip the components of the current list. + const_component_lists_iterator &operator++() { + assert(ListSizeCur != ListSizeEnd && RemainingLists && + "Invalid iterator!"); + + // If we don't have more lists just skip all the components. Otherwise, + // advance the iterator by the number of components in the current list. + if (std::next(ListSizeCur) == ListSizeEnd) { + this->I = End; + RemainingLists = 0; + } else { + std::advance(this->I, *ListSizeCur - PrevListSize); + PrevListSize = *ListSizeCur; + + // We are done with a declaration, move to the next one. + if (!(--RemainingLists)) { + ++DeclCur; + ++NumListsCur; + RemainingLists = *NumListsCur; + assert(RemainingLists && "No lists in the following declaration??"); + } + } + + ++ListSizeCur; + return *this; + } + }; + + typedef llvm::iterator_range + const_component_lists_range; + + /// \brief Iterators for all component lists. + const_component_lists_iterator component_lists_begin() const { + return const_component_lists_iterator( + getUniqueDeclsRef(), getDeclNumListsRef(), getComponentListSizesRef(), + getComponentsRef()); + } + const_component_lists_iterator component_lists_end() const { + return const_component_lists_iterator( + ArrayRef(), ArrayRef(), ArrayRef(), + MappableExprComponentListRef(getComponentsRef().end(), + getComponentsRef().end())); + } + const_component_lists_range component_lists() const { + return {component_lists_begin(), component_lists_end()}; + } + + /// \brief Iterators for component lists associated with the provided + /// declaration. + const_component_lists_iterator + decl_component_lists_begin(const ValueDecl *VD) const { + return const_component_lists_iterator( + VD, getUniqueDeclsRef(), getDeclNumListsRef(), + getComponentListSizesRef(), getComponentsRef()); + } + const_component_lists_iterator decl_component_lists_end() const { + return component_lists_end(); + } + const_component_lists_range decl_component_lists(const ValueDecl *VD) const { + return {decl_component_lists_begin(VD), decl_component_lists_end()}; + } + + /// Iterators to access all the declarations, number of lists, list sizes, and + /// components. + typedef ArrayRef::iterator const_all_decls_iterator; + typedef llvm::iterator_range const_all_decls_range; + const_all_decls_range all_decls() const { + auto A = getUniqueDeclsRef(); + return const_all_decls_range(A.begin(), A.end()); + } + + typedef ArrayRef::iterator const_all_num_lists_iterator; + typedef llvm::iterator_range + const_all_num_lists_range; + const_all_num_lists_range all_num_lists() const { + auto A = getDeclNumListsRef(); + return const_all_num_lists_range(A.begin(), A.end()); + } + + typedef ArrayRef::iterator const_all_lists_sizes_iterator; + typedef llvm::iterator_range + const_all_lists_sizes_range; + const_all_lists_sizes_range all_lists_sizes() const { + auto A = getComponentListSizesRef(); + return const_all_lists_sizes_range(A.begin(), A.end()); + } + + typedef ArrayRef::iterator const_all_components_iterator; + typedef llvm::iterator_range + const_all_components_range; + const_all_components_range all_components() const { + auto A = getComponentsRef(); + return const_all_components_range(A.begin(), A.end()); + } +}; + /// \brief This represents clause 'map' in the '#pragma omp ...' /// directives. /// @@ -2731,16 +3279,33 @@ public: /// In this example directive '#pragma omp target' has clause 'map' /// with the variables 'a' and 'b'. /// -class OMPMapClause final : public OMPVarListClause, - private llvm::TrailingObjects { +class OMPMapClause final : public OMPMappableExprListClause, + private llvm::TrailingObjects< + OMPMapClause, Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent> { friend TrailingObjects; friend OMPVarListClause; + friend OMPMappableExprListClause; friend class OMPClauseReader; + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + /// \brief Map type modifier for the 'map' clause. OpenMPMapClauseKind MapTypeModifier; /// \brief Map type for the 'map' clause. OpenMPMapClauseKind MapType; + /// \brief Is this an implicit map type or not. + bool MapTypeIsImplicit; /// \brief Location of the map type. SourceLocation MapLoc; /// \brief Colon location. @@ -2767,30 +3332,49 @@ class OMPMapClause final : public OMPVarListClause, /// \brief Set colon location. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - /// \brief Build clause with number of variables \a N. + /// \brief Build a clause for \a NumVars listed expressions, \a + /// NumUniqueDeclarations declarations, \a NumComponentLists total component + /// lists, and \a NumComponents total expression components. /// /// \param MapTypeModifier Map type modifier. /// \param MapType Map type. + /// \param MapTypeIsImplicit Map type is inferred implicitly. /// \param MapLoc Location of the map type. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// \param N Number of the variables in the clause. + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. /// explicit OMPMapClause(OpenMPMapClauseKind MapTypeModifier, - OpenMPMapClauseKind MapType, SourceLocation MapLoc, - SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, unsigned N) - : OMPVarListClause(OMPC_map, StartLoc, LParenLoc, EndLoc, N), - MapTypeModifier(MapTypeModifier), MapType(MapType), MapLoc(MapLoc) {} + OpenMPMapClauseKind MapType, bool MapTypeIsImplicit, + SourceLocation MapLoc, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause(OMPC_map, StartLoc, LParenLoc, EndLoc, + NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents), + MapTypeModifier(MapTypeModifier), MapType(MapType), + MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) {} /// \brief Build an empty clause. /// - /// \param N Number of variables. + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. /// - explicit OMPMapClause(unsigned N) - : OMPVarListClause(OMPC_map, SourceLocation(), - SourceLocation(), SourceLocation(), N), - MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), MapLoc() {} + explicit OMPMapClause(unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause( + OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(), + NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents), + MapTypeModifier(OMPC_MAP_unknown), MapType(OMPC_MAP_unknown), + MapTypeIsImplicit(false), MapLoc() {} public: /// \brief Creates clause with a list of variables \a VL. @@ -2798,26 +3382,49 @@ public: /// \param C AST context. /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. - /// \param VL List of references to the variables. + /// \param Vars The original expression used in the clause. + /// \param Declarations Declarations used in the clause. + /// \param ComponentLists Component lists used in the clause. /// \param TypeModifier Map type modifier. /// \param Type Map type. + /// \param TypeIsImplicit Map type is inferred implicitly. /// \param TypeLoc Location of the map type. /// static OMPMapClause *Create(const ASTContext &C, SourceLocation StartLoc, - SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef VL, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef Vars, + ArrayRef Declarations, + MappableExprComponentListsRef ComponentLists, OpenMPMapClauseKind TypeModifier, - OpenMPMapClauseKind Type, SourceLocation TypeLoc); - /// \brief Creates an empty clause with the place for \a N variables. + OpenMPMapClauseKind Type, bool TypeIsImplicit, + SourceLocation TypeLoc); + /// \brief Creates an empty clause with the place for for \a NumVars original + /// expressions, \a NumUniqueDeclarations declarations, \NumComponentLists + /// lists, and \a NumComponents expression components. /// /// \param C AST context. - /// \param N The number of variables. - /// - static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned N); + /// \param NumVars Number of expressions listed in the clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of unique base declarations in this + /// clause. + /// \param NumComponents Total number of expression components in the clause. + /// + static OMPMapClause *CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents); /// \brief Fetches mapping kind for the clause. OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; } + /// \brief Is this an implicit map type? + /// We have to capture 'IsMapTypeImplicit' from the parser for more + /// informative error messages. It helps distinguish map(r) from + /// map(tofrom: r), which is important to print more helpful error + /// messages for some target directives. + bool isImplicitMapType() const LLVM_READONLY { return MapTypeIsImplicit; } + /// \brief Fetches the map type modifier for the clause. OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY { return MapTypeModifier; @@ -3193,6 +3800,553 @@ public: child_range children() { return child_range(&Hint, &Hint + 1); } }; +/// \brief This represents 'dist_schedule' clause in the '#pragma omp ...' +/// directive. +/// +/// \code +/// #pragma omp distribute dist_schedule(static, 3) +/// \endcode +/// In this example directive '#pragma omp distribute' has 'dist_schedule' +/// clause with arguments 'static' and '3'. +/// +class OMPDistScheduleClause : public OMPClause, public OMPClauseWithPreInit { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief A kind of the 'schedule' clause. + OpenMPDistScheduleClauseKind Kind; + /// \brief Start location of the schedule kind in source code. + SourceLocation KindLoc; + /// \brief Location of ',' (if any). + SourceLocation CommaLoc; + /// \brief Chunk size. + Expr *ChunkSize; + + /// \brief Set schedule kind. + /// + /// \param K Schedule kind. + /// + void setDistScheduleKind(OpenMPDistScheduleClauseKind K) { Kind = K; } + /// \brief Sets the location of '('. + /// + /// \param Loc Location of '('. + /// + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Set schedule kind start location. + /// + /// \param KLoc Schedule kind location. + /// + void setDistScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + /// \brief Set location of ','. + /// + /// \param Loc Location of ','. + /// + void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } + /// \brief Set chunk size. + /// + /// \param E Chunk size. + /// + void setChunkSize(Expr *E) { ChunkSize = E; } + +public: + /// \brief Build 'dist_schedule' clause with schedule kind \a Kind and chunk + /// size expression \a ChunkSize. + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param KLoc Starting location of the argument. + /// \param CommaLoc Location of ','. + /// \param EndLoc Ending location of the clause. + /// \param Kind DistSchedule kind. + /// \param ChunkSize Chunk size. + /// \param HelperChunkSize Helper chunk size for combined directives. + /// + OMPDistScheduleClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation KLoc, SourceLocation CommaLoc, + SourceLocation EndLoc, + OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, + Stmt *HelperChunkSize) + : OMPClause(OMPC_dist_schedule, StartLoc, EndLoc), + OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Kind(Kind), + KindLoc(KLoc), CommaLoc(CommaLoc), ChunkSize(ChunkSize) { + setPreInitStmt(HelperChunkSize); + } + + /// \brief Build an empty clause. + /// + explicit OMPDistScheduleClause() + : OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()), + OMPClauseWithPreInit(this), Kind(OMPC_DIST_SCHEDULE_unknown), + ChunkSize(nullptr) {} + + /// \brief Get kind of the clause. + /// + OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; } + /// \brief Get location of '('. + /// + SourceLocation getLParenLoc() { return LParenLoc; } + /// \brief Get kind location. + /// + SourceLocation getDistScheduleKindLoc() { return KindLoc; } + /// \brief Get location of ','. + /// + SourceLocation getCommaLoc() { return CommaLoc; } + /// \brief Get chunk size. + /// + Expr *getChunkSize() { return ChunkSize; } + /// \brief Get chunk size. + /// + const Expr *getChunkSize() const { return ChunkSize; } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_dist_schedule; + } + + child_range children() { + return child_range(reinterpret_cast(&ChunkSize), + reinterpret_cast(&ChunkSize) + 1); + } +}; + +/// \brief This represents 'defaultmap' clause in the '#pragma omp ...' directive. +/// +/// \code +/// #pragma omp target defaultmap(tofrom: scalar) +/// \endcode +/// In this example directive '#pragma omp target' has 'defaultmap' clause of kind +/// 'scalar' with modifier 'tofrom'. +/// +class OMPDefaultmapClause : public OMPClause { + friend class OMPClauseReader; + /// \brief Location of '('. + SourceLocation LParenLoc; + /// \brief Modifiers for 'defaultmap' clause. + OpenMPDefaultmapClauseModifier Modifier; + /// \brief Locations of modifiers. + SourceLocation ModifierLoc; + /// \brief A kind of the 'defaultmap' clause. + OpenMPDefaultmapClauseKind Kind; + /// \brief Start location of the defaultmap kind in source code. + SourceLocation KindLoc; + + /// \brief Set defaultmap kind. + /// + /// \param K Defaultmap kind. + /// + void setDefaultmapKind(OpenMPDefaultmapClauseKind K) { Kind = K; } + /// \brief Set the defaultmap modifier. + /// + /// \param M Defaultmap modifier. + /// + void setDefaultmapModifier(OpenMPDefaultmapClauseModifier M) { + Modifier = M; + } + /// \brief Set location of the defaultmap modifier. + /// + void setDefaultmapModifierLoc(SourceLocation Loc) { + ModifierLoc = Loc; + } + /// \brief Sets the location of '('. + /// + /// \param Loc Location of '('. + /// + void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } + /// \brief Set defaultmap kind start location. + /// + /// \param KLoc Defaultmap kind location. + /// + void setDefaultmapKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } + +public: + /// \brief Build 'defaultmap' clause with defaultmap kind \a Kind + /// + /// \param StartLoc Starting location of the clause. + /// \param LParenLoc Location of '('. + /// \param KLoc Starting location of the argument. + /// \param EndLoc Ending location of the clause. + /// \param Kind Defaultmap kind. + /// \param M The modifier applied to 'defaultmap' clause. + /// \param MLoc Location of the modifier + /// + OMPDefaultmapClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation MLoc, SourceLocation KLoc, + SourceLocation EndLoc, OpenMPDefaultmapClauseKind Kind, + OpenMPDefaultmapClauseModifier M) + : OMPClause(OMPC_defaultmap, StartLoc, EndLoc), LParenLoc(LParenLoc), + Modifier(M), ModifierLoc(MLoc), Kind(Kind), KindLoc(KLoc) {} + + /// \brief Build an empty clause. + /// + explicit OMPDefaultmapClause() + : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()), + Modifier(OMPC_DEFAULTMAP_MODIFIER_unknown), + Kind(OMPC_DEFAULTMAP_unknown) {} + + /// \brief Get kind of the clause. + /// + OpenMPDefaultmapClauseKind getDefaultmapKind() const { return Kind; } + /// \brief Get the modifier of the clause. + /// + OpenMPDefaultmapClauseModifier getDefaultmapModifier() const { + return Modifier; + } + /// \brief Get location of '('. + /// + SourceLocation getLParenLoc() { return LParenLoc; } + /// \brief Get kind location. + /// + SourceLocation getDefaultmapKindLoc() { return KindLoc; } + /// \brief Get the modifier location. + /// + SourceLocation getDefaultmapModifierLoc() const { + return ModifierLoc; + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_defaultmap; + } + + child_range children() { + return child_range(child_iterator(), child_iterator()); + } +}; + +/// \brief This represents clause 'to' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target update to(a,b) +/// \endcode +/// In this example directive '#pragma omp target update' has clause 'to' +/// with the variables 'a' and 'b'. +/// +class OMPToClause final : public OMPMappableExprListClause, + private llvm::TrailingObjects< + OMPToClause, Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent> { + friend TrailingObjects; + friend OMPVarListClause; + friend OMPMappableExprListClause; + friend class OMPClauseReader; + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + + /// \brief Build clause with number of variables \a NumVars. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. + /// + explicit OMPToClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause(OMPC_to, StartLoc, LParenLoc, EndLoc, NumVars, + NumUniqueDeclarations, NumComponentLists, + NumComponents) {} + + /// \brief Build an empty clause. + /// + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. + /// + explicit OMPToClause(unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause( + OMPC_to, SourceLocation(), SourceLocation(), SourceLocation(), + NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} + +public: + /// \brief Creates clause with a list of variables \a Vars. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param Vars The original expression used in the clause. + /// \param Declarations Declarations used in the clause. + /// \param ComponentLists Component lists used in the clause. + /// + static OMPToClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef Vars, + ArrayRef Declarations, + MappableExprComponentListsRef ComponentLists); + + /// \brief Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param NumVars Number of expressions listed in the clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of unique base declarations in this + /// clause. + /// \param NumComponents Total number of expression components in the clause. + /// + static OMPToClause *CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents); + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_to; + } + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } +}; + +/// \brief This represents clause 'from' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target update from(a,b) +/// \endcode +/// In this example directive '#pragma omp target update' has clause 'from' +/// with the variables 'a' and 'b'. +/// +class OMPFromClause final + : public OMPMappableExprListClause, + private llvm::TrailingObjects< + OMPFromClause, Expr *, ValueDecl *, unsigned, + OMPClauseMappableExprCommon::MappableComponent> { + friend TrailingObjects; + friend OMPVarListClause; + friend OMPMappableExprListClause; + friend class OMPClauseReader; + + /// Define the sizes of each trailing object array except the last one. This + /// is required for TrailingObjects to work properly. + size_t numTrailingObjects(OverloadToken) const { + return varlist_size(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum(); + } + size_t numTrailingObjects(OverloadToken) const { + return getUniqueDeclarationsNum() + getTotalComponentListNum(); + } + + /// \brief Build clause with number of variables \a NumVars. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. + /// + explicit OMPFromClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause(OMPC_from, StartLoc, LParenLoc, EndLoc, + NumVars, NumUniqueDeclarations, + NumComponentLists, NumComponents) {} + + /// \brief Build an empty clause. + /// + /// \param NumVars Number of expressions listed in this clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of component lists in this clause. + /// \param NumComponents Total number of expression components in the clause. + /// + explicit OMPFromClause(unsigned NumVars, unsigned NumUniqueDeclarations, + unsigned NumComponentLists, unsigned NumComponents) + : OMPMappableExprListClause( + OMPC_from, SourceLocation(), SourceLocation(), SourceLocation(), + NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} + +public: + /// \brief Creates clause with a list of variables \a Vars. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// \param Vars The original expression used in the clause. + /// \param Declarations Declarations used in the clause. + /// \param ComponentLists Component lists used in the clause. + /// + static OMPFromClause *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation LParenLoc, SourceLocation EndLoc, + ArrayRef Vars, + ArrayRef Declarations, + MappableExprComponentListsRef ComponentLists); + + /// \brief Creates an empty clause with the place for \a NumVars variables. + /// + /// \param C AST context. + /// \param NumVars Number of expressions listed in the clause. + /// \param NumUniqueDeclarations Number of unique base declarations in this + /// clause. + /// \param NumComponentLists Number of unique base declarations in this + /// clause. + /// \param NumComponents Total number of expression components in the clause. + /// + static OMPFromClause *CreateEmpty(const ASTContext &C, unsigned NumVars, + unsigned NumUniqueDeclarations, + unsigned NumComponentLists, + unsigned NumComponents); + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_from; + } + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } +}; + +/// This represents clause 'use_device_ptr' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target data use_device_ptr(a,b) +/// \endcode +/// In this example directive '#pragma omp target data' has clause +/// 'use_device_ptr' with the variables 'a' and 'b'. +/// +class OMPUseDevicePtrClause final + : public OMPVarListClause, + private llvm::TrailingObjects { + friend TrailingObjects; + friend OMPVarListClause; + friend class OMPClauseReader; + /// 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. + /// + OMPUseDevicePtrClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause(OMPC_use_device_ptr, StartLoc, + LParenLoc, EndLoc, N) {} + + /// \brief Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPUseDevicePtrClause(unsigned N) + : OMPVarListClause( + OMPC_use_device_ptr, SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// 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 OMPUseDevicePtrClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef VL); + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPUseDevicePtrClause *CreateEmpty(const ASTContext &C, unsigned N); + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_use_device_ptr; + } +}; + +/// This represents clause 'is_device_ptr' in the '#pragma omp ...' +/// directives. +/// +/// \code +/// #pragma omp target is_device_ptr(a,b) +/// \endcode +/// In this example directive '#pragma omp target' has clause +/// 'is_device_ptr' with the variables 'a' and 'b'. +/// +class OMPIsDevicePtrClause final + : public OMPVarListClause, + private llvm::TrailingObjects { + friend TrailingObjects; + friend OMPVarListClause; + friend class OMPClauseReader; + /// 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. + /// + OMPIsDevicePtrClause(SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, unsigned N) + : OMPVarListClause(OMPC_is_device_ptr, StartLoc, + LParenLoc, EndLoc, N) {} + + /// Build an empty clause. + /// + /// \param N Number of variables. + /// + explicit OMPIsDevicePtrClause(unsigned N) + : OMPVarListClause( + OMPC_is_device_ptr, SourceLocation(), SourceLocation(), + SourceLocation(), N) {} + +public: + /// 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 OMPIsDevicePtrClause * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc, ArrayRef VL); + /// Creates an empty clause with the place for \a N variables. + /// + /// \param C AST context. + /// \param N The number of variables. + /// + static OMPIsDevicePtrClause *CreateEmpty(const ASTContext &C, unsigned N); + + child_range children() { + return child_range(reinterpret_cast(varlist_begin()), + reinterpret_cast(varlist_end())); + } + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_is_device_ptr; + } +}; } // end namespace clang #endif // LLVM_CLANG_AST_OPENMPCLAUSE_H diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def new file mode 100644 index 0000000000000..82f494bec9951 --- /dev/null +++ b/include/clang/AST/OperationKinds.def @@ -0,0 +1,406 @@ +//===--- OperationKinds.def - Operations Database ---------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file enumerates the different kinds of operations that can be +// performed by various expressions. +// +//===----------------------------------------------------------------------===// +// +/// @file OperationKinds.def +/// +/// In this file, each of the C/C++ operations is enumerated CAST_OPERATION, +/// BINARY_OPERATION or UNARY_OPERATION macro, each of which can be specified by +/// the code including this file. +/// +/// Macros had one or two arguments: +/// +/// Name: The name of the operation. Name (prefixed with CK_, UO_ or BO_) will +/// be the name of the corresponding enumerator (see OperationsKinds.h). +/// +/// Spelling: A string that provides a canonical spelling for the operation. + +#ifndef CAST_OPERATION +# define CAST_OPERATION(Name) +#endif + +#ifndef BINARY_OPERATION +# define BINARY_OPERATION(Name, Spelling) +#endif + +#ifndef UNARY_OPERATION +# define UNARY_OPERATION(Name, Spelling) +#endif + +//===- Cast Operations ---------------------------------------------------===// + +/// CK_Dependent - A conversion which cannot yet be analyzed because +/// either the expression or target type is dependent. These are +/// created only for explicit casts; dependent ASTs aren't required +/// to even approximately type-check. +/// (T*) malloc(sizeof(T)) +/// reinterpret_cast(A::alloc()); +CAST_OPERATION(Dependent) + +/// CK_BitCast - A conversion which causes a bit pattern of one type +/// to be reinterpreted as a bit pattern of another type. Generally +/// the operands must have equivalent size and unrelated types. +/// +/// The pointer conversion char* -> int* is a bitcast. A conversion +/// from any pointer type to a C pointer type is a bitcast unless +/// it's actually BaseToDerived or DerivedToBase. A conversion to a +/// block pointer or ObjC pointer type is a bitcast only if the +/// operand has the same type kind; otherwise, it's one of the +/// specialized casts below. +/// +/// Vector coercions are bitcasts. +CAST_OPERATION(BitCast) + +/// CK_LValueBitCast - A conversion which reinterprets the address of +/// an l-value as an l-value of a different kind. Used for +/// reinterpret_casts of l-value expressions to reference types. +/// bool b; reinterpret_cast(b) = 'a'; +CAST_OPERATION(LValueBitCast) + +/// CK_LValueToRValue - A conversion which causes the extraction of +/// an r-value from the operand gl-value. The result of an r-value +/// conversion is always unqualified. +CAST_OPERATION(LValueToRValue) + +/// CK_NoOp - A conversion which does not affect the type other than +/// (possibly) adding qualifiers. +/// int -> int +/// char** -> const char * const * +CAST_OPERATION(NoOp) + +/// CK_BaseToDerived - A conversion from a C++ class pointer/reference +/// to a derived class pointer/reference. +/// B *b = static_cast(a); +CAST_OPERATION(BaseToDerived) + +/// CK_DerivedToBase - A conversion from a C++ class pointer +/// to a base class pointer. +/// A *a = new B(); +CAST_OPERATION(DerivedToBase) + +/// CK_UncheckedDerivedToBase - A conversion from a C++ class +/// pointer/reference to a base class that can assume that the +/// derived pointer is not null. +/// const A &a = B(); +/// b->method_from_a(); +CAST_OPERATION(UncheckedDerivedToBase) + +/// CK_Dynamic - A C++ dynamic_cast. +CAST_OPERATION(Dynamic) + +/// CK_ToUnion - The GCC cast-to-union extension. +/// int -> union { int x; float y; } +/// float -> union { int x; float y; } +CAST_OPERATION(ToUnion) + +/// CK_ArrayToPointerDecay - Array to pointer decay. +/// int[10] -> int* +/// char[5][6] -> char(*)[6] +CAST_OPERATION(ArrayToPointerDecay) + +/// CK_FunctionToPointerDecay - Function to pointer decay. +/// void(int) -> void(*)(int) +CAST_OPERATION(FunctionToPointerDecay) + +/// CK_NullToPointer - Null pointer constant to pointer, ObjC +/// pointer, or block pointer. +/// (void*) 0 +/// void (^block)() = 0; +CAST_OPERATION(NullToPointer) + +/// CK_NullToMemberPointer - Null pointer constant to member pointer. +/// int A::*mptr = 0; +/// int (A::*fptr)(int) = nullptr; +CAST_OPERATION(NullToMemberPointer) + +/// CK_BaseToDerivedMemberPointer - Member pointer in base class to +/// member pointer in derived class. +/// int B::*mptr = &A::member; +CAST_OPERATION(BaseToDerivedMemberPointer) + +/// CK_DerivedToBaseMemberPointer - Member pointer in derived class to +/// member pointer in base class. +/// int A::*mptr = static_cast(&B::member); +CAST_OPERATION(DerivedToBaseMemberPointer) + +/// CK_MemberPointerToBoolean - Member pointer to boolean. A check +/// against the null member pointer. +CAST_OPERATION(MemberPointerToBoolean) + +/// CK_ReinterpretMemberPointer - Reinterpret a member pointer as a +/// different kind of member pointer. C++ forbids this from +/// crossing between function and object types, but otherwise does +/// not restrict it. However, the only operation that is permitted +/// on a "punned" member pointer is casting it back to the original +/// type, which is required to be a lossless operation (although +/// many ABIs do not guarantee this on all possible intermediate types). +CAST_OPERATION(ReinterpretMemberPointer) + +/// CK_UserDefinedConversion - Conversion using a user defined type +/// conversion function. +/// struct A { operator int(); }; int i = int(A()); +CAST_OPERATION(UserDefinedConversion) + +/// CK_ConstructorConversion - Conversion by constructor. +/// struct A { A(int); }; A a = A(10); +CAST_OPERATION(ConstructorConversion) + +/// CK_IntegralToPointer - Integral to pointer. A special kind of +/// reinterpreting conversion. Applies to normal, ObjC, and block +/// pointers. +/// (char*) 0x1001aab0 +/// reinterpret_cast(0) +CAST_OPERATION(IntegralToPointer) + +/// CK_PointerToIntegral - Pointer to integral. A special kind of +/// reinterpreting conversion. Applies to normal, ObjC, and block +/// pointers. +/// (intptr_t) "help!" +CAST_OPERATION(PointerToIntegral) + +/// CK_PointerToBoolean - Pointer to boolean conversion. A check +/// against null. Applies to normal, ObjC, and block pointers. +CAST_OPERATION(PointerToBoolean) + +/// CK_ToVoid - Cast to void, discarding the computed value. +/// (void) malloc(2048) +CAST_OPERATION(ToVoid) + +/// CK_VectorSplat - A conversion from an arithmetic type to a +/// vector of that element type. Fills all elements ("splats") with +/// the source value. +/// __attribute__((ext_vector_type(4))) int v = 5; +CAST_OPERATION(VectorSplat) + +/// CK_IntegralCast - A cast between integral types (other than to +/// boolean). Variously a bitcast, a truncation, a sign-extension, +/// or a zero-extension. +/// long l = 5; +/// (unsigned) i +CAST_OPERATION(IntegralCast) + +/// CK_IntegralToBoolean - Integral to boolean. A check against zero. +/// (bool) i +CAST_OPERATION(IntegralToBoolean) + +/// CK_IntegralToFloating - Integral to floating point. +/// float f = i; +CAST_OPERATION(IntegralToFloating) + +/// CK_FloatingToIntegral - Floating point to integral. Rounds +/// towards zero, discarding any fractional component. +/// (int) f +CAST_OPERATION(FloatingToIntegral) + +/// CK_FloatingToBoolean - Floating point to boolean. +/// (bool) f +CAST_OPERATION(FloatingToBoolean) + +// CK_BooleanToSignedIntegral - Convert a boolean to -1 or 0 for true and +// false, respectively. +CAST_OPERATION(BooleanToSignedIntegral) + +/// CK_FloatingCast - Casting between floating types of different size. +/// (double) f +/// (float) ld +CAST_OPERATION(FloatingCast) + +/// CK_CPointerToObjCPointerCast - Casting a C pointer kind to an +/// Objective-C pointer. +CAST_OPERATION(CPointerToObjCPointerCast) + +/// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an +/// ObjC pointer. +CAST_OPERATION(BlockPointerToObjCPointerCast) + +/// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer +/// to a block pointer. Block-to-block casts are bitcasts. +CAST_OPERATION(AnyPointerToBlockPointerCast) + +/// \brief Converting between two Objective-C object types, which +/// can occur when performing reference binding to an Objective-C +/// object. +CAST_OPERATION(ObjCObjectLValueCast) + +/// \brief A conversion of a floating point real to a floating point +/// complex of the original type. Injects the value as the real +/// component with a zero imaginary component. +/// float -> _Complex float +CAST_OPERATION(FloatingRealToComplex) + +/// \brief Converts a floating point complex to floating point real +/// of the source's element type. Just discards the imaginary +/// component. +/// _Complex long double -> long double +CAST_OPERATION(FloatingComplexToReal) + +/// \brief Converts a floating point complex to bool by comparing +/// against 0+0i. +CAST_OPERATION(FloatingComplexToBoolean) + +/// \brief Converts between different floating point complex types. +/// _Complex float -> _Complex double +CAST_OPERATION(FloatingComplexCast) + +/// \brief Converts from a floating complex to an integral complex. +/// _Complex float -> _Complex int +CAST_OPERATION(FloatingComplexToIntegralComplex) + +/// \brief Converts from an integral real to an integral complex +/// whose element type matches the source. Injects the value as +/// the real component with a zero imaginary component. +/// long -> _Complex long +CAST_OPERATION(IntegralRealToComplex) + +/// \brief Converts an integral complex to an integral real of the +/// source's element type by discarding the imaginary component. +/// _Complex short -> short +CAST_OPERATION(IntegralComplexToReal) + +/// \brief Converts an integral complex to bool by comparing against +/// 0+0i. +CAST_OPERATION(IntegralComplexToBoolean) + +/// \brief Converts between different integral complex types. +/// _Complex char -> _Complex long long +/// _Complex unsigned int -> _Complex signed int +CAST_OPERATION(IntegralComplexCast) + +/// \brief Converts from an integral complex to a floating complex. +/// _Complex unsigned -> _Complex float +CAST_OPERATION(IntegralComplexToFloatingComplex) + +/// \brief [ARC] Produces a retainable object pointer so that it may +/// be consumed, e.g. by being passed to a consuming parameter. +/// Calls objc_retain. +CAST_OPERATION(ARCProduceObject) + +/// \brief [ARC] Consumes a retainable object pointer that has just +/// been produced, e.g. as the return value of a retaining call. +/// Enters a cleanup to call objc_release at some indefinite time. +CAST_OPERATION(ARCConsumeObject) + +/// \brief [ARC] Reclaim a retainable object pointer object that may +/// have been produced and autoreleased as part of a function return +/// sequence. +CAST_OPERATION(ARCReclaimReturnedObject) + +/// \brief [ARC] Causes a value of block type to be copied to the +/// heap, if it is not already there. A number of other operations +/// in ARC cause blocks to be copied; this is for cases where that +/// would not otherwise be guaranteed, such as when casting to a +/// non-block pointer type. +CAST_OPERATION(ARCExtendBlockObject) + +/// \brief Converts from _Atomic(T) to T. +CAST_OPERATION(AtomicToNonAtomic) +/// \brief Converts from T to _Atomic(T). +CAST_OPERATION(NonAtomicToAtomic) + +/// \brief Causes a block literal to by copied to the heap and then +/// autoreleased. +/// +/// This particular cast kind is used for the conversion from a C++11 +/// lambda expression to a block pointer. +CAST_OPERATION(CopyAndAutoreleaseBlockObject) + +// Convert a builtin function to a function pointer; only allowed in the +// callee of a call expression. +CAST_OPERATION(BuiltinFnToFnPtr) + +// Convert a zero value for OpenCL event_t initialization. +CAST_OPERATION(ZeroToOCLEvent) + +// Convert a pointer to a different address space. +CAST_OPERATION(AddressSpaceConversion) + + +//===- Binary Operations -------------------------------------------------===// +// Operators listed in order of precedence. +// Note that additions to this should also update the StmtVisitor class. + +// [C++ 5.5] Pointer-to-member operators. +BINARY_OPERATION(PtrMemD, ".*") +BINARY_OPERATION(PtrMemI, "->*") +// [C99 6.5.5] Multiplicative operators. +BINARY_OPERATION(Mul, "*") +BINARY_OPERATION(Div, "/") +BINARY_OPERATION(Rem, "%") +// [C99 6.5.6] Additive operators. +BINARY_OPERATION(Add, "+") +BINARY_OPERATION(Sub, "-") +// [C99 6.5.7] Bitwise shift operators. +BINARY_OPERATION(Shl, "<<") +BINARY_OPERATION(Shr, ">>") +// [C99 6.5.8] Relational operators. +BINARY_OPERATION(LT, "<") +BINARY_OPERATION(GT, ">") +BINARY_OPERATION(LE, "<=") +BINARY_OPERATION(GE, ">=") +// [C99 6.5.9] Equality operators. +BINARY_OPERATION(EQ, "==") +BINARY_OPERATION(NE, "!=") +// [C99 6.5.10] Bitwise AND operator. +BINARY_OPERATION(And, "&") +// [C99 6.5.11] Bitwise XOR operator. +BINARY_OPERATION(Xor, "^") +// [C99 6.5.12] Bitwise OR operator. +BINARY_OPERATION(Or, "|") +// [C99 6.5.13] Logical AND operator. +BINARY_OPERATION(LAnd, "&&") +// [C99 6.5.14] Logical OR operator. +BINARY_OPERATION(LOr, "||") +// [C99 6.5.16] Assignment operators. +BINARY_OPERATION(Assign, "=") +BINARY_OPERATION(MulAssign, "*=") +BINARY_OPERATION(DivAssign, "/=") +BINARY_OPERATION(RemAssign, "%=") +BINARY_OPERATION(AddAssign, "+=") +BINARY_OPERATION(SubAssign, "-=") +BINARY_OPERATION(ShlAssign, "<<=") +BINARY_OPERATION(ShrAssign, ">>=") +BINARY_OPERATION(AndAssign, "&=") +BINARY_OPERATION(XorAssign, "^=") +BINARY_OPERATION(OrAssign, "|=") +// [C99 6.5.17] Comma operator. +BINARY_OPERATION(Comma, ",") + + +//===- Unary Operations ---------------------------------------------------===// +// Note that additions to this should also update the StmtVisitor class. + +// [C99 6.5.2.4] Postfix increment and decrement +UNARY_OPERATION(PostInc, "++") +UNARY_OPERATION(PostDec, "--") +// [C99 6.5.3.1] Prefix increment and decrement +UNARY_OPERATION(PreInc, "++") +UNARY_OPERATION(PreDec, "--") +// [C99 6.5.3.2] Address and indirection +UNARY_OPERATION(AddrOf, "&") +UNARY_OPERATION(Deref, "*") +// [C99 6.5.3.3] Unary arithmetic +UNARY_OPERATION(Plus, "+") +UNARY_OPERATION(Minus, "-") +UNARY_OPERATION(Not, "~") +UNARY_OPERATION(LNot, "!") +// "__real expr"/"__imag expr" Extension. +UNARY_OPERATION(Real, "__real") +UNARY_OPERATION(Imag, "__imag") +// __extension__ marker. +UNARY_OPERATION(Extension, "__extension__") +// [C++ Coroutines] co_await operator +UNARY_OPERATION(Coawait, "co_await") + +#undef CAST_OPERATION +#undef BINARY_OPERATION +#undef UNARY_OPERATION diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index 102bbc21edb37..00f060fe9e3d0 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -19,327 +19,20 @@ namespace clang { /// CastKind - The kind of operation required for a conversion. enum CastKind { - /// CK_Dependent - A conversion which cannot yet be analyzed because - /// either the expression or target type is dependent. These are - /// created only for explicit casts; dependent ASTs aren't required - /// to even approximately type-check. - /// (T*) malloc(sizeof(T)) - /// reinterpret_cast(A::alloc()); - CK_Dependent, - - /// CK_BitCast - A conversion which causes a bit pattern of one type - /// to be reinterpreted as a bit pattern of another type. Generally - /// the operands must have equivalent size and unrelated types. - /// - /// The pointer conversion char* -> int* is a bitcast. A conversion - /// from any pointer type to a C pointer type is a bitcast unless - /// it's actually BaseToDerived or DerivedToBase. A conversion to a - /// block pointer or ObjC pointer type is a bitcast only if the - /// operand has the same type kind; otherwise, it's one of the - /// specialized casts below. - /// - /// Vector coercions are bitcasts. - CK_BitCast, - - /// CK_LValueBitCast - A conversion which reinterprets the address of - /// an l-value as an l-value of a different kind. Used for - /// reinterpret_casts of l-value expressions to reference types. - /// bool b; reinterpret_cast(b) = 'a'; - CK_LValueBitCast, - - /// CK_LValueToRValue - A conversion which causes the extraction of - /// an r-value from the operand gl-value. The result of an r-value - /// conversion is always unqualified. - CK_LValueToRValue, - - /// CK_NoOp - A conversion which does not affect the type other than - /// (possibly) adding qualifiers. - /// int -> int - /// char** -> const char * const * - CK_NoOp, - - /// CK_BaseToDerived - A conversion from a C++ class pointer/reference - /// to a derived class pointer/reference. - /// B *b = static_cast(a); - CK_BaseToDerived, - - /// CK_DerivedToBase - A conversion from a C++ class pointer - /// to a base class pointer. - /// A *a = new B(); - CK_DerivedToBase, - - /// CK_UncheckedDerivedToBase - A conversion from a C++ class - /// pointer/reference to a base class that can assume that the - /// derived pointer is not null. - /// const A &a = B(); - /// b->method_from_a(); - CK_UncheckedDerivedToBase, - - /// CK_Dynamic - A C++ dynamic_cast. - CK_Dynamic, - - /// CK_ToUnion - The GCC cast-to-union extension. - /// int -> union { int x; float y; } - /// float -> union { int x; float y; } - CK_ToUnion, - - /// CK_ArrayToPointerDecay - Array to pointer decay. - /// int[10] -> int* - /// char[5][6] -> char(*)[6] - CK_ArrayToPointerDecay, - - /// CK_FunctionToPointerDecay - Function to pointer decay. - /// void(int) -> void(*)(int) - CK_FunctionToPointerDecay, - - /// CK_NullToPointer - Null pointer constant to pointer, ObjC - /// pointer, or block pointer. - /// (void*) 0 - /// void (^block)() = 0; - CK_NullToPointer, - - /// CK_NullToMemberPointer - Null pointer constant to member pointer. - /// int A::*mptr = 0; - /// int (A::*fptr)(int) = nullptr; - CK_NullToMemberPointer, - - /// CK_BaseToDerivedMemberPointer - Member pointer in base class to - /// member pointer in derived class. - /// int B::*mptr = &A::member; - CK_BaseToDerivedMemberPointer, - - /// CK_DerivedToBaseMemberPointer - Member pointer in derived class to - /// member pointer in base class. - /// int A::*mptr = static_cast(&B::member); - CK_DerivedToBaseMemberPointer, - - /// CK_MemberPointerToBoolean - Member pointer to boolean. A check - /// against the null member pointer. - CK_MemberPointerToBoolean, - - /// CK_ReinterpretMemberPointer - Reinterpret a member pointer as a - /// different kind of member pointer. C++ forbids this from - /// crossing between function and object types, but otherwise does - /// not restrict it. However, the only operation that is permitted - /// on a "punned" member pointer is casting it back to the original - /// type, which is required to be a lossless operation (although - /// many ABIs do not guarantee this on all possible intermediate types). - CK_ReinterpretMemberPointer, - - /// CK_UserDefinedConversion - Conversion using a user defined type - /// conversion function. - /// struct A { operator int(); }; int i = int(A()); - CK_UserDefinedConversion, - - /// CK_ConstructorConversion - Conversion by constructor. - /// struct A { A(int); }; A a = A(10); - CK_ConstructorConversion, - - /// CK_IntegralToPointer - Integral to pointer. A special kind of - /// reinterpreting conversion. Applies to normal, ObjC, and block - /// pointers. - /// (char*) 0x1001aab0 - /// reinterpret_cast(0) - CK_IntegralToPointer, - - /// CK_PointerToIntegral - Pointer to integral. A special kind of - /// reinterpreting conversion. Applies to normal, ObjC, and block - /// pointers. - /// (intptr_t) "help!" - CK_PointerToIntegral, - - /// CK_PointerToBoolean - Pointer to boolean conversion. A check - /// against null. Applies to normal, ObjC, and block pointers. - CK_PointerToBoolean, - - /// CK_ToVoid - Cast to void, discarding the computed value. - /// (void) malloc(2048) - CK_ToVoid, - - /// CK_VectorSplat - A conversion from an arithmetic type to a - /// vector of that element type. Fills all elements ("splats") with - /// the source value. - /// __attribute__((ext_vector_type(4))) int v = 5; - CK_VectorSplat, - - /// CK_IntegralCast - A cast between integral types (other than to - /// boolean). Variously a bitcast, a truncation, a sign-extension, - /// or a zero-extension. - /// long l = 5; - /// (unsigned) i - CK_IntegralCast, - - /// CK_IntegralToBoolean - Integral to boolean. A check against zero. - /// (bool) i - CK_IntegralToBoolean, - - /// CK_IntegralToFloating - Integral to floating point. - /// float f = i; - CK_IntegralToFloating, - - /// CK_FloatingToIntegral - Floating point to integral. Rounds - /// towards zero, discarding any fractional component. - /// (int) f - CK_FloatingToIntegral, - - /// CK_FloatingToBoolean - Floating point to boolean. - /// (bool) f - CK_FloatingToBoolean, - - // CK_BooleanToSignedIntegral - Convert a boolean to -1 or 0 for true and - // false, respectively. - CK_BooleanToSignedIntegral, - - /// CK_FloatingCast - Casting between floating types of different size. - /// (double) f - /// (float) ld - CK_FloatingCast, - - /// CK_CPointerToObjCPointerCast - Casting a C pointer kind to an - /// Objective-C pointer. - CK_CPointerToObjCPointerCast, - - /// CK_BlockPointerToObjCPointerCast - Casting a block pointer to an - /// ObjC pointer. - CK_BlockPointerToObjCPointerCast, - - /// CK_AnyPointerToBlockPointerCast - Casting any non-block pointer - /// to a block pointer. Block-to-block casts are bitcasts. - CK_AnyPointerToBlockPointerCast, - - /// \brief Converting between two Objective-C object types, which - /// can occur when performing reference binding to an Objective-C - /// object. - CK_ObjCObjectLValueCast, - - /// \brief A conversion of a floating point real to a floating point - /// complex of the original type. Injects the value as the real - /// component with a zero imaginary component. - /// float -> _Complex float - CK_FloatingRealToComplex, - - /// \brief Converts a floating point complex to floating point real - /// of the source's element type. Just discards the imaginary - /// component. - /// _Complex long double -> long double - CK_FloatingComplexToReal, - - /// \brief Converts a floating point complex to bool by comparing - /// against 0+0i. - CK_FloatingComplexToBoolean, - - /// \brief Converts between different floating point complex types. - /// _Complex float -> _Complex double - CK_FloatingComplexCast, - - /// \brief Converts from a floating complex to an integral complex. - /// _Complex float -> _Complex int - CK_FloatingComplexToIntegralComplex, - - /// \brief Converts from an integral real to an integral complex - /// whose element type matches the source. Injects the value as - /// the real component with a zero imaginary component. - /// long -> _Complex long - CK_IntegralRealToComplex, - - /// \brief Converts an integral complex to an integral real of the - /// source's element type by discarding the imaginary component. - /// _Complex short -> short - CK_IntegralComplexToReal, - - /// \brief Converts an integral complex to bool by comparing against - /// 0+0i. - CK_IntegralComplexToBoolean, - - /// \brief Converts between different integral complex types. - /// _Complex char -> _Complex long long - /// _Complex unsigned int -> _Complex signed int - CK_IntegralComplexCast, - - /// \brief Converts from an integral complex to a floating complex. - /// _Complex unsigned -> _Complex float - CK_IntegralComplexToFloatingComplex, - - /// \brief [ARC] Produces a retainable object pointer so that it may - /// be consumed, e.g. by being passed to a consuming parameter. - /// Calls objc_retain. - CK_ARCProduceObject, - - /// \brief [ARC] Consumes a retainable object pointer that has just - /// been produced, e.g. as the return value of a retaining call. - /// Enters a cleanup to call objc_release at some indefinite time. - CK_ARCConsumeObject, - - /// \brief [ARC] Reclaim a retainable object pointer object that may - /// have been produced and autoreleased as part of a function return - /// sequence. - CK_ARCReclaimReturnedObject, - - /// \brief [ARC] Causes a value of block type to be copied to the - /// heap, if it is not already there. A number of other operations - /// in ARC cause blocks to be copied; this is for cases where that - /// would not otherwise be guaranteed, such as when casting to a - /// non-block pointer type. - CK_ARCExtendBlockObject, - - /// \brief Converts from _Atomic(T) to T. - CK_AtomicToNonAtomic, - /// \brief Converts from T to _Atomic(T). - CK_NonAtomicToAtomic, - - /// \brief Causes a block literal to by copied to the heap and then - /// autoreleased. - /// - /// This particular cast kind is used for the conversion from a C++11 - /// lambda expression to a block pointer. - CK_CopyAndAutoreleaseBlockObject, - - // Convert a builtin function to a function pointer; only allowed in the - // callee of a call expression. - CK_BuiltinFnToFnPtr, - - // Convert a zero value for OpenCL event_t initialization. - CK_ZeroToOCLEvent, - - // Convert a pointer to a different address space. - CK_AddressSpaceConversion +#define CAST_OPERATION(Name) CK_##Name, +#include "clang/AST/OperationKinds.def" }; static const CastKind CK_Invalid = static_cast(-1); enum BinaryOperatorKind { - // Operators listed in order of precedence. - // Note that additions to this should also update the StmtVisitor class. - BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. - BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. - BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. - BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. - BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. - BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. - BO_And, // [C99 6.5.10] Bitwise AND operator. - BO_Xor, // [C99 6.5.11] Bitwise XOR operator. - BO_Or, // [C99 6.5.12] Bitwise OR operator. - BO_LAnd, // [C99 6.5.13] Logical AND operator. - BO_LOr, // [C99 6.5.14] Logical OR operator. - BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. - BO_DivAssign, BO_RemAssign, - BO_AddAssign, BO_SubAssign, - BO_ShlAssign, BO_ShrAssign, - BO_AndAssign, BO_XorAssign, - BO_OrAssign, - BO_Comma // [C99 6.5.17] Comma operator. +#define BINARY_OPERATION(Name, Spelling) BO_##Name, +#include "clang/AST/OperationKinds.def" }; enum UnaryOperatorKind { - // Note that additions to this should also update the StmtVisitor class. - UO_PostInc, UO_PostDec, // [C99 6.5.2.4] Postfix increment and decrement - UO_PreInc, UO_PreDec, // [C99 6.5.3.1] Prefix increment and decrement - UO_AddrOf, UO_Deref, // [C99 6.5.3.2] Address and indirection - UO_Plus, UO_Minus, // [C99 6.5.3.3] Unary arithmetic - UO_Not, UO_LNot, // [C99 6.5.3.3] Unary arithmetic - UO_Real, UO_Imag, // "__real expr"/"__imag expr" Extension. - UO_Extension, // __extension__ marker. - UO_Coawait // [C++ Coroutines] co_await operator +#define UNARY_OPERATION(Name, Spelling) UO_##Name, +#include "clang/AST/OperationKinds.def" }; /// \brief The kind of bridging performed by the Objective-C bridge cast. @@ -355,6 +48,6 @@ enum ObjCBridgeCastKind { OBC_BridgeRetained }; -} +} // end namespace clang #endif diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 8ab3f61703a3c..274df220e160e 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -32,20 +32,35 @@ public: /// \brief Describes how types, statements, expressions, and /// declarations should be printed. +/// +/// This type is intended to be small and suitable for passing by value. +/// It is very frequently copied. struct PrintingPolicy { - /// \brief Create a default printing policy for C. + /// \brief Create a default printing policy for the specified language. PrintingPolicy(const LangOptions &LO) - : LangOpts(LO), Indentation(2), SuppressSpecifiers(false), - SuppressTagKeyword(false), SuppressTag(false), SuppressScope(false), + : Indentation(2), SuppressSpecifiers(false), + SuppressTagKeyword(LO.CPlusPlus), + IncludeTagDefinition(false), SuppressScope(false), SuppressUnwrittenScope(false), SuppressInitializers(false), ConstantArraySizeAsWritten(false), AnonymousTagLocations(true), SuppressStrongLifetime(false), SuppressLifetimeQualifiers(false), - Bool(LO.Bool), TerseOutput(false), PolishForDeclaration(false), + SuppressTemplateArgsInCXXConstructors(false), + Bool(LO.Bool), Restrict(LO.C99), + Alignof(LO.CPlusPlus11), UnderscoreAlignof(LO.C11), + UseVoidForZeroParams(!LO.CPlusPlus), + TerseOutput(false), PolishForDeclaration(false), Half(LO.Half), MSWChar(LO.MicrosoftExt && !LO.WChar), IncludeNewlines(true), MSVCFormatting(false) { } - /// \brief What language we're printing. - LangOptions LangOpts; + /// \brief Adjust this printing policy for cases where it's known that + /// we're printing C++ code (for instance, if AST dumping reaches a + /// C++-only construct). This should not be used if a real LangOptions + /// object is available. + void adjustForCPlusPlus() { + SuppressTagKeyword = true; + Bool = true; + UseVoidForZeroParams = false; + } /// \brief The number of spaces to use to indent each line. unsigned Indentation : 8; @@ -76,15 +91,15 @@ struct PrintingPolicy { /// \endcode bool SuppressTagKeyword : 1; - /// \brief Whether type printing should skip printing the actual tag type. + /// \brief When true, include the body of a tag definition. /// - /// This is used when the caller needs to print a tag definition in front - /// of the type, as in constructs like the following: + /// This is used to place the definition of a struct + /// in the middle of another declaration as with: /// /// \code /// typedef struct { int x, y; } Point; /// \endcode - bool SuppressTag : 1; + bool IncludeTagDefinition : 1; /// \brief Suppresses printing of scope specifiers. bool SuppressScope : 1; @@ -136,11 +151,28 @@ struct PrintingPolicy { /// \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). + + /// When true, suppresses printing template arguments in names of C++ + /// constructors. + unsigned SuppressTemplateArgsInCXXConstructors : 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; + /// \brief Whether we can use 'restrict' rather than '__restrict'. + unsigned Restrict : 1; + + /// \brief Whether we can use 'alignof' rather than '__alignof'. + unsigned Alignof : 1; + + /// \brief Whether we can use '_Alignof' rather than '__alignof'. + unsigned UnderscoreAlignof : 1; + + /// \brief Whether we should use '(void)' rather than '()' for a function + /// prototype with zero parameters. + unsigned UseVoidForZeroParams : 1; + /// \brief Provide a 'terse' output. /// /// For example, in this mode we don't print function bodies, class members, diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 667f23520eb78..7a39c3b2539df 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -71,10 +71,7 @@ private: CharUnits RequiredAlignment; /// FieldOffsets - Array of field offsets in bits. - uint64_t *FieldOffsets; - - // FieldCount - Number of fields. - unsigned FieldCount; + ASTVector FieldOffsets; /// CXXRecordLayoutInfo - Contains C++ specific layout information. struct CXXRecordLayoutInfo { @@ -104,10 +101,10 @@ private: /// a primary base class. bool HasExtendableVFPtr : 1; - /// HasZeroSizedSubObject - True if this class contains a zero sized member - /// or base or a base with a zero sized member or base. Only used for - /// MS-ABI. - bool HasZeroSizedSubObject : 1; + /// EndsWithZeroSizedObject - True if this class contains a zero sized + /// member or base or a base with a zero sized member or base. + /// Only used for MS-ABI. + bool EndsWithZeroSizedObject : 1; /// \brief True if this class is zero sized or first base is zero sized or /// has this property. Only used for MS-ABI. @@ -136,9 +133,8 @@ private: friend class ASTContext; ASTRecordLayout(const ASTContext &Ctx, CharUnits size, CharUnits alignment, - CharUnits requiredAlignment, - CharUnits datasize, const uint64_t *fieldoffsets, - unsigned fieldcount); + CharUnits requiredAlignment, CharUnits datasize, + ArrayRef fieldoffsets); // Constructor for C++ records. typedef CXXRecordLayoutInfo::BaseOffsetsMapTy BaseOffsetsMapTy; @@ -148,13 +144,13 @@ private: bool hasOwnVFPtr, bool hasExtendableVFPtr, CharUnits vbptroffset, CharUnits datasize, - const uint64_t *fieldoffsets, unsigned fieldcount, + ArrayRef fieldoffsets, CharUnits nonvirtualsize, CharUnits nonvirtualalignment, CharUnits SizeOfLargestEmptySubobject, const CXXRecordDecl *PrimaryBase, bool IsPrimaryBaseVirtual, const CXXRecordDecl *BaseSharingVBPtr, - bool HasZeroSizedSubObject, + bool EndsWithZeroSizedObject, bool LeadsWithZeroSizedBase, const BaseOffsetsMapTy& BaseOffsets, const VBaseOffsetsMapTy& VBaseOffsets); @@ -174,12 +170,11 @@ public: CharUnits getSize() const { return Size; } /// getFieldCount - Get the number of fields in the layout. - unsigned getFieldCount() const { return FieldCount; } + unsigned getFieldCount() const { return FieldOffsets.size(); } /// getFieldOffset - Get the offset of the given field index, in /// bits. uint64_t getFieldOffset(unsigned FieldNo) const { - assert (FieldNo < FieldCount && "Invalid Field No"); return FieldOffsets[FieldNo]; } @@ -283,8 +278,8 @@ public: return RequiredAlignment; } - bool hasZeroSizedSubObject() const { - return CXXInfo && CXXInfo->HasZeroSizedSubObject; + bool endsWithZeroSizedObject() const { + return CXXInfo && CXXInfo->EndsWithZeroSizedObject; } bool leadsWithZeroSizedBase() const { diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index 0c25a45c1cec3..f918b830d4212 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -72,8 +72,8 @@ namespace clang { return false; \ } while (0) -/// \brief A class that does preorder depth-first traversal on the -/// entire Clang AST and visits each node. +/// \brief A class that does preordor or postorder +/// depth-first traversal on the entire Clang AST and visits each node. /// /// This class performs three distinct tasks: /// 1. traverse the AST (i.e. go to each node); @@ -133,13 +133,19 @@ namespace clang { /// to return true, in which case all known implicit and explicit /// instantiations will be visited at the same time as the pattern /// from which they were produced. +/// +/// By default, this visitor preorder traverses the AST. If postorder traversal +/// is needed, the \c shouldTraversePostOrder method needs to be overriden +/// to return \c true. template class RecursiveASTVisitor { public: /// A queue used for performing data recursion over statements. /// Parameters involving this type are used to implement data /// recursion over Stmts and Exprs within this class, and should /// typically not be explicitly specified by derived classes. - typedef SmallVectorImpl DataRecursionQueue; + /// The bool bit indicates whether the statement has been traversed or not. + typedef SmallVectorImpl> + DataRecursionQueue; /// \brief Return a reference to the derived class. Derived &getDerived() { return *static_cast(this); } @@ -156,6 +162,9 @@ public: /// code, e.g., implicit constructors and destructors. bool shouldVisitImplicitCode() const { return false; } + /// \brief Return whether this visitor should traverse post-order. + bool shouldTraversePostOrder() const { return false; } + /// \brief Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. /// @@ -163,6 +172,18 @@ public: /// otherwise (including when the argument is nullptr). bool TraverseStmt(Stmt *S, DataRecursionQueue *Queue = nullptr); + /// Invoked before visiting a statement or expression via data recursion. + /// + /// \returns false to skip visiting the node, true otherwise. + bool dataTraverseStmtPre(Stmt *S) { return true; } + + /// Invoked after visiting a statement or expression via data recursion. + /// This is not invoked if the previously invoked \c dataTraverseStmtPre + /// returned false. + /// + /// \returns false if the visitation was terminated early, true otherwise. + bool dataTraverseStmtPost(Stmt *S) { return true; } + /// \brief Recursively visit a type, by dispatching to /// Traverse*Type() based on the argument's getTypeClass() property. /// @@ -335,7 +356,7 @@ public: bool TraverseUnary##NAME(UnaryOperator *S, \ DataRecursionQueue *Queue = nullptr) { \ TRY_TO(WalkUpFromUnary##NAME(S)); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getSubExpr()); \ return true; \ } \ bool WalkUpFromUnary##NAME(UnaryOperator *S) { \ @@ -353,9 +374,10 @@ public: // (they're all opcodes in BinaryOperator) but do have visitors. #define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \ bool TraverseBin##NAME(BINOP_TYPE *S, DataRecursionQueue *Queue = nullptr) { \ - TRY_TO(WalkUpFromBin##NAME(S)); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \ + if (!getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFromBin##NAME(S)); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getLHS()); \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRHS()); \ return true; \ } \ bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \ @@ -480,8 +502,12 @@ private: #include "clang/Basic/OpenMPKinds.def" /// \brief Process clauses with list of variables. template bool VisitOMPClauseList(T *Node); + /// Process clauses with pre-initis. + bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node); + bool VisitOMPClauseWithPostUpdate(OMPClauseWithPostUpdate *Node); bool dataTraverseNode(Stmt *S, DataRecursionQueue *Queue); + bool PostVisitStmt(Stmt *S); }; template @@ -539,6 +565,24 @@ bool RecursiveASTVisitor::dataTraverseNode(Stmt *S, #undef DISPATCH_STMT + +template +bool RecursiveASTVisitor::PostVisitStmt(Stmt *S) { + switch (S->getStmtClass()) { + case Stmt::NoStmtClass: + break; +#define ABSTRACT_STMT(STMT) +#define STMT(CLASS, PARENT) \ + case Stmt::CLASS##Class: \ + TRY_TO(WalkUpFrom##CLASS(static_cast(S))); break; +#include "clang/AST/StmtNodes.inc" + } + + return true; +} + +#undef DISPATCH_STMT + template bool RecursiveASTVisitor::TraverseStmt(Stmt *S, DataRecursionQueue *Queue) { @@ -546,20 +590,35 @@ bool RecursiveASTVisitor::TraverseStmt(Stmt *S, return true; if (Queue) { - Queue->push_back(S); + Queue->push_back({S, false}); return true; } - SmallVector LocalQueue; - LocalQueue.push_back(S); + SmallVector, 8> LocalQueue; + LocalQueue.push_back({S, false}); while (!LocalQueue.empty()) { - Stmt *CurrS = LocalQueue.pop_back_val(); + auto &CurrSAndVisited = LocalQueue.back(); + Stmt *CurrS = CurrSAndVisited.getPointer(); + bool Visited = CurrSAndVisited.getInt(); + if (Visited) { + LocalQueue.pop_back(); + TRY_TO(dataTraverseStmtPost(CurrS)); + if (getDerived().shouldTraversePostOrder()) { + TRY_TO(PostVisitStmt(CurrS)); + } + continue; + } - size_t N = LocalQueue.size(); - TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); - // Process new children in the order they were added. - std::reverse(LocalQueue.begin() + N, LocalQueue.end()); + if (getDerived().dataTraverseStmtPre(CurrS)) { + CurrSAndVisited.setInt(true); + size_t N = LocalQueue.size(); + TRY_TO(dataTraverseNode(CurrS, &LocalQueue)); + // Process new children in the order they were added. + std::reverse(LocalQueue.begin() + N, LocalQueue.end()); + } else { + LocalQueue.pop_back(); + } } return true; @@ -809,6 +868,17 @@ bool RecursiveASTVisitor::TraverseConstructorInitializer( if (Init->isWritten() || getDerived().shouldVisitImplicitCode()) TRY_TO(TraverseStmt(Init->getInit())); + + if (getDerived().shouldVisitImplicitCode()) + // The braces for this one-line loop are required for MSVC2013. It + // refuses to compile + // for (int i : int_vec) + // do {} while(false); + // without braces on the for loop. + for (VarDecl *VD : Init->getArrayIndices()) { + TRY_TO(TraverseDecl(VD)); + } + return true; } @@ -834,8 +904,11 @@ bool RecursiveASTVisitor::TraverseLambdaBody( #define DEF_TRAVERSE_TYPE(TYPE, CODE) \ template \ bool RecursiveASTVisitor::Traverse##TYPE(TYPE *T) { \ - TRY_TO(WalkUpFrom##TYPE(T)); \ + if (!getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFrom##TYPE(T)); \ { CODE; } \ + if (getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFrom##TYPE(T)); \ return true; \ } @@ -1238,10 +1311,16 @@ bool RecursiveASTVisitor::TraverseDeclContextHelper(DeclContext *DC) { #define DEF_TRAVERSE_DECL(DECL, CODE) \ template \ bool RecursiveASTVisitor::Traverse##DECL(DECL *D) { \ - TRY_TO(WalkUpFrom##DECL(D)); \ + bool ShouldVisitChildren = true; \ + bool ReturnValue = true; \ + if (!getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFrom##DECL(D)); \ { CODE; } \ - TRY_TO(TraverseDeclContextHelper(dyn_cast(D))); \ - return true; \ + if (ReturnValue && ShouldVisitChildren) \ + TRY_TO(TraverseDeclContextHelper(dyn_cast(D))); \ + if (ReturnValue && getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFrom##DECL(D)); \ + return ReturnValue; \ } DEF_TRAVERSE_DECL(AccessSpecDecl, {}) @@ -1255,18 +1334,12 @@ DEF_TRAVERSE_DECL(BlockDecl, { TRY_TO(TraverseStmt(I.getCopyExpr())); } } - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; + ShouldVisitChildren = false; }) DEF_TRAVERSE_DECL(CapturedDecl, { TRY_TO(TraverseStmt(D->getBody())); - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; + ShouldVisitChildren = false; }) DEF_TRAVERSE_DECL(EmptyDecl, {}) @@ -1325,6 +1398,10 @@ DEF_TRAVERSE_DECL( // D->getAnonymousNamespace(). }) +DEF_TRAVERSE_DECL(PragmaCommentDecl, {}) + +DEF_TRAVERSE_DECL(PragmaDetectMismatchDecl, {}) + DEF_TRAVERSE_DECL(ExternCContextDecl, {}) DEF_TRAVERSE_DECL(NamespaceAliasDecl, { @@ -1332,11 +1409,7 @@ DEF_TRAVERSE_DECL(NamespaceAliasDecl, { // We shouldn't traverse an aliased namespace, since it will be // defined (and, therefore, traversed) somewhere else. - // - // This return statement makes sure the traversal of nodes in - // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro) - // is skipped - don't remove it. - return true; + ShouldVisitChildren = false; }) DEF_TRAVERSE_DECL(LabelDecl, {// There is no code in a LabelDecl. @@ -1385,14 +1458,13 @@ DEF_TRAVERSE_DECL(ObjCMethodDecl, { if (D->getReturnTypeSourceInfo()) { TRY_TO(TraverseTypeLoc(D->getReturnTypeSourceInfo()->getTypeLoc())); } - for (ObjCMethodDecl::param_iterator I = D->param_begin(), E = D->param_end(); - I != E; ++I) { - TRY_TO(TraverseDecl(*I)); + for (ParmVarDecl *Parameter : D->parameters()) { + TRY_TO(TraverseDecl(Parameter)); } if (D->isThisDeclarationADefinition()) { TRY_TO(TraverseStmt(D->getBody())); } - return true; + ShouldVisitChildren = false; }) DEF_TRAVERSE_DECL(ObjCTypeParamDecl, { @@ -1409,7 +1481,7 @@ DEF_TRAVERSE_DECL(ObjCPropertyDecl, { TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc())); else TRY_TO(TraverseType(D->getType())); - return true; + ShouldVisitChildren = false; }) DEF_TRAVERSE_DECL(UsingDecl, { @@ -1423,12 +1495,24 @@ DEF_TRAVERSE_DECL(UsingDirectiveDecl, { DEF_TRAVERSE_DECL(UsingShadowDecl, {}) +DEF_TRAVERSE_DECL(ConstructorUsingShadowDecl, {}) + DEF_TRAVERSE_DECL(OMPThreadPrivateDecl, { for (auto *I : D->varlists()) { TRY_TO(TraverseStmt(I)); } }) +DEF_TRAVERSE_DECL(OMPDeclareReductionDecl, { + TRY_TO(TraverseStmt(D->getCombiner())); + if (auto *Initializer = D->getInitializer()) + TRY_TO(TraverseStmt(Initializer)); + TRY_TO(TraverseType(D->getType())); + return true; +}) + +DEF_TRAVERSE_DECL(OMPCapturedExprDecl, { TRY_TO(TraverseVarHelper(D)); }) + // A helper method for TemplateDecl's children. template bool RecursiveASTVisitor::TraverseTemplateParameterListHelper( @@ -1778,10 +1862,9 @@ bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { // 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)); + for (ParmVarDecl *Parameter : D->parameters()) { + TRY_TO(TraverseDecl(Parameter)); + } } if (CXXConstructorDecl *Ctor = dyn_cast(D)) { @@ -1800,19 +1883,22 @@ bool RecursiveASTVisitor::TraverseFunctionHelper(FunctionDecl *D) { DEF_TRAVERSE_DECL(FunctionDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); + ShouldVisitChildren = false; + ReturnValue = TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXMethodDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); + ShouldVisitChildren = false; + ReturnValue = TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXConstructorDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); + ShouldVisitChildren = false; + ReturnValue = TraverseFunctionHelper(D); }) // CXXConversionDecl is the declaration of a type conversion operator. @@ -1820,13 +1906,15 @@ DEF_TRAVERSE_DECL(CXXConstructorDecl, { DEF_TRAVERSE_DECL(CXXConversionDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); + ShouldVisitChildren = false; + ReturnValue = TraverseFunctionHelper(D); }) DEF_TRAVERSE_DECL(CXXDestructorDecl, { // We skip decls_begin/decls_end, which are already covered by // TraverseFunctionHelper(). - return TraverseFunctionHelper(D); + ShouldVisitChildren = false; + ReturnValue = TraverseFunctionHelper(D); }) template @@ -1878,12 +1966,19 @@ DEF_TRAVERSE_DECL(ParmVarDecl, { template \ bool RecursiveASTVisitor::Traverse##STMT( \ STMT *S, DataRecursionQueue *Queue) { \ - TRY_TO(WalkUpFrom##STMT(S)); \ + bool ShouldVisitChildren = true; \ + bool ReturnValue = true; \ + if (!getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFrom##STMT(S)); \ { CODE; } \ - for (Stmt *SubStmt : S->children()) { \ - TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ + if (ShouldVisitChildren) { \ + for (Stmt *SubStmt : S->children()) { \ + TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); \ + } \ } \ - return true; \ + if (!Queue && ReturnValue && getDerived().shouldTraversePostOrder()) \ + TRY_TO(WalkUpFrom##STMT(S)); \ + return ReturnValue; \ } DEF_TRAVERSE_STMT(GCCAsmStmt, { @@ -1920,7 +2015,7 @@ DEF_TRAVERSE_STMT(DeclStmt, { // initializer]'. The decls above already traverse over the // initializers, so we don't have to do it again (which // children() would do). - return true; + ShouldVisitChildren = false; }) // These non-expr stmts (most of them), do not need any action except @@ -1952,7 +2047,7 @@ DEF_TRAVERSE_STMT(CXXForRangeStmt, { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getRangeInit()); TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); // Visit everything else only if shouldVisitImplicitCode(). - return true; + ShouldVisitChildren = false; } }) DEF_TRAVERSE_STMT(MSDependentExistsStmt, { @@ -2029,7 +2124,11 @@ template bool RecursiveASTVisitor::TraverseSynOrSemInitListExpr( InitListExpr *S, DataRecursionQueue *Queue) { if (S) { - TRY_TO(WalkUpFromInitListExpr(S)); + // Skip this if we traverse postorder. We will visit it later + // in PostVisitStmt. + if (!getDerived().shouldTraversePostOrder()) + TRY_TO(WalkUpFromInitListExpr(S)); + // All we need are the default actions. FIXME: use a helper function. for (Stmt *SubStmt : S->children()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(SubStmt); @@ -2049,7 +2148,7 @@ DEF_TRAVERSE_STMT(InitListExpr, { S->isSemanticForm() ? S->getSyntacticForm() : S, Queue)); TRY_TO(TraverseSynOrSemInitListExpr( S->isSemanticForm() ? S : S->getSemanticForm(), Queue)); - return true; + ShouldVisitChildren = false; }) // GenericSelectionExpr is a special case because the types and expressions @@ -2062,7 +2161,7 @@ DEF_TRAVERSE_STMT(GenericSelectionExpr, { TRY_TO(TraverseTypeLoc(TS->getTypeLoc())); TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getAssocExpr(i)); } - return true; + ShouldVisitChildren = false; }) // PseudoObjectExpr is a special case because of the weirdness with @@ -2077,7 +2176,7 @@ DEF_TRAVERSE_STMT(PseudoObjectExpr, { sub = OVE->getSourceExpr(); TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(sub); } - return true; + ShouldVisitChildren = false; }) DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, { @@ -2181,7 +2280,8 @@ DEF_TRAVERSE_STMT(LambdaExpr, { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(NE); } - return TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue); + ReturnValue = TRAVERSE_STMT_BASE(LambdaBody, LambdaExpr, S, Queue); + ShouldVisitChildren = false; }) DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, { @@ -2214,6 +2314,7 @@ DEF_TRAVERSE_STMT(CXXDefaultArgExpr, {}) DEF_TRAVERSE_STMT(CXXDefaultInitExpr, {}) DEF_TRAVERSE_STMT(CXXDeleteExpr, {}) DEF_TRAVERSE_STMT(ExprWithCleanups, {}) +DEF_TRAVERSE_STMT(CXXInheritedCtorInitExpr, {}) DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, {}) DEF_TRAVERSE_STMT(CXXStdInitializerListExpr, {}) DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, { @@ -2251,6 +2352,7 @@ DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, {}) DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, { TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc())); }) +DEF_TRAVERSE_STMT(ObjCAvailabilityCheckExpr, {}) DEF_TRAVERSE_STMT(ParenExpr, {}) DEF_TRAVERSE_STMT(ParenListExpr, {}) DEF_TRAVERSE_STMT(PredefinedExpr, {}) @@ -2307,25 +2409,25 @@ DEF_TRAVERSE_STMT(AtomicExpr, {}) DEF_TRAVERSE_STMT(CoroutineBodyStmt, { if (!getDerived().shouldVisitImplicitCode()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getBody()); - return true; + ShouldVisitChildren = false; } }) DEF_TRAVERSE_STMT(CoreturnStmt, { if (!getDerived().shouldVisitImplicitCode()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); - return true; + ShouldVisitChildren = false; } }) DEF_TRAVERSE_STMT(CoawaitExpr, { if (!getDerived().shouldVisitImplicitCode()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); - return true; + ShouldVisitChildren = false; } }) DEF_TRAVERSE_STMT(CoyieldExpr, { if (!getDerived().shouldVisitImplicitCode()) { TRY_TO_TRAVERSE_OR_ENQUEUE_STMT(S->getOperand()); - return true; + ShouldVisitChildren = false; } }) @@ -2433,9 +2535,24 @@ DEF_TRAVERSE_STMT(OMPTargetDirective, DEF_TRAVERSE_STMT(OMPTargetDataDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetEnterDataDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetExitDataDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetParallelDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetParallelForDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPTeamsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPTargetUpdateDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPTaskLoopDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2445,6 +2562,18 @@ DEF_TRAVERSE_STMT(OMPTaskLoopSimdDirective, DEF_TRAVERSE_STMT(OMPDistributeDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPDistributeParallelForDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPDistributeParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPDistributeSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { @@ -2457,12 +2586,28 @@ bool RecursiveASTVisitor::TraverseOMPClause(OMPClause *C) { break; #include "clang/Basic/OpenMPKinds.def" case OMPC_threadprivate: + case OMPC_uniform: case OMPC_unknown: break; } return true; } +template +bool RecursiveASTVisitor::VisitOMPClauseWithPreInit( + OMPClauseWithPreInit *Node) { + TRY_TO(TraverseStmt(Node->getPreInitStmt())); + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPClauseWithPostUpdate( + OMPClauseWithPostUpdate *Node) { + TRY_TO(VisitOMPClauseWithPreInit(Node)); + TRY_TO(TraverseStmt(Node->getPostUpdateExpr())); + return true; +} + template bool RecursiveASTVisitor::VisitOMPIfClause(OMPIfClause *C) { TRY_TO(TraverseStmt(C->getCondition())); @@ -2514,8 +2659,8 @@ bool RecursiveASTVisitor::VisitOMPProcBindClause(OMPProcBindClause *) { template bool RecursiveASTVisitor::VisitOMPScheduleClause(OMPScheduleClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); TRY_TO(TraverseStmt(C->getChunkSize())); - TRY_TO(TraverseStmt(C->getHelperChunkSize())); return true; } @@ -2603,6 +2748,7 @@ template bool RecursiveASTVisitor::VisitOMPFirstprivateClause( OMPFirstprivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + TRY_TO(VisitOMPClauseWithPreInit(C)); for (auto *E : C->private_copies()) { TRY_TO(TraverseStmt(E)); } @@ -2616,6 +2762,7 @@ template bool RecursiveASTVisitor::VisitOMPLastprivateClause( OMPLastprivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + TRY_TO(VisitOMPClauseWithPostUpdate(C)); for (auto *E : C->private_copies()) { TRY_TO(TraverseStmt(E)); } @@ -2642,6 +2789,7 @@ bool RecursiveASTVisitor::VisitOMPLinearClause(OMPLinearClause *C) { TRY_TO(TraverseStmt(C->getStep())); TRY_TO(TraverseStmt(C->getCalcStep())); TRY_TO(VisitOMPClauseList(C)); + TRY_TO(VisitOMPClauseWithPostUpdate(C)); for (auto *E : C->privates()) { TRY_TO(TraverseStmt(E)); } @@ -2701,6 +2849,7 @@ RecursiveASTVisitor::VisitOMPReductionClause(OMPReductionClause *C) { TRY_TO(TraverseNestedNameSpecifierLoc(C->getQualifierLoc())); TRY_TO(TraverseDeclarationNameInfo(C->getNameInfo())); TRY_TO(VisitOMPClauseList(C)); + TRY_TO(VisitOMPClauseWithPostUpdate(C)); for (auto *E : C->privates()) { TRY_TO(TraverseStmt(E)); } @@ -2781,6 +2930,46 @@ bool RecursiveASTVisitor::VisitOMPHintClause(OMPHintClause *C) { return true; } +template +bool RecursiveASTVisitor::VisitOMPDistScheduleClause( + OMPDistScheduleClause *C) { + TRY_TO(VisitOMPClauseWithPreInit(C)); + TRY_TO(TraverseStmt(C->getChunkSize())); + return true; +} + +template +bool +RecursiveASTVisitor::VisitOMPDefaultmapClause(OMPDefaultmapClause *C) { + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPToClause(OMPToClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPFromClause(OMPFromClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPUseDevicePtrClause( + OMPUseDevicePtrClause *C) { + TRY_TO(VisitOMPClauseList(C)); + return true; +} + +template +bool RecursiveASTVisitor::VisitOMPIsDevicePtrClause( + OMPIsDevicePtrClause *C) { + TRY_TO(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/Stmt.h b/include/clang/AST/Stmt.h index d3950e92cf0d7..96847cf88f969 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -93,6 +93,13 @@ protected: unsigned NumStmts : 32 - NumStmtBits; }; + class IfStmtBitfields { + friend class IfStmt; + unsigned : NumStmtBits; + + unsigned IsConstexpr : 1; + }; + class ExprBitfields { friend class Expr; friend class DeclRefExpr; // computeDependence @@ -115,6 +122,7 @@ protected: friend class OverloadExpr; // ctor friend class PseudoObjectExpr; // ctor friend class AtomicExpr; // ctor + friend class OpaqueValueExpr; // ctor unsigned : NumStmtBits; unsigned ValueKind : 2; @@ -191,7 +199,10 @@ protected: unsigned : NumExprBits; - unsigned NumObjects : 32 - NumExprBits; + // When false, it must not have side effects. + unsigned CleanupsHaveSideEffects : 1; + + unsigned NumObjects : 32 - 1 - NumExprBits; }; class PseudoObjectExprBitfields { @@ -244,6 +255,7 @@ protected: union { StmtBitfields StmtBits; CompoundStmtBitfields CompoundStmtBits; + IfStmtBitfields IfStmtBits; ExprBitfields ExprBits; CharacterLiteralBitfields CharacterLiteralBits; FloatingLiteralBitfields FloatingLiteralBits; @@ -867,14 +879,15 @@ public: /// IfStmt - This represents an if/then/else. /// class IfStmt : public Stmt { - enum { VAR, COND, THEN, ELSE, END_EXPR }; + enum { INIT, VAR, COND, THEN, ELSE, END_EXPR }; Stmt* SubExprs[END_EXPR]; SourceLocation IfLoc; SourceLocation ElseLoc; public: - IfStmt(const ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, + IfStmt(const ASTContext &C, SourceLocation IL, + bool IsConstexpr, Stmt *init, VarDecl *var, Expr *cond, Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = nullptr); @@ -898,6 +911,9 @@ public: return reinterpret_cast(SubExprs[VAR]); } + Stmt *getInit() { return SubExprs[INIT]; } + const Stmt *getInit() const { return SubExprs[INIT]; } + void setInit(Stmt *S) { SubExprs[INIT] = S; } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } const Stmt *getThen() const { return SubExprs[THEN]; } @@ -914,6 +930,9 @@ public: SourceLocation getElseLoc() const { return ElseLoc; } void setElseLoc(SourceLocation L) { ElseLoc = L; } + bool isConstexpr() const { return IfStmtBits.IsConstexpr; } + void setConstexpr(bool C) { IfStmtBits.IsConstexpr = C; } + SourceLocation getLocStart() const LLVM_READONLY { return IfLoc; } SourceLocation getLocEnd() const LLVM_READONLY { if (SubExprs[ELSE]) @@ -937,7 +956,7 @@ public: /// class SwitchStmt : public Stmt { SourceLocation SwitchLoc; - enum { VAR, COND, BODY, END_EXPR }; + enum { INIT, VAR, COND, BODY, END_EXPR }; Stmt* SubExprs[END_EXPR]; // This points to a linked list of case and default statements and, if the // SwitchStmt is a switch on an enum value, records whether all the enum @@ -946,7 +965,7 @@ class SwitchStmt : public Stmt { llvm::PointerIntPair FirstCase; public: - SwitchStmt(const ASTContext &C, VarDecl *Var, Expr *cond); + SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond); /// \brief Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) { } @@ -969,6 +988,9 @@ public: return reinterpret_cast(SubExprs[VAR]); } + Stmt *getInit() { return SubExprs[INIT]; } + const Stmt *getInit() const { return SubExprs[INIT]; } + void setInit(Stmt *S) { SubExprs[INIT] = S; } const Expr *getCond() const { return reinterpret_cast(SubExprs[COND]);} const Stmt *getBody() const { return SubExprs[BODY]; } const SwitchCase *getSwitchCaseList() const { return FirstCase.getPointer(); } diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 1ca73e207e4c5..1d29c228a4b3c 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -127,7 +127,7 @@ public: /// can be extracted using getLoopVariable and getRangeInit. class CXXForRangeStmt : public Stmt { SourceLocation ForLoc; - enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END }; + enum { RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END }; // SubExprs[RANGE] is an expression or declstmt. // SubExprs[COND] and SubExprs[INC] are expressions. Stmt *SubExprs[END]; @@ -137,7 +137,7 @@ class CXXForRangeStmt : public Stmt { friend class ASTStmtReader; public: - CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, + CXXForRangeStmt(DeclStmt *Range, DeclStmt *Begin, DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, SourceLocation FL, SourceLocation CAL, SourceLocation CL, SourceLocation RPL); @@ -152,9 +152,10 @@ public: DeclStmt *getRangeStmt() { return cast(SubExprs[RANGE]); } - DeclStmt *getBeginEndStmt() { - return cast_or_null(SubExprs[BEGINEND]); + DeclStmt *getBeginStmt() { + return cast_or_null(SubExprs[BEGINSTMT]); } + DeclStmt *getEndStmt() { return cast_or_null(SubExprs[ENDSTMT]); } Expr *getCond() { return cast_or_null(SubExprs[COND]); } Expr *getInc() { return cast_or_null(SubExprs[INC]); } DeclStmt *getLoopVarStmt() { return cast(SubExprs[LOOPVAR]); } @@ -163,8 +164,11 @@ public: const DeclStmt *getRangeStmt() const { return cast(SubExprs[RANGE]); } - const DeclStmt *getBeginEndStmt() const { - return cast_or_null(SubExprs[BEGINEND]); + const DeclStmt *getBeginStmt() const { + return cast_or_null(SubExprs[BEGINSTMT]); + } + const DeclStmt *getEndStmt() const { + return cast_or_null(SubExprs[ENDSTMT]); } const Expr *getCond() const { return cast_or_null(SubExprs[COND]); @@ -179,7 +183,8 @@ public: void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast(E); } void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } - void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } + void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; } + void setEndStmt(Stmt *S) { SubExprs[ENDSTMT] = S; } void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast(E); } void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast(E); } void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 68fe3ef697bc6..5260b6985bf58 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -326,7 +326,7 @@ public: Expr *getThrowExpr() { return reinterpret_cast(Throw); } void setThrowExpr(Stmt *S) { Throw = S; } - SourceLocation getThrowLoc() { return AtThrowLoc; } + SourceLocation getThrowLoc() const LLVM_READONLY { return AtThrowLoc; } void setThrowLoc(SourceLocation Loc) { AtThrowLoc = Loc; } SourceLocation getLocStart() const LLVM_READONLY { return AtThrowLoc; } diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 1ba859c0b8467..1e357263461ed 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -70,8 +70,7 @@ protected: : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)), EndLoc(std::move(EndLoc)), NumClauses(NumClauses), NumChildren(NumChildren), - ClausesOffset(llvm::RoundUpToAlignment(sizeof(T), - llvm::alignOf())) {} + ClausesOffset(llvm::alignTo(sizeof(T), llvm::alignOf())) {} /// \brief Sets the list of variables for this clause. /// @@ -300,9 +299,11 @@ class OMPLoopDirective : public OMPExecutableDirective { /// This enumeration contains offsets to all the pointers to children /// expressions stored in OMPLoopDirective. /// The first 9 children are nesessary for all the loop directives, and - /// the next 7 are specific to the worksharing ones. + /// the next 10 are specific to the worksharing ones. /// After the fixed children, three arrays of length CollapsedNum are /// allocated: loop counters, their updates and final values. + /// PrevLowerBound and PrevUpperBound are used to communicate blocking + /// information in composite constructs which require loop blocking /// enum { AssociatedStmtOffset = 0, @@ -313,21 +314,25 @@ class OMPLoopDirective : public OMPExecutableDirective { CondOffset = 5, InitOffset = 6, IncOffset = 7, + PreInitsOffset = 8, // The '...End' enumerators do not correspond to child expressions - they // specify the offset to the end (and start of the following counters/ // updates/finals arrays). - DefaultEnd = 8, + DefaultEnd = 9, // The following 7 exprs are used by worksharing loops only. - IsLastIterVariableOffset = 8, - LowerBoundVariableOffset = 9, - UpperBoundVariableOffset = 10, - StrideVariableOffset = 11, - EnsureUpperBoundOffset = 12, - NextLowerBoundOffset = 13, - NextUpperBoundOffset = 14, + IsLastIterVariableOffset = 9, + LowerBoundVariableOffset = 10, + UpperBoundVariableOffset = 11, + StrideVariableOffset = 12, + EnsureUpperBoundOffset = 13, + NextLowerBoundOffset = 14, + NextUpperBoundOffset = 15, + NumIterationsOffset = 16, + PrevLowerBoundVariableOffset = 17, + PrevUpperBoundVariableOffset = 18, // Offset to the end (and start of the following counters/updates/finals // arrays) for worksharing loop directives. - WorksharingEnd = 15, + WorksharingEnd = 19, }; /// \brief Get the counters storage. @@ -423,6 +428,9 @@ protected: } void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } + void setPreInits(Stmt *PreInits) { + *std::next(child_begin(), PreInitsOffset) = PreInits; + } void setIsLastIterVariable(Expr *IL) { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || isOpenMPTaskLoopDirective(getDirectiveKind()) || @@ -472,6 +480,27 @@ protected: "expected worksharing loop directive"); *std::next(child_begin(), NextUpperBoundOffset) = NUB; } + void setNumIterations(Expr *NI) { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + *std::next(child_begin(), NumIterationsOffset) = NI; + } + void setPrevLowerBoundVariable(Expr *PrevLB) { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + *std::next(child_begin(), PrevLowerBoundVariableOffset) = PrevLB; + } + void setPrevUpperBoundVariable(Expr *PrevUB) { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + *std::next(child_begin(), PrevUpperBoundVariableOffset) = PrevUB; + } void setCounters(ArrayRef A); void setPrivateCounters(ArrayRef A); void setInits(ArrayRef A); @@ -512,6 +541,12 @@ public: Expr *NLB; /// \brief Update of UpperBound for statically sheduled 'omp for' loops. Expr *NUB; + /// \brief PreviousLowerBound - local variable passed to runtime in the + /// enclosing schedule or null if that does not apply. + Expr *PrevLB; + /// \brief PreviousUpperBound - local variable passed to runtime in the + /// enclosing schedule or null if that does not apply. + Expr *PrevUB; /// \brief Counters Loop counters. SmallVector Counters; /// \brief PrivateCounters Loop counters. @@ -522,6 +557,8 @@ public: SmallVector Updates; /// \brief Final loop counter values for GodeGen. SmallVector Finals; + /// Init statement for all captured expressions. + Stmt *PreInits; /// \brief Check if all the expressions are built (does not check the /// worksharing ones). @@ -548,6 +585,9 @@ public: EUB = nullptr; NLB = nullptr; NUB = nullptr; + NumIterations = nullptr; + PrevLB = nullptr; + PrevUB = nullptr; Counters.resize(Size); PrivateCounters.resize(Size); Inits.resize(Size); @@ -560,6 +600,7 @@ public: Updates[i] = nullptr; Finals[i] = nullptr; } + PreInits = nullptr; } }; @@ -594,55 +635,90 @@ public: return const_cast( reinterpret_cast(*std::next(child_begin(), IncOffset))); } + const Stmt *getPreInits() const { + return *std::next(child_begin(), PreInitsOffset); + } + Stmt *getPreInits() { return *std::next(child_begin(), PreInitsOffset); } Expr *getIsLastIterVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), IsLastIterVariableOffset))); } Expr *getLowerBoundVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), LowerBoundVariableOffset))); } Expr *getUpperBoundVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), UpperBoundVariableOffset))); } Expr *getStrideVariable() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), StrideVariableOffset))); } Expr *getEnsureUpperBound() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), EnsureUpperBoundOffset))); } Expr *getNextLowerBound() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), NextLowerBoundOffset))); } Expr *getNextUpperBound() const { assert((isOpenMPWorksharingDirective(getDirectiveKind()) || - isOpenMPTaskLoopDirective(getDirectiveKind())) && + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && "expected worksharing loop directive"); return const_cast(reinterpret_cast( *std::next(child_begin(), NextUpperBoundOffset))); } + Expr *getNumIterations() const { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), NumIterationsOffset))); + } + Expr *getPrevLowerBoundVariable() const { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), PrevLowerBoundVariableOffset))); + } + Expr *getPrevUpperBoundVariable() const { + assert((isOpenMPWorksharingDirective(getDirectiveKind()) || + isOpenMPTaskLoopDirective(getDirectiveKind()) || + isOpenMPDistributeDirective(getDirectiveKind())) && + "expected worksharing loop directive"); + return const_cast(reinterpret_cast( + *std::next(child_begin(), PrevUpperBoundVariableOffset))); + } const Stmt *getBody() const { // This relies on the loop form is already checked by Sema. Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); @@ -692,7 +768,12 @@ public: T->getStmtClass() == OMPParallelForSimdDirectiveClass || T->getStmtClass() == OMPTaskLoopDirectiveClass || T->getStmtClass() == OMPTaskLoopSimdDirectiveClass || - T->getStmtClass() == OMPDistributeDirectiveClass; + T->getStmtClass() == OMPDistributeDirectiveClass || + T->getStmtClass() == OMPTargetParallelForDirectiveClass || + T->getStmtClass() == OMPDistributeParallelForDirectiveClass || + T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass || + T->getStmtClass() == OMPDistributeSimdDirectiveClass || + T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass; } }; @@ -2039,6 +2120,264 @@ public: } }; +/// \brief This represents '#pragma omp target enter data' directive. +/// +/// \code +/// #pragma omp target enter data device(0) if(a) map(b[:]) +/// \endcode +/// In this example directive '#pragma omp target enter data' has clauses +/// 'device' with the value '0', 'if' with condition 'a' and 'map' with array +/// section 'b[:]'. +/// +class OMPTargetEnterDataDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param NumClauses The number of clauses. + /// + OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass, + OMPD_target_enter_data, StartLoc, EndLoc, + NumClauses, /*NumChildren=*/0) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetEnterDataDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetEnterDataDirectiveClass, + OMPD_target_enter_data, SourceLocation(), + SourceLocation(), NumClauses, + /*NumChildren=*/0) {} + +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. + /// + static OMPTargetEnterDataDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses); + + /// \brief Creates an empty directive with the place for \a N clauses. + /// + /// \param C AST context. + /// \param N The number of clauses. + /// + static OMPTargetEnterDataDirective *CreateEmpty(const ASTContext &C, + unsigned N, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetEnterDataDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp target exit data' directive. +/// +/// \code +/// #pragma omp target exit data device(0) if(a) map(b[:]) +/// \endcode +/// In this example directive '#pragma omp target exit data' has clauses +/// 'device' with the value '0', 'if' with condition 'a' and 'map' with array +/// section 'b[:]'. +/// +class OMPTargetExitDataDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param NumClauses The number of clauses. + /// + OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass, + OMPD_target_exit_data, StartLoc, EndLoc, + NumClauses, /*NumChildren=*/0) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetExitDataDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetExitDataDirectiveClass, + OMPD_target_exit_data, SourceLocation(), + SourceLocation(), NumClauses, + /*NumChildren=*/0) {} + +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. + /// + static OMPTargetExitDataDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses); + + /// \brief Creates an empty directive with the place for \a N clauses. + /// + /// \param C AST context. + /// \param N The number of clauses. + /// + static OMPTargetExitDataDirective *CreateEmpty(const ASTContext &C, + unsigned N, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetExitDataDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp target parallel' directive. +/// +/// \code +/// #pragma omp target parallel if(a) +/// \endcode +/// In this example directive '#pragma omp target parallel' has clause 'if' with +/// condition 'a'. +/// +class OMPTargetParallelDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param NumClauses Number of clauses. + /// + OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetParallelDirectiveClass, + OMPD_target_parallel, StartLoc, EndLoc, + NumClauses, /*NumChildren=*/1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetParallelDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetParallelDirectiveClass, + OMPD_target_parallel, SourceLocation(), + SourceLocation(), NumClauses, + /*NumChildren=*/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 OMPTargetParallelDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef Clauses, Stmt *AssociatedStmt); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPTargetParallelDirective * + CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetParallelDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp target parallel for' directive. +/// +/// \code +/// #pragma omp target parallel for private(a,b) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp target parallel for' has clauses +/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+' +/// and variables 'c' and 'd'. +/// +class OMPTargetParallelForDirective : public OMPLoopDirective { + friend class ASTStmtReader; + + /// \brief true if current region has inner cancel directive. + bool HasCancel; + + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPTargetParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPTargetParallelForDirectiveClass, + OMPD_target_parallel_for, StartLoc, EndLoc, + CollapsedNum, NumClauses), + HasCancel(false) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetParallelForDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPTargetParallelForDirectiveClass, + OMPD_target_parallel_for, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses), + HasCancel(false) {} + + /// \brief Set cancel state. + void setHasCancel(bool Has) { HasCancel = Has; } + +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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// \param HasCancel true if current directive has inner cancel directive. + /// + static OMPTargetParallelForDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTargetParallelForDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + /// \brief Return true if current directive has inner cancel directive. + bool hasCancel() const { return HasCancel; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetParallelForDirectiveClass; + } +}; + /// \brief This represents '#pragma omp teams' directive. /// /// \code @@ -2395,7 +2734,7 @@ public: /// \param Clauses List of clauses. /// \param AssociatedStmt Statement, associated with the directive. /// \param Exprs Helper expressions for CodeGen. - /// + /// static OMPDistributeDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef Clauses, @@ -2417,6 +2756,340 @@ public: } }; +/// \brief This represents '#pragma omp target update' directive. +/// +/// \code +/// #pragma omp target update to(a) from(b) device(1) +/// \endcode +/// In this example directive '#pragma omp target update' has clause 'to' with +/// argument 'a', clause 'from' with argument 'b' and clause 'device' with +/// argument '1'. +/// +class OMPTargetUpdateDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param NumClauses The number of clauses. + /// + OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass, + OMPD_target_update, StartLoc, EndLoc, NumClauses, + 0) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetUpdateDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetUpdateDirectiveClass, + OMPD_target_update, SourceLocation(), + SourceLocation(), NumClauses, 0) {} + +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. + /// + static OMPTargetUpdateDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef Clauses); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses The number of clauses. + /// + static OMPTargetUpdateDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetUpdateDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp distribute parallel for' composite +/// directive. +/// +/// \code +/// #pragma omp distribute parallel for private(a,b) +/// \endcode +/// In this example directive '#pragma omp distribute parallel for' has clause +/// 'private' with the variables 'a' and 'b' +/// +class OMPDistributeParallelForDirective : public OMPLoopDirective { + friend class ASTStmtReader; + + /// \brief Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPDistributeParallelForDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass, + OMPD_distribute_parallel_for, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPDistributeParallelForDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeParallelForDirectiveClass, + OMPD_distribute_parallel_for, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPDistributeParallelForDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// \brief Creates an empty directive with the place + /// for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPDistributeParallelForDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDistributeParallelForDirectiveClass; + } +}; + +/// This represents '#pragma omp distribute parallel for simd' composite +/// directive. +/// +/// \code +/// #pragma omp distribute parallel for simd private(x) +/// \endcode +/// In this example directive '#pragma omp distribute parallel for simd' has +/// clause 'private' with the variables 'x' +/// +class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPDistributeParallelForSimdDirective(SourceLocation StartLoc, + SourceLocation EndLoc, + unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeParallelForSimdDirectiveClass, + OMPD_distribute_parallel_for_simd, StartLoc, + EndLoc, CollapsedNum, NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeParallelForSimdDirectiveClass, + OMPD_distribute_parallel_for_simd, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} + +public: + /// 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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPDistributeParallelForSimdDirective *Create( + const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPDistributeParallelForSimdDirective *CreateEmpty( + const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass; + } +}; + +/// This represents '#pragma omp distribute simd' composite directive. +/// +/// \code +/// #pragma omp distribute simd private(x) +/// \endcode +/// In this example directive '#pragma omp distribute simd' has clause +/// 'private' with the variables 'x' +/// +class OMPDistributeSimdDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPDistributeSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeSimdDirectiveClass, + OMPD_distribute_simd, StartLoc, EndLoc, CollapsedNum, + NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPDistributeSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPDistributeSimdDirectiveClass, + OMPD_distribute_simd, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +public: + /// 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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPDistributeSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPDistributeSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPDistributeSimdDirectiveClass; + } +}; + +/// This represents '#pragma omp target parallel for simd' directive. +/// +/// \code +/// #pragma omp target parallel for simd private(a) map(b) safelen(c) +/// \endcode +/// In this example directive '#pragma omp target parallel for simd' has clauses +/// 'private' with the variable 'a', 'map' with the variable 'b' and 'safelen' +/// with the variable 'c'. +/// +class OMPTargetParallelForSimdDirective final : public OMPLoopDirective { + friend class ASTStmtReader; + + /// Build directive with the given start and end location. + /// + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + OMPTargetParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPTargetParallelForSimdDirectiveClass, + OMPD_target_parallel_for_simd, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} + + /// Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPTargetParallelForSimdDirectiveClass, + OMPD_target_parallel_for_simd, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} + +public: + /// 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 CollapsedNum Number of collapsed loops. + /// \param Clauses List of clauses. + /// \param AssociatedStmt Statement, associated with the directive. + /// \param Exprs Helper expressions for CodeGen. + /// + static OMPTargetParallelForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef Clauses, + Stmt *AssociatedStmt, const HelperExprs &Exprs); + + /// Creates an empty directive with the place for \a NumClauses clauses. + /// + /// \param C AST context. + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + static OMPTargetParallelForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index f87171a81d1d2..b9c2c08943e95 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -354,6 +354,12 @@ public: /// \brief Print this template argument to the given output stream. void print(const PrintingPolicy &Policy, raw_ostream &Out) const; + /// \brief Debugging aid that dumps the template argument. + void dump(raw_ostream &Out) const; + + /// \brief Debugging aid that dumps the template argument to standard error. + void dump() const; + /// \brief Used to insert TemplateArguments into FoldingSets. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; }; diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index 3e10d2fc4ad2a..bf4d008ee807a 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_AST_TEMPLATENAME_H #define LLVM_CLANG_AST_TEMPLATENAME_H +#include "clang/AST/NestedNameSpecifier.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/PointerUnion.h" diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index d63b2c43d5538..1067c086c764a 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -111,6 +111,7 @@ namespace clang { /// The collection of all-type qualifiers we support. /// Clang supports five independent qualifiers: /// * C99: const, volatile, and restrict +/// * MS: __unaligned /// * Embedded C (TR18037): address spaces /// * Objective C: the GC attributes (none, weak, or strong) class Qualifiers { @@ -152,8 +153,8 @@ public: enum { /// The maximum supported address space number. - /// 24 bits should be enough for anyone. - MaxAddressSpace = 0xffffffu, + /// 23 bits should be enough for anyone. + MaxAddressSpace = 0x7fffffu, /// The width of the "fast" qualifier mask. FastWidth = 3, @@ -214,6 +215,12 @@ public: return Qs; } + static Qualifiers fromCVRUMask(unsigned CVRU) { + Qualifiers Qs; + Qs.addCVRUQualifiers(CVRU); + return Qs; + } + // Deserialize qualifiers from an opaque representation. static Qualifiers fromOpaqueValue(unsigned opaque) { Qualifiers Qs; @@ -264,6 +271,17 @@ public: assert(!(mask & ~CVRMask) && "bitmask contains non-CVR bits"); Mask |= mask; } + void addCVRUQualifiers(unsigned mask) { + assert(!(mask & ~CVRMask & ~UMask) && "bitmask contains non-CVRU bits"); + Mask |= mask; + } + + bool hasUnaligned() const { return Mask & UMask; } + void setUnaligned(bool flag) { + Mask = (Mask & ~UMask) | (flag ? UMask : 0); + } + void removeUnaligned() { Mask &= ~UMask; } + void addUnaligned() { Mask |= UMask; } bool hasObjCGCAttr() const { return Mask & GCAttrMask; } GC getObjCGCAttr() const { return GC((Mask & GCAttrMask) >> GCAttrShift); } @@ -433,7 +451,9 @@ public: // ObjC lifetime qualifiers must match exactly. getObjCLifetime() == other.getObjCLifetime() && // CVR qualifiers may subset. - (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); + (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)) && + // U qualifier may superset. + (!other.hasUnaligned() || hasUnaligned()); } /// \brief Determines if these qualifiers compatibly include another set of @@ -501,16 +521,19 @@ public: private: - // bits: |0 1 2|3 .. 4|5 .. 7|8 ... 31| - // |C R V|GCAttr|Lifetime|AddressSpace| + // bits: |0 1 2|3|4 .. 5|6 .. 8|9 ... 31| + // |C R V|U|GCAttr|Lifetime|AddressSpace| uint32_t Mask; - static const uint32_t GCAttrMask = 0x18; - static const uint32_t GCAttrShift = 3; - static const uint32_t LifetimeMask = 0xE0; - static const uint32_t LifetimeShift = 5; - static const uint32_t AddressSpaceMask = ~(CVRMask|GCAttrMask|LifetimeMask); - static const uint32_t AddressSpaceShift = 8; + static const uint32_t UMask = 0x8; + static const uint32_t UShift = 3; + static const uint32_t GCAttrMask = 0x30; + static const uint32_t GCAttrShift = 4; + static const uint32_t LifetimeMask = 0x1C0; + static const uint32_t LifetimeShift = 6; + static const uint32_t AddressSpaceMask = + ~(CVRMask | UMask | GCAttrMask | LifetimeMask); + static const uint32_t AddressSpaceShift = 9; }; /// A std::pair-like structure for storing a qualified type split @@ -709,27 +732,27 @@ public: /// applied to this type. unsigned getCVRQualifiers() const; - bool isConstant(ASTContext& Ctx) const { + bool isConstant(const ASTContext& Ctx) const { return QualType::isConstant(*this, Ctx); } /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). - bool isPODType(ASTContext &Context) const; + bool isPODType(const ASTContext &Context) const; /// Return true if this is a POD type according to the rules of the C++98 /// standard, regardless of the current compilation's language. - bool isCXX98PODType(ASTContext &Context) const; + bool isCXX98PODType(const ASTContext &Context) const; /// Return true if this is a POD type according to the more relaxed rules /// of the C++11 standard, regardless of the current compilation's language. /// (C++0x [basic.types]p9) - bool isCXX11PODType(ASTContext &Context) const; + bool isCXX11PODType(const ASTContext &Context) const; /// Return true if this is a trivial type per (C++0x [basic.types]p9) - bool isTrivialType(ASTContext &Context) const; + bool isTrivialType(const ASTContext &Context) const; /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) - bool isTriviallyCopyableType(ASTContext &Context) const; + bool isTriviallyCopyableType(const ASTContext &Context) const; // Don't promise in the API that anything besides 'const' can be // easily added. @@ -909,16 +932,19 @@ public: std::string getAsString(const PrintingPolicy &Policy) const; void print(raw_ostream &OS, const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine()) const { - print(split(), OS, Policy, PlaceHolder); + const Twine &PlaceHolder = Twine(), + unsigned Indentation = 0) const { + print(split(), OS, Policy, PlaceHolder, Indentation); } static void print(SplitQualType split, raw_ostream &OS, - const PrintingPolicy &policy, const Twine &PlaceHolder) { - return print(split.Ty, split.Quals, OS, policy, PlaceHolder); + const PrintingPolicy &policy, const Twine &PlaceHolder, + unsigned Indentation = 0) { + return print(split.Ty, split.Quals, OS, policy, PlaceHolder, Indentation); } static void print(const Type *ty, Qualifiers qs, raw_ostream &OS, const PrintingPolicy &policy, - const Twine &PlaceHolder); + const Twine &PlaceHolder, + unsigned Indentation = 0); void getAsStringInternal(std::string &Str, const PrintingPolicy &Policy) const { @@ -936,21 +962,24 @@ public: const QualType &T; const PrintingPolicy &Policy; const Twine &PlaceHolder; + unsigned Indentation; public: StreamedQualTypeHelper(const QualType &T, const PrintingPolicy &Policy, - const Twine &PlaceHolder) - : T(T), Policy(Policy), PlaceHolder(PlaceHolder) { } + const Twine &PlaceHolder, unsigned Indentation) + : T(T), Policy(Policy), PlaceHolder(PlaceHolder), + Indentation(Indentation) { } friend raw_ostream &operator<<(raw_ostream &OS, const StreamedQualTypeHelper &SQT) { - SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder); + SQT.T.print(OS, SQT.Policy, SQT.PlaceHolder, SQT.Indentation); return OS; } }; StreamedQualTypeHelper stream(const PrintingPolicy &Policy, - const Twine &PlaceHolder = Twine()) const { - return StreamedQualTypeHelper(*this, Policy, PlaceHolder); + const Twine &PlaceHolder = Twine(), + unsigned Indentation = 0) const { + return StreamedQualTypeHelper(*this, Policy, PlaceHolder, Indentation); } void dump(const char *s) const; @@ -1061,11 +1090,14 @@ public: /// Strip Objective-C "__kindof" types from the given type. QualType stripObjCKindOfType(const ASTContext &ctx) const; + /// Remove all qualifiers including _Atomic. + QualType getAtomicUnqualifiedType() const; + private: // These methods are implemented in a separate translation unit; // "static"-ize them to avoid creating temporary QualTypes in the // caller. - static bool isConstant(QualType T, ASTContext& Ctx); + static bool isConstant(QualType T, const ASTContext& Ctx); static QualType getDesugaredType(QualType T, const ASTContext &Context); static SplitQualType getSplitDesugaredType(QualType T); static SplitQualType getSplitUnqualifiedTypeImpl(QualType type); @@ -1353,7 +1385,7 @@ protected: /// /// C++ 8.3.5p4: The return type, the parameter type list and the /// cv-qualifier-seq, [...], are part of the function type. - unsigned TypeQuals : 3; + unsigned TypeQuals : 4; /// \brief The ref-qualifier associated with a \c FunctionProtoType. /// @@ -1600,7 +1632,7 @@ public: bool isChar16Type() const; bool isChar32Type() const; bool isAnyCharacterType() const; - bool isIntegralType(ASTContext &Ctx) const; + bool isIntegralType(const ASTContext &Ctx) const; /// Determine whether this type is an integral or enumeration type. bool isIntegralOrEnumerationType() const; @@ -1699,18 +1731,9 @@ public: bool isNullPtrType() const; // C++0x nullptr_t bool isAtomicType() const; // C11 _Atomic() - bool isImage1dT() const; // OpenCL image1d_t - bool isImage1dArrayT() const; // OpenCL image1d_array_t - bool isImage1dBufferT() const; // OpenCL image1d_buffer_t - bool isImage2dT() const; // OpenCL image2d_t - bool isImage2dArrayT() const; // OpenCL image2d_array_t - bool isImage2dDepthT() const; // OpenCL image_2d_depth_t - bool isImage2dArrayDepthT() const; // OpenCL image_2d_array_depth_t - bool isImage2dMSAAT() const; // OpenCL image_2d_msaa_t - bool isImage2dArrayMSAAT() const; // OpenCL image_2d_array_msaa_t - bool isImage2dMSAATDepth() const; // OpenCL image_2d_msaa_depth_t - bool isImage2dArrayMSAATDepth() const; // OpenCL image_2d_array_msaa_depth_t - bool isImage3dT() const; // OpenCL image3d_t +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + bool is##Id##Type() const; +#include "clang/Basic/OpenCLImageTypes.def" bool isImageType() const; // Any OpenCL image type @@ -1875,6 +1898,11 @@ public: /// This should never be used when type qualifiers are meaningful. const Type *getArrayElementTypeNoTypeQual() const; + /// If this is a pointer type, return the pointee type. + /// If this is an array type, return the array element type. + /// This should never be used when type qualifiers are meaningful. + const Type *getPointeeOrArrayElementType() const; + /// If this is a pointer, ObjC object pointer, or block /// pointer, this returns the respective pointee. QualType getPointeeType() const; @@ -2011,6 +2039,10 @@ template <> inline const Class##Type *Type::castAs() const { \ class BuiltinType : public Type { public: enum Kind { +// OpenCL image types +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) Id, +#include "clang/Basic/OpenCLImageTypes.def" +// All other builtin types #define BUILTIN_TYPE(Id, SingletonId) Id, #define LAST_BUILTIN_TYPE(Id) LastKind = Id #include "clang/AST/BuiltinTypes.def" @@ -2050,7 +2082,7 @@ public: } bool isFloatingPoint() const { - return getKind() >= Half && getKind() <= LongDouble; + return getKind() >= Half && getKind() <= Float128; } /// Determines whether the given kind corresponds to a placeholder type. @@ -2499,13 +2531,13 @@ public: /// \brief Determine the number of bits required to address a member of // an array with the given element type and number of elements. - static unsigned getNumAddressingBits(ASTContext &Context, + static unsigned getNumAddressingBits(const ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements); /// \brief Determine the maximum number of active bits that an array's size /// can require, which limits the maximum size of the array. - static unsigned getMaxSizeBits(ASTContext &Context); + static unsigned getMaxSizeBits(const ASTContext &Context); void Profile(llvm::FoldingSetNodeID &ID) { Profile(ID, getElementType(), getSize(), @@ -2990,7 +3022,7 @@ public: /// \brief Determine the type of an expression that calls a function of /// this type. - QualType getCallResultType(ASTContext &Context) const { + QualType getCallResultType(const ASTContext &Context) const { return getReturnType().getNonLValueExprType(Context); } @@ -3040,6 +3072,74 @@ public: /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { public: + /// Interesting information about a specific parameter that can't simply + /// be reflected in parameter's type. + /// + /// It makes sense to model language features this way when there's some + /// sort of parameter-specific override (such as an attribute) that + /// affects how the function is called. For example, the ARC ns_consumed + /// attribute changes whether a parameter is passed at +0 (the default) + /// or +1 (ns_consumed). This must be reflected in the function type, + /// but isn't really a change to the parameter type. + /// + /// One serious disadvantage of modelling language features this way is + /// that they generally do not work with language features that attempt + /// to destructure types. For example, template argument deduction will + /// not be able to match a parameter declared as + /// T (*)(U) + /// against an argument of type + /// void (*)(__attribute__((ns_consumed)) id) + /// because the substitution of T=void, U=id into the former will + /// not produce the latter. + class ExtParameterInfo { + enum { + ABIMask = 0x0F, + IsConsumed = 0x10 + }; + unsigned char Data; + public: + ExtParameterInfo() : Data(0) {} + + /// Return the ABI treatment of this parameter. + ParameterABI getABI() const { + return ParameterABI(Data & ABIMask); + } + ExtParameterInfo withABI(ParameterABI kind) const { + ExtParameterInfo copy = *this; + copy.Data = (copy.Data & ~ABIMask) | unsigned(kind); + return copy; + } + + /// Is this parameter considered "consumed" by Objective-C ARC? + /// Consumed parameters must have retainable object type. + bool isConsumed() const { + return (Data & IsConsumed); + } + ExtParameterInfo withIsConsumed(bool consumed) const { + ExtParameterInfo copy = *this; + if (consumed) { + copy.Data |= IsConsumed; + } else { + copy.Data &= ~IsConsumed; + } + return copy; + } + + unsigned char getOpaqueValue() const { return Data; } + static ExtParameterInfo getFromOpaqueValue(unsigned char data) { + ExtParameterInfo result; + result.Data = data; + return result; + } + + friend bool operator==(ExtParameterInfo lhs, ExtParameterInfo rhs) { + return lhs.Data == rhs.Data; + } + friend bool operator!=(ExtParameterInfo lhs, ExtParameterInfo rhs) { + return lhs.Data != rhs.Data; + } + }; + struct ExceptionSpecInfo { ExceptionSpecInfo() : Type(EST_None), NoexceptExpr(nullptr), @@ -3067,11 +3167,11 @@ public: struct ExtProtoInfo { ExtProtoInfo() : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ExtParameterInfos(nullptr) {} ExtProtoInfo(CallingConv CC) : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - RefQualifier(RQ_None), ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ExtParameterInfos(nullptr) {} ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { ExtProtoInfo Result(*this); @@ -3085,7 +3185,7 @@ public: unsigned char TypeQuals; RefQualifierKind RefQualifier; ExceptionSpecInfo ExceptionSpec; - const bool *ConsumedParameters; + const ExtParameterInfo *ExtParameterInfos; }; private: @@ -3112,8 +3212,8 @@ private: /// The type of exception specification this function has. unsigned ExceptionSpecType : 4; - /// Whether this function has any consumed parameters. - unsigned HasAnyConsumedParams : 1; + /// Whether this function has extended parameter information. + unsigned HasExtParameterInfos : 1; /// Whether the function is variadic. unsigned Variadic : 1; @@ -3135,25 +3235,36 @@ private: // instantiate this function type's exception specification, and the function // from which it should be instantiated. - // ConsumedParameters - A variable size array, following Exceptions - // and of length NumParams, holding flags indicating which parameters - // are consumed. This only appears if HasAnyConsumedParams is true. + // ExtParameterInfos - A variable size array, following the exception + // specification and of length NumParams, holding an ExtParameterInfo + // for each of the parameters. This only appears if HasExtParameterInfos + // is true. friend class ASTContext; // ASTContext creates these. - const bool *getConsumedParamsBuffer() const { - assert(hasAnyConsumedParams()); + const ExtParameterInfo *getExtParameterInfosBuffer() const { + assert(hasExtParameterInfos()); - // Find the end of the exceptions. - Expr *const *eh_end = reinterpret_cast(exception_end()); - if (getExceptionSpecType() == EST_ComputedNoexcept) - eh_end += 1; // NoexceptExpr - // The memory layout of these types isn't handled here, so - // hopefully this is never called for them? - assert(getExceptionSpecType() != EST_Uninstantiated && - getExceptionSpecType() != EST_Unevaluated); + // Find the end of the exception specification. + const char *ptr = reinterpret_cast(exception_begin()); + ptr += getExceptionSpecSize(); - return reinterpret_cast(eh_end); + return reinterpret_cast(ptr); + } + + size_t getExceptionSpecSize() const { + switch (getExceptionSpecType()) { + case EST_None: return 0; + case EST_DynamicNone: return 0; + case EST_MSAny: return 0; + case EST_BasicNoexcept: return 0; + case EST_Unparsed: return 0; + case EST_Dynamic: return getNumExceptions() * sizeof(QualType); + case EST_ComputedNoexcept: return sizeof(Expr*); + case EST_Uninstantiated: return 2 * sizeof(FunctionDecl*); + case EST_Unevaluated: return sizeof(FunctionDecl*); + } + llvm_unreachable("bad exception specification kind"); } public: @@ -3184,8 +3295,8 @@ public: } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); } - if (hasAnyConsumedParams()) - EPI.ConsumedParameters = getConsumedParamsBuffer(); + if (hasExtParameterInfos()) + EPI.ExtParameterInfos = getExtParameterInfosBuffer(); return EPI; } @@ -3300,11 +3411,41 @@ public: return exception_begin() + NumExceptions; } - bool hasAnyConsumedParams() const { return HasAnyConsumedParams; } + /// Is there any interesting extra information for any of the parameters + /// of this function type? + bool hasExtParameterInfos() const { return HasExtParameterInfos; } + ArrayRef getExtParameterInfos() const { + assert(hasExtParameterInfos()); + return ArrayRef(getExtParameterInfosBuffer(), + getNumParams()); + } + /// Return a pointer to the beginning of the array of extra parameter + /// information, if present, or else null if none of the parameters + /// carry it. This is equivalent to getExtProtoInfo().ExtParameterInfos. + const ExtParameterInfo *getExtParameterInfosOrNull() const { + if (!hasExtParameterInfos()) + return nullptr; + return getExtParameterInfosBuffer(); + } + + ExtParameterInfo getExtParameterInfo(unsigned I) const { + assert(I < getNumParams() && "parameter index out of range"); + if (hasExtParameterInfos()) + return getExtParameterInfosBuffer()[I]; + return ExtParameterInfo(); + } + + ParameterABI getParameterABI(unsigned I) const { + assert(I < getNumParams() && "parameter index out of range"); + if (hasExtParameterInfos()) + return getExtParameterInfosBuffer()[I].getABI(); + return ParameterABI::Ordinary; + } + bool isParamConsumed(unsigned I) const { assert(I < getNumParams() && "parameter index out of range"); - if (hasAnyConsumedParams()) - return getConsumedParamsBuffer()[I]; + if (hasExtParameterInfos()) + return getExtParameterInfosBuffer()[I].isConsumed(); return false; } @@ -3518,6 +3659,28 @@ public: } }; +/// \brief Internal representation of canonical, dependent +/// __underlying_type(type) types. +/// +/// This class is used internally by the ASTContext to manage +/// canonical, dependent types, only. Clients will only see instances +/// of this class via UnaryTransformType nodes. +class DependentUnaryTransformType : public UnaryTransformType, + public llvm::FoldingSetNode { +public: + DependentUnaryTransformType(const ASTContext &C, QualType BaseType, + UTTKind UKind); + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, getBaseType(), getUTTKind()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, QualType BaseType, + UTTKind UKind) { + ID.AddPointer(BaseType.getAsOpaquePtr()); + ID.AddInteger((unsigned)UKind); + } +}; + class TagType : public Type { /// Stores the TagDecl associated with this type. The decl may point to any /// TagDecl that declares the entity. @@ -3626,10 +3789,13 @@ public: attr_stdcall, attr_thiscall, attr_pascal, + attr_swiftcall, attr_vectorcall, attr_inteloclbicc, attr_ms_abi, attr_sysv_abi, + attr_preserve_most, + attr_preserve_all, attr_ptr32, attr_ptr64, attr_sptr, @@ -4002,19 +4168,18 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType unsigned NumArgs : 31; /// Whether this template specialization type is a substituted type alias. - bool TypeAlias : 1; + unsigned TypeAlias : 1; TemplateSpecializationType(TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, QualType Canon, + ArrayRef Args, + QualType Canon, QualType Aliased); friend class ASTContext; // ASTContext creates these public: /// Determine whether any of the given template arguments are dependent. - static bool anyDependentTemplateArguments(const TemplateArgumentLoc *Args, - unsigned NumArgs, + static bool anyDependentTemplateArguments(ArrayRef Args, bool &InstantiationDependent); static bool anyDependentTemplateArguments(const TemplateArgumentListInfo &, @@ -4023,14 +4188,12 @@ public: /// \brief Print a template argument list, including the '<' and '>' /// enclosing the template arguments. static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, const PrintingPolicy &Policy, bool SkipBrackets = false); static void PrintTemplateArgumentList(raw_ostream &OS, - const TemplateArgumentLoc *Args, - unsigned NumArgs, + ArrayRef Args, const PrintingPolicy &Policy); static void PrintTemplateArgumentList(raw_ostream &OS, @@ -4087,20 +4250,23 @@ public: /// \pre \c isArgType(Arg) const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h + ArrayRef template_arguments() const { + return {getArgs(), NumArgs}; + } + bool isSugared() const { return !isDependentType() || isCurrentInstantiation() || isTypeAlias(); } QualType desugar() const { return getCanonicalTypeInternal(); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx) { - Profile(ID, Template, getArgs(), NumArgs, Ctx); + Profile(ID, Template, template_arguments(), Ctx); if (isTypeAlias()) getAliasedType().Profile(ID); } static void Profile(llvm::FoldingSetNodeID &ID, TemplateName T, - const TemplateArgument *Args, - unsigned NumArgs, + ArrayRef Args, const ASTContext &Context); static bool classof(const Type *T) { @@ -4143,6 +4309,8 @@ class InjectedClassNameType : public Type { friend class ASTReader; // FIXME: ASTContext::getInjectedClassNameType is not // currently suitable for AST reading, too much // interdependencies. + friend class ASTNodeImporter; + InjectedClassNameType(CXXRecordDecl *D, QualType TST) : Type(InjectedClassName, QualType(), /*Dependent=*/true, /*InstantiationDependent=*/true, @@ -4402,8 +4570,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType DependentTemplateSpecializationType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args, + ArrayRef Args, QualType Canon); friend class ASTContext; // ASTContext creates these @@ -4422,6 +4589,10 @@ public: const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h + ArrayRef template_arguments() const { + return {getArgs(), NumArgs}; + } + typedef const TemplateArgument * iterator; iterator begin() const { return getArgs(); } iterator end() const; // inline in TemplateBase.h @@ -4430,7 +4601,7 @@ public: QualType desugar() const { return QualType(this, 0); } void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) { - Profile(ID, Context, getKeyword(), NNS, Name, NumArgs, getArgs()); + Profile(ID, Context, getKeyword(), NNS, Name, {getArgs(), NumArgs}); } static void Profile(llvm::FoldingSetNodeID &ID, @@ -4438,8 +4609,7 @@ public: ElaboratedTypeKeyword Keyword, NestedNameSpecifier *Qualifier, const IdentifierInfo *Name, - unsigned NumArgs, - const TemplateArgument *Args); + ArrayRef Args); static bool classof(const Type *T) { return T->getTypeClass() == DependentTemplateSpecialization; @@ -5194,7 +5364,8 @@ inline void QualType::removeLocalVolatile() { inline void QualType::removeLocalCVRQualifiers(unsigned Mask) { assert(!(Mask & ~Qualifiers::CVRMask) && "mask has non-CVR bits"); - assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask); + static_assert((int)Qualifiers::CVRMask == (int)Qualifiers::FastMask, + "Fast bits differ from CVR bits!"); // Fast path: we don't need to touch the slow qualifiers. removeLocalFastQualifiers(Mask); @@ -5230,9 +5401,9 @@ inline FunctionType::ExtInfo getFunctionExtInfo(QualType t) { /// "int". However, it is not more qualified than "const volatile /// int". inline bool QualType::isMoreQualifiedThan(QualType other) const { - Qualifiers myQuals = getQualifiers(); - Qualifiers otherQuals = other.getQualifiers(); - return (myQuals != otherQuals && myQuals.compatiblyIncludes(otherQuals)); + Qualifiers MyQuals = getQualifiers(); + Qualifiers OtherQuals = other.getQualifiers(); + return (MyQuals != OtherQuals && MyQuals.compatiblyIncludes(OtherQuals)); } /// Determine whether this type is at last @@ -5240,7 +5411,13 @@ inline bool QualType::isMoreQualifiedThan(QualType other) const { /// int" is at least as qualified as "const int", "volatile int", /// "int", and "const volatile int". inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { - return getQualifiers().compatiblyIncludes(other.getQualifiers()); + Qualifiers OtherQuals = other.getQualifiers(); + + // Ignore __unaligned qualifier if this type is a void. + if (getUnqualifiedType()->isVoidType()) + OtherQuals.removeUnaligned(); + + return getQualifiers().compatiblyIncludes(OtherQuals); } /// If Type is a reference type (e.g., const @@ -5417,53 +5594,11 @@ inline bool Type::isObjCBuiltinType() const { return isObjCIdType() || isObjCClassType() || isObjCSelType(); } -inline bool Type::isImage1dT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage1d); -} - -inline bool Type::isImage1dArrayT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage1dArray); -} - -inline bool Type::isImage1dBufferT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage1dBuffer); -} - -inline bool Type::isImage2dT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2d); -} - -inline bool Type::isImage2dArrayT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArray); -} - -inline bool Type::isImage2dDepthT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dDepth); -} - -inline bool Type::isImage2dArrayDepthT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayDepth); -} - -inline bool Type::isImage2dMSAAT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAA); -} - -inline bool Type::isImage2dArrayMSAAT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAA); -} - -inline bool Type::isImage2dMSAATDepth() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dMSAADepth); -} - -inline bool Type::isImage2dArrayMSAATDepth() const { - return isSpecificBuiltinType(BuiltinType::OCLImage2dArrayMSAADepth); -} - -inline bool Type::isImage3dT() const { - return isSpecificBuiltinType(BuiltinType::OCLImage3d); -} +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ + inline bool Type::is##Id##Type() const { \ + return isSpecificBuiltinType(BuiltinType::Id); \ + } +#include "clang/Basic/OpenCLImageTypes.def" inline bool Type::isSamplerT() const { return isSpecificBuiltinType(BuiltinType::OCLSampler); @@ -5490,11 +5625,10 @@ inline bool Type::isReserveIDT() const { } inline bool Type::isImageType() const { - return isImage3dT() || isImage2dT() || isImage2dArrayT() || - isImage2dDepthT() || isImage2dArrayDepthT() || isImage2dMSAAT() || - isImage2dArrayMSAAT() || isImage2dMSAATDepth() || - isImage2dArrayMSAATDepth() || isImage1dT() || isImage1dArrayT() || - isImage1dBufferT(); +#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) is##Id##Type() || + return +#include "clang/Basic/OpenCLImageTypes.def" + 0; // end boolean or operation } inline bool Type::isPipeType() const { @@ -5644,6 +5778,15 @@ inline const Type *Type::getBaseElementTypeUnsafe() const { return type; } +inline const Type *Type::getPointeeOrArrayElementType() const { + const Type *type = this; + if (type->isAnyPointerType()) + return type->getPointeeType().getTypePtr(); + else if (type->isArrayType()) + return type->getBaseElementTypeUnsafe(); + return type; +} + /// Insertion operator for diagnostics. This allows sending QualType's into a /// diagnostic with <<. inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 29035a41776e8..67adf4a638bc9 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -254,7 +254,7 @@ public: unsigned align = TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0)); uintptr_t dataInt = reinterpret_cast(Data); - dataInt = llvm::RoundUpToAlignment(dataInt, align); + dataInt = llvm::alignTo(dataInt, align); return UnqualTypeLoc(getTypePtr(), reinterpret_cast(dataInt)); } @@ -353,7 +353,7 @@ public: unsigned getLocalDataSize() const { unsigned size = sizeof(LocalData); unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); - size = llvm::RoundUpToAlignment(size, extraAlign); + size = llvm::alignTo(size, extraAlign); size += asDerived()->getExtraLocalDataSize(); return size; } @@ -399,14 +399,14 @@ protected: void *getExtraLocalData() const { unsigned size = sizeof(LocalData); unsigned extraAlign = asDerived()->getExtraLocalDataAlignment(); - size = llvm::RoundUpToAlignment(size, extraAlign); + size = llvm::alignTo(size, extraAlign); return reinterpret_cast(Base::Data) + size; } void *getNonLocalData() const { uintptr_t data = reinterpret_cast(Base::Data); data += asDerived()->getLocalDataSize(); - data = llvm::RoundUpToAlignment(data, getNextTypeAlign()); + data = llvm::alignTo(data, getNextTypeAlign()); return reinterpret_cast(data); } @@ -538,7 +538,7 @@ public: bool needsExtraLocalData() const { BuiltinType::Kind bk = getTypePtr()->getKind(); return (bk >= BuiltinType::UShort && bk <= BuiltinType::UInt128) - || (bk >= BuiltinType::Short && bk <= BuiltinType::LongDouble) + || (bk >= BuiltinType::Short && bk <= BuiltinType::Float128) || bk == BuiltinType::UChar || bk == BuiltinType::SChar; } diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 26ee1cf71c813..c1be2aa0f2013 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -59,8 +59,13 @@ class UnresolvedSetImpl { // UnresolvedSet. private: template friend class UnresolvedSet; - UnresolvedSetImpl() {} - UnresolvedSetImpl(const UnresolvedSetImpl &) {} + UnresolvedSetImpl() = default; + UnresolvedSetImpl(const UnresolvedSetImpl &) = default; + UnresolvedSetImpl &operator=(const UnresolvedSetImpl &) = default; + + // FIXME: Switch these to "= default" once MSVC supports generating move ops + UnresolvedSetImpl(UnresolvedSetImpl &&) {} + UnresolvedSetImpl &operator=(UnresolvedSetImpl &&) { return *this; } public: // We don't currently support assignment through this iterator, so we might diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 92ec92c299c57..042408859c9de 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -241,6 +241,11 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, ASTContext &Context); /// @} +/// \brief Returns the results of matching \p Matcher on the translation unit of +/// \p Context and collects the \c BoundNodes of all callback invocations. +template +SmallVector match(MatcherT Matcher, ASTContext &Context); + /// \brief Returns the first result of type \c NodeT bound to \p BoundTo. /// /// Returns \c NULL if there is no match, or if the matching node cannot be @@ -288,6 +293,16 @@ match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { return match(Matcher, ast_type_traits::DynTypedNode::create(Node), Context); } +template +SmallVector +match(MatcherT Matcher, ASTContext &Context) { + internal::CollectMatchesCallback Callback; + MatchFinder Finder; + Finder.addMatcher(Matcher, &Callback); + Finder.matchAST(Context); + return std::move(Callback.Nodes); +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index e6ba8778f249a..aef4b4eafd9ac 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -163,11 +163,35 @@ const internal::VariadicDynCastAllOfMatcher /// Given /// \code /// typedef int X; +/// using Y = int; /// \endcode /// typedefDecl() -/// matches "typedef int X" +/// matches "typedef int X", but not "using Y = int" const internal::VariadicDynCastAllOfMatcher typedefDecl; +/// \brief Matches typedef name declarations. +/// +/// Given +/// \code +/// typedef int X; +/// using Y = int; +/// \endcode +/// typedefNameDecl() +/// matches "typedef int X" and "using Y = int" +const internal::VariadicDynCastAllOfMatcher + typedefNameDecl; + +/// \brief Matches type alias declarations. +/// +/// Given +/// \code +/// typedef int X; +/// using Y = int; +/// \endcode +/// typeAliasDecl() +/// matches "using Y = int", but not "typedef int X" +const internal::VariadicDynCastAllOfMatcher typeAliasDecl; + /// \brief Matches AST nodes that were expanded within the main-file. /// /// Example matches X but not Y @@ -282,6 +306,17 @@ const internal::VariadicDynCastAllOfMatcher /// \endcode const internal::VariadicDynCastAllOfMatcher namedDecl; +/// \brief Matches a declaration of label. +/// +/// Given +/// \code +/// goto FOO; +/// FOO: bar(); +/// \endcode +/// labelDecl() +/// matches 'FOO:' +const internal::VariadicDynCastAllOfMatcher labelDecl; + /// \brief Matches a declaration of a namespace. /// /// Given @@ -447,7 +482,7 @@ const internal::VariadicDynCastAllOfMatcher< /// }; /// \endcode /// fieldDecl(isPublic()) -/// matches 'int a;' +/// matches 'int a;' AST_MATCHER(Decl, isPublic) { return Node.getAccess() == AS_public; } @@ -463,7 +498,7 @@ AST_MATCHER(Decl, isPublic) { /// }; /// \endcode /// fieldDecl(isProtected()) -/// matches 'int b;' +/// matches 'int b;' AST_MATCHER(Decl, isProtected) { return Node.getAccess() == AS_protected; } @@ -479,11 +514,43 @@ AST_MATCHER(Decl, isProtected) { /// }; /// \endcode /// fieldDecl(isPrivate()) -/// matches 'int c;' +/// matches 'int c;' AST_MATCHER(Decl, isPrivate) { return Node.getAccess() == AS_private; } +/// \brief Matches non-static data members that are bit-fields. +/// +/// Given +/// \code +/// class C { +/// int a : 2; +/// int b; +/// }; +/// \endcode +/// fieldDecl(isBitField()) +/// matches 'int a;' but not 'int b;'. +AST_MATCHER(FieldDecl, isBitField) { + return Node.isBitField(); +} + +/// \brief Matches non-static data members that are bit-fields. +/// +/// Given +/// \code +/// class C { +/// int a : 2; +/// int b : 4; +/// int c : 2; +/// }; +/// \endcode +/// fieldDecl(isBitField()) +/// matches 'int a;' and 'int c;' but not 'int b;'. +AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) { + return Node.isBitField() && + Node.getBitWidthValue(Finder->getASTContext()) == Width; +} + /// \brief Matches a declaration that has been implicitly added /// by the compiler (eg. implicit default/copy constructors). AST_MATCHER(Decl, isImplicit) { @@ -513,6 +580,32 @@ AST_POLYMORPHIC_MATCHER_P( Builder); } +/// \brief Matches expressions that match InnerMatcher after any implicit AST +/// nodes are stripped off. +/// +/// Parentheses and explicit casts are not discarded. +/// Given +/// \code +/// class C {}; +/// C a = C(); +/// C b; +/// C c = b; +/// \endcode +/// The matchers +/// \code +/// varDecl(hasInitializer(ignoringImplicit(cxxConstructExpr()))) +/// \endcode +/// would match the declarations for a, b, and c. +/// While +/// \code +/// varDecl(hasInitializer(cxxConstructExpr())) +/// \endcode +/// only match the declarations for b and c. +AST_MATCHER_P(Expr, ignoringImplicit, ast_matchers::internal::Matcher, + InnerMatcher) { + return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder); +} + /// \brief Matches expressions that match InnerMatcher after any implicit casts /// are stripped off. /// @@ -590,6 +683,22 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts, return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder); } +/// \brief Matches types that match InnerMatcher after any parens are stripped. +/// +/// Given +/// \code +/// void (*fp)(void); +/// \endcode +/// The matcher +/// \code +/// varDecl(hasType(pointerType(pointee(ignoringParens(functionType()))))) +/// \endcode +/// would match the declaration for fp. +AST_MATCHER_P(QualType, ignoringParens, + internal::Matcher, InnerMatcher) { + return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder); +} + /// \brief Matches classTemplateSpecializations where the n'th TemplateArgument /// matches the given InnerMatcher. /// @@ -976,6 +1085,43 @@ const internal::VariadicDynCastAllOfMatcher< /// matches "{ 1, 2 }" and "{ 5, 6 }" const internal::VariadicDynCastAllOfMatcher initListExpr; +/// \brief Matches the syntactic form of init list expressions +/// (if expression have it). +AST_MATCHER_P(InitListExpr, hasSyntacticForm, + internal::Matcher, InnerMatcher) { + const Expr *SyntForm = Node.getSyntacticForm(); + return (SyntForm != nullptr && + InnerMatcher.matches(*SyntForm, Finder, Builder)); +} + +/// \brief Matches implicit initializers of init list expressions. +/// +/// Given +/// \code +/// point ptarray[10] = { [2].y = 1.0, [2].x = 2.0, [0].x = 1.0 }; +/// \endcode +/// implicitValueInitExpr() +/// matches "[0].y" (implicitly) +const internal::VariadicDynCastAllOfMatcher +implicitValueInitExpr; + +/// \brief Matches paren list expressions. +/// ParenListExprs don't have a predefined type and are used for late parsing. +/// In the final AST, they can be met in template declarations. +/// +/// Given +/// \code +/// template class X { +/// void f() { +/// X x(*this); +/// int a = 0, b = 1; int i = (a, b); +/// } +/// }; +/// \endcode +/// parenListExpr() matches "*this" but NOT matches (a, b) because (a, b) +/// has a predefined type and is a ParenExpr, not a ParenListExpr. +const internal::VariadicDynCastAllOfMatcher parenListExpr; + /// \brief Matches substitutions of non-type template parameters. /// /// Given @@ -1014,6 +1160,24 @@ const internal::VariadicDynCastAllOfMatcher< Decl, UsingDirectiveDecl> usingDirectiveDecl; +/// \brief Matches reference to a name that can be looked up during parsing +/// but could not be resolved to a specific declaration. +/// +/// Given +/// \code +/// template +/// T foo() { T a; return a; } +/// template +/// void bar() { +/// foo(); +/// } +/// \endcode +/// unresolvedLookupExpr() +/// matches \code foo() \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + UnresolvedLookupExpr> unresolvedLookupExpr; + /// \brief Matches unresolved using value declarations. /// /// Given @@ -1048,6 +1212,17 @@ const internal::VariadicDynCastAllOfMatcher< Decl, UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl; +/// \brief Matches parentheses used in expressions. +/// +/// Example matches (foo() + 1) +/// \code +/// int foo() { return 1; } +/// int a = (foo() + 1); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + ParenExpr> parenExpr; + /// \brief Matches constructor call expressions (including implicit ones). /// /// Example matches string(ptr, n) and ptr within arguments of f @@ -1357,6 +1532,18 @@ const internal::VariadicDynCastAllOfMatcher gotoStmt; /// matches 'FOO:' const internal::VariadicDynCastAllOfMatcher labelStmt; +/// \brief Matches address of label statements (GNU extension). +/// +/// Given +/// \code +/// FOO: bar(); +/// void *ptr = &&FOO; +/// goto *bar; +/// \endcode +/// addrLabelExpr() +/// matches '&&FOO' +const internal::VariadicDynCastAllOfMatcher addrLabelExpr; + /// \brief Matches switch statements. /// /// Given @@ -1465,7 +1652,8 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches "abcd", L"abcd" /// \code -/// char *s = "abcd"; wchar_t *ws = L"abcd" +/// char *s = "abcd"; +/// wchar_t *ws = L"abcd"; /// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, @@ -1478,7 +1666,8 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example matches 'a', L'a' /// \code -/// char ch = 'a'; wchar_t chw = L'a'; +/// char ch = 'a'; +/// wchar_t chw = L'a'; /// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, @@ -1514,7 +1703,8 @@ const internal::VariadicDynCastAllOfMatcher< /// /// Example match: {1}, (1, 2) /// \code -/// int array[4] = {1}; vector int myvec = (vector int)(1, 2); +/// int array[4] = {1}; +/// vector int myvec = (vector int)(1, 2); /// \endcode const internal::VariadicDynCastAllOfMatcher< Stmt, @@ -1526,9 +1716,22 @@ const internal::VariadicDynCastAllOfMatcher< CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; /// \brief Matches GNU __null expression. -const internal::VariadicDynCastAllOfMatcher< - Stmt, - GNUNullExpr> gnuNullExpr; +const internal::VariadicDynCastAllOfMatcher gnuNullExpr; + +/// \brief Matches atomic builtins. +/// Example matches __atomic_load_n(ptr, 1) +/// \code +/// void foo() { int *ptr; __atomic_load_n(ptr, 1); } +/// \endcode +const internal::VariadicDynCastAllOfMatcher atomicExpr; + +/// \brief Matches statement expression (GNU extension). +/// +/// Example match: ({ int X = 4; X; }) +/// \code +/// int C = ({ int X = 4; X; }); +/// \endcode +const internal::VariadicDynCastAllOfMatcher stmtExpr; /// \brief Matches binary operator expressions. /// @@ -1560,6 +1763,28 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, ConditionalOperator> conditionalOperator; +/// \brief Matches binary conditional operator expressions (GNU extension). +/// +/// Example matches a ?: b +/// \code +/// (a ?: b) + 42; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + BinaryConditionalOperator> binaryConditionalOperator; + +/// \brief Matches opaque value expressions. They are used as helpers +/// to reference another expressions and can be met +/// in BinaryConditionalOperators, for example. +/// +/// Example matches 'a' +/// \code +/// (a ?: c) + 42; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + OpaqueValueExpr> opaqueValueExpr; + /// \brief Matches a C++ static_assert declaration. /// /// Example: @@ -1716,6 +1941,41 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CXXTemporaryObjectExpr> cxxTemporaryObjectExpr; +/// \brief Matches predefined identifier expressions [C99 6.4.2.2]. +/// +/// Example: Matches __func__ +/// \code +/// printf("%s", __func__); +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + PredefinedExpr> predefinedExpr; + +/// \brief Matches C99 designated initializer expressions [C99 6.7.8]. +/// +/// Example: Matches { [2].y = 1.0, [0].x = 1.0 } +/// \code +/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 }; +/// \endcode +const internal::VariadicDynCastAllOfMatcher< + Stmt, + DesignatedInitExpr> designatedInitExpr; + +/// \brief Matches designated initializer expressions that contain +/// a specific number of designators. +/// +/// Example: Given +/// \code +/// point ptarray[10] = { [2].y = 1.0, [0].x = 1.0 }; +/// point ptarray2[10] = { [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }; +/// \endcode +/// designatorCountIs(2) +/// matches '{ [2].y = 1.0, [0].x = 1.0 }', +/// but not '{ [2].y = 1.0, [2].x = 0.0, [0].x = 1.0 }'. +AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) { + return Node.size() == N; +} + /// \brief Matches \c QualTypes in the clang AST. const internal::VariadicAllOfMatcher qualType; @@ -1834,9 +2094,25 @@ inline internal::Matcher sizeOfExpr( /// namespace a { namespace b { class X; } } /// \endcode inline internal::Matcher hasName(const std::string &Name) { - return internal::Matcher(new internal::HasNameMatcher(Name)); + std::vector Names; + Names.push_back(Name); + return internal::Matcher(new internal::HasNameMatcher(Names)); } +/// \brief Matches NamedDecl nodes that have any of the specified names. +/// +/// This matcher is only provided as a performance optimization of hasName. +/// \code +/// hasAnyName(a, b, c) +/// \endcode +/// is equivalent to, but faster than +/// \code +/// anyOf(hasName(a), hasName(b), hasName(c)) +/// \endcode +const internal::VariadicFunction, StringRef, + internal::hasAnyNameFunc> + hasAnyName = {}; + /// \brief Matches NamedDecl nodes whose fully qualified names contain /// a substring matched by the given RegExp. /// @@ -1953,6 +2229,19 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher, Node.method_end(), Finder, Builder); } +/// \brief Matches the generated class of lambda expressions. +/// +/// Given: +/// \code +/// auto x = []{}; +/// \endcode +/// +/// \c cxxRecordDecl(isLambda()) matches the implicit class declaration of +/// \c decltype(x) +AST_MATCHER(CXXRecordDecl, isLambda) { + return Node.isLambda(); +} + /// \brief Matches AST nodes that have child AST nodes that match the /// provided matcher. /// @@ -1967,6 +2256,10 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher, /// ChildT must be an AST base type. /// /// Usable as: Any Matcher +/// Note that has is direct matcher, so it also matches things like implicit +/// casts and paren casts. If you are matching with expr then you should +/// probably consider using ignoringParenImpCasts like: +/// has(ignoringParenImpCasts(expr())). const internal::ArgumentAdaptingMatcherFunc LLVM_ATTRIBUTE_UNUSED has = {}; @@ -2117,8 +2410,8 @@ const internal::VariadicOperatorMatcherFunc<1, 1> unless = { /// /// Usable as: Matcher, Matcher, /// Matcher, Matcher, Matcher, -/// Matcher, Matcher, Matcher, -/// Matcher, Matcher, +/// Matcher, Matcher, Matcher, +/// Matcher, Matcher, Matcher, /// Matcher, Matcher, /// Matcher, Matcher inline internal::PolymorphicMatcherWithParam1< @@ -2287,14 +2580,17 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher, InnerMatcher, /// /// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X"))))) /// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X"))))) +/// and U (matcher = typedefDecl(hasType(asString("int"))) /// \code /// class X {}; /// void y(X &x) { x; X z; } +/// typedef int U; /// \endcode AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, ValueDecl), + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefNameDecl, ValueDecl), internal::Matcher, InnerMatcher, 0) { - return InnerMatcher.matches(Node.getType(), Finder, Builder); + return InnerMatcher.matches(internal::getUnderlyingType(Node), + Finder, Builder); } /// \brief Overloaded to match the declaration of the expression's or value @@ -2829,18 +3125,13 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) { /// matches x(1, y, 42) /// with hasAnyArgument(...) /// matching y -/// -/// 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(CallExpr, CXXConstructExpr), internal::Matcher, InnerMatcher) { for (const Expr *Arg : Node.arguments()) { BoundNodesTreeBuilder Result(*Builder); - if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) { + if (InnerMatcher.matches(*Arg, Finder, &Result)) { *Builder = std::move(Result); return true; } @@ -2853,6 +3144,22 @@ AST_MATCHER(CXXConstructExpr, isListInitialization) { return Node.isListInitialization(); } +/// \brief Matches a constructor call expression which requires +/// zero initialization. +/// +/// Given +/// \code +/// void foo() { +/// struct point { double x; double y; }; +/// point pt[2] = { { 1.0, 2.0 } }; +/// } +/// \endcode +/// initListExpr(has(cxxConstructExpr(requiresZeroInitialization())) +/// will match the implicit array filler for pt[1]. +AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) { + return Node.requiresZeroInitialization(); +} + /// \brief Matches the n'th parameter of a function declaration. /// /// Given @@ -2871,6 +3178,60 @@ AST_MATCHER_P2(FunctionDecl, hasParameter, *Node.getParamDecl(N), Finder, Builder)); } +/// \brief Matches all arguments and their respective ParmVarDecl. +/// +/// Given +/// \code +/// void f(int i); +/// int y; +/// f(y); +/// \endcode +/// callExpr( +/// forEachArgumentWithParam( +/// declRefExpr(to(varDecl(hasName("y")))), +/// parmVarDecl(hasType(isInteger())) +/// )) +/// matches f(y); +/// with declRefExpr(...) +/// matching int y +/// and parmVarDecl(...) +/// matching int i +AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam, + AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, + CXXConstructExpr), + internal::Matcher, ArgMatcher, + internal::Matcher, ParamMatcher) { + BoundNodesTreeBuilder Result; + // The first argument of an overloaded member operator is the implicit object + // argument of the method which should not be matched against a parameter, so + // we skip over it here. + BoundNodesTreeBuilder Matches; + unsigned ArgIndex = cxxOperatorCallExpr(callee(cxxMethodDecl())) + .matches(Node, Finder, &Matches) + ? 1 + : 0; + int ParamIndex = 0; + bool Matched = false; + for (; ArgIndex < Node.getNumArgs(); ++ArgIndex) { + BoundNodesTreeBuilder ArgMatches(*Builder); + if (ArgMatcher.matches(*(Node.getArg(ArgIndex)->IgnoreParenCasts()), + Finder, &ArgMatches)) { + BoundNodesTreeBuilder ParamMatches(ArgMatches); + if (expr(anyOf(cxxConstructExpr(hasDeclaration(cxxConstructorDecl( + hasParameter(ParamIndex, ParamMatcher)))), + callExpr(callee(functionDecl( + hasParameter(ParamIndex, ParamMatcher)))))) + .matches(Node, Finder, &ParamMatches)) { + Result.addMatch(ParamMatches); + Matched = true; + } + } + ++ParamIndex; + } + *Builder = std::move(Result); + return Matched; +} + /// \brief Matches any parameter of a function declaration. /// /// Does not match the 'this' parameter of a method. @@ -2889,16 +3250,27 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, Node.param_end(), Finder, Builder); } -/// \brief Matches \c FunctionDecls that have a specific parameter count. +/// \brief Matches \c FunctionDecls and \c FunctionProtoTypes that have a +/// specific parameter count. /// /// Given /// \code /// void f(int i) {} /// void g(int i, int j) {} +/// void h(int i, int j); +/// void j(int i); +/// void k(int x, int y, int z, ...); /// \endcode /// functionDecl(parameterCountIs(2)) -/// matches g(int i, int j) {} -AST_MATCHER_P(FunctionDecl, parameterCountIs, unsigned, N) { +/// matches void g(int i, int j) {} +/// functionProtoType(parameterCountIs(2)) +/// matches void h(int i, int j) +/// functionProtoType(parameterCountIs(3)) +/// matches void k(int x, int y, int z, ...); +AST_POLYMORPHIC_MATCHER_P(parameterCountIs, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + FunctionProtoType), + unsigned, N) { return Node.getNumParams() == N; } @@ -2942,6 +3314,42 @@ AST_MATCHER(FunctionDecl, isDeleted) { return Node.isDeleted(); } +/// \brief Matches defaulted function declarations. +/// +/// Given: +/// \code +/// class A { ~A(); }; +/// class B { ~B() = default; }; +/// \endcode +/// functionDecl(isDefaulted()) +/// matches the declaration of ~B, but not ~A. +AST_MATCHER(FunctionDecl, isDefaulted) { + return Node.isDefaulted(); +} + +/// \brief Matches functions that have a dynamic exception specification. +/// +/// Given: +/// \code +/// void f(); +/// void g() noexcept; +/// void h() noexcept(true); +/// void i() noexcept(false); +/// void j() throw(); +/// void k() throw(int); +/// void l() throw(...); +/// \endcode +/// functionDecl(hasDynamicExceptionSpec()) and +/// functionProtoType(hasDynamicExceptionSpec()) +/// match the declarations of j, k, and l, but not f, g, h, or i. +AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + FunctionProtoType)) { + if (const FunctionProtoType *FnTy = internal::getFunctionProtoType(Node)) + return FnTy->hasDynamicExceptionSpec(); + return false; +} + /// \brief Matches functions that have a non-throwing exception specification. /// /// Given: @@ -2952,10 +3360,12 @@ AST_MATCHER(FunctionDecl, isDeleted) { /// void i() throw(int); /// void j() noexcept(false); /// \endcode -/// functionDecl(isNoThrow()) -/// matches the declarations of g, and h, but not f, i or j. -AST_MATCHER(FunctionDecl, isNoThrow) { - const auto *FnTy = Node.getType()->getAs(); +/// functionDecl(isNoThrow()) and functionProtoType(isNoThrow()) +/// match the declarations of g, and h, but not f, i or j. +AST_POLYMORPHIC_MATCHER(isNoThrow, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + FunctionProtoType)) { + const FunctionProtoType *FnTy = internal::getFunctionProtoType(Node); // If the function does not have a prototype, then it is assumed to be a // throwing function (as it would if the function did not have any exception @@ -2967,7 +3377,7 @@ AST_MATCHER(FunctionDecl, isNoThrow) { if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType())) return true; - return FnTy->isNothrow(Node.getASTContext()); + return FnTy->isNothrow(Finder->getASTContext()); } /// \brief Matches constexpr variable and function declarations. @@ -2988,17 +3398,17 @@ AST_POLYMORPHIC_MATCHER(isConstexpr, } /// \brief Matches the condition expression of an if statement, for loop, -/// or conditional operator. +/// switch statement or conditional operator. /// /// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true)))) /// \code /// if (true) {} /// \endcode -AST_POLYMORPHIC_MATCHER_P(hasCondition, - AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, - WhileStmt, DoStmt, - ConditionalOperator), - internal::Matcher, InnerMatcher) { +AST_POLYMORPHIC_MATCHER_P( + hasCondition, + AST_POLYMORPHIC_SUPPORTED_TYPES(IfStmt, ForStmt, WhileStmt, DoStmt, + SwitchStmt, AbstractConditionalOperator), + internal::Matcher, InnerMatcher) { const Expr *const Condition = Node.getCond(); return (Condition != nullptr && InnerMatcher.matches(*Condition, Finder, Builder)); @@ -3114,8 +3524,8 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, return false; } -/// \brief Matches a 'for', 'while', or 'do while' statement that has -/// a given body. +/// \brief Matches a 'for', 'while', 'do while' statement or a function +/// definition that has a given body. /// /// Given /// \code @@ -3128,15 +3538,16 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, AST_POLYMORPHIC_MATCHER_P(hasBody, AST_POLYMORPHIC_SUPPORTED_TYPES(DoStmt, ForStmt, WhileStmt, - CXXForRangeStmt), + CXXForRangeStmt, + FunctionDecl), internal::Matcher, InnerMatcher) { - const Stmt *const Statement = Node.getBody(); + const Stmt *const Statement = internal::GetBodyMatcher::get(Node); return (Statement != nullptr && InnerMatcher.matches(*Statement, Finder, Builder)); } /// \brief Matches compound statements where at least one substatement matches -/// a given matcher. +/// a given matcher. Also matches StmtExprs that have CompoundStmt as children. /// /// Given /// \code @@ -3146,10 +3557,13 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, /// matches '{ {}; 1+2; }' /// with compoundStmt() /// matching '{}' -AST_MATCHER_P(CompoundStmt, hasAnySubstatement, - internal::Matcher, InnerMatcher) { - return matchesFirstInPointerRange(InnerMatcher, Node.body_begin(), - Node.body_end(), Finder, Builder); +AST_POLYMORPHIC_MATCHER_P(hasAnySubstatement, + AST_POLYMORPHIC_SUPPORTED_TYPES(CompoundStmt, + StmtExpr), + internal::Matcher, InnerMatcher) { + const CompoundStmt *CS = CompoundStmtMatcher::get(Node); + return CS && matchesFirstInPointerRange(InnerMatcher, CS->body_begin(), + CS->body_end(), Finder, Builder); } /// \brief Checks that a compound statement contains a specific number of @@ -3248,21 +3662,43 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, InnerMatcher.matches(*Operand, Finder, Builder)); } -/// \brief Matches if the cast's source expression matches the given matcher. +/// \brief Matches if the cast's source expression +/// or opaque value's source expression matches the given matcher. /// -/// Example: matches "a string" (matcher = -/// hasSourceExpression(cxxConstructExpr())) +/// Example 1: matches "a string" +/// (matcher = castExpr(hasSourceExpression(cxxConstructExpr()))) /// \code /// class URL { URL(string); }; /// URL url = "a string"; /// \endcode -AST_MATCHER_P(CastExpr, hasSourceExpression, - internal::Matcher, InnerMatcher) { - const Expr* const SubExpression = Node.getSubExpr(); +/// +/// Example 2: matches 'b' (matcher = +/// opaqueValueExpr(hasSourceExpression(implicitCastExpr(declRefExpr()))) +/// \code +/// int a = b ?: 1; +/// \endcode + +AST_POLYMORPHIC_MATCHER_P(hasSourceExpression, + AST_POLYMORPHIC_SUPPORTED_TYPES(CastExpr, + OpaqueValueExpr), + internal::Matcher, InnerMatcher) { + const Expr *const SubExpression = + internal::GetSourceExpressionMatcher::get(Node); return (SubExpression != nullptr && InnerMatcher.matches(*SubExpression, Finder, Builder)); } +/// \brief Matches casts that has a given cast kind. +/// +/// Example: matches the implicit cast around \c 0 +/// (matcher = castExpr(hasCastKind(CK_NullToPointer))) +/// \code +/// int *p = 0; +/// \endcode +AST_MATCHER_P(CastExpr, hasCastKind, CastKind, Kind) { + return Node.getCastKind() == Kind; +} + /// \brief Matches casts whose destination type matches a given matcher. /// /// (Note: Clang's AST refers to other conversions as "casts" too, and calls @@ -3320,24 +3756,31 @@ AST_MATCHER(RecordDecl, isClass) { /// \brief Matches the true branch expression of a conditional operator. /// -/// Example matches a +/// Example 1 (conditional ternary operator): matches a /// \code /// condition ? a : b /// \endcode -AST_MATCHER_P(ConditionalOperator, hasTrueExpression, +/// +/// Example 2 (conditional binary operator): matches opaqueValueExpr(condition) +/// \code +/// condition ?: b +/// \endcode +AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression, internal::Matcher, InnerMatcher) { const Expr *Expression = Node.getTrueExpr(); return (Expression != nullptr && InnerMatcher.matches(*Expression, Finder, Builder)); } -/// \brief Matches the false branch expression of a conditional operator. +/// \brief Matches the false branch expression of a conditional operator +/// (binary or ternary). /// /// Example matches b /// \code /// condition ? a : b +/// condition ?: b /// \endcode -AST_MATCHER_P(ConditionalOperator, hasFalseExpression, +AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression, internal::Matcher, InnerMatcher) { const Expr *Expression = Node.getFalseExpr(); return (Expression != nullptr && @@ -3401,6 +3844,47 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, InnerMatcher.matches(*Parent, Finder, Builder)); } +/// \brief Matches each method overriden by the given method. This matcher may +/// produce multiple matches. +/// +/// Given +/// \code +/// class A { virtual void f(); }; +/// class B : public A { void f(); }; +/// class C : public B { void f(); }; +/// \endcode +/// cxxMethodDecl(ofClass(hasName("C")), +/// forEachOverridden(cxxMethodDecl().bind("b"))).bind("d") +/// matches once, with "b" binding "A::f" and "d" binding "C::f" (Note +/// that B::f is not overridden by C::f). +/// +/// The check can produce multiple matches in case of multiple inheritance, e.g. +/// \code +/// class A1 { virtual void f(); }; +/// class A2 { virtual void f(); }; +/// class C : public A1, public A2 { void f(); }; +/// \endcode +/// cxxMethodDecl(ofClass(hasName("C")), +/// forEachOverridden(cxxMethodDecl().bind("b"))).bind("d") +/// matches twice, once with "b" binding "A1::f" and "d" binding "C::f", and +/// once with "b" binding "A2::f" and "d" binding "C::f". +AST_MATCHER_P(CXXMethodDecl, forEachOverridden, + internal::Matcher, InnerMatcher) { + BoundNodesTreeBuilder Result; + bool Matched = false; + for (const auto *Overridden : Node.overridden_methods()) { + BoundNodesTreeBuilder OverriddenBuilder(*Builder); + const bool OverriddenMatched = + InnerMatcher.matches(*Overridden, Finder, &OverriddenBuilder); + if (OverriddenMatched) { + Matched = true; + Result.addMatch(OverriddenBuilder); + } + } + *Builder = std::move(Result); + return Matched; +} + /// \brief Matches if the given method declaration is virtual. /// /// Given @@ -3415,6 +3899,24 @@ AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } +/// \brief Matches if the given method declaration has an explicit "virtual". +/// +/// Given +/// \code +/// class A { +/// public: +/// virtual void x(); +/// }; +/// class B : public A { +/// public: +/// void x(); +/// }; +/// \endcode +/// matches A::x but not B::x +AST_MATCHER(CXXMethodDecl, isVirtualAsWritten) { + return Node.isVirtualAsWritten(); +} + /// \brief Matches if the given method or class declaration is final. /// /// Given: @@ -3482,6 +3984,23 @@ AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) { return Node.isCopyAssignmentOperator(); } +/// \brief Matches if the given method declaration declares a move assignment +/// operator. +/// +/// Given +/// \code +/// struct A { +/// A &operator=(const A &); +/// A &operator=(A &&); +/// }; +/// \endcode +/// +/// cxxMethodDecl(isMoveAssignmentOperator()) matches the second method but not +/// the first one. +AST_MATCHER(CXXMethodDecl, isMoveAssignmentOperator) { + return Node.isMoveAssignmentOperator(); +} + /// \brief Matches if the given method declaration overrides another method. /// /// Given @@ -3500,6 +4019,21 @@ AST_MATCHER(CXXMethodDecl, isOverride) { return Node.size_overridden_methods() > 0 || Node.hasAttr(); } +/// \brief Matches method declarations that are user-provided. +/// +/// Given +/// \code +/// struct S { +/// S(); // #1 +/// S(const S &) = default; // #2 +/// S(S &&) = delete; // #3 +/// }; +/// \endcode +/// cxxConstructorDecl(isUserProvided()) will match #1, but not #2 or #3. +AST_MATCHER(CXXMethodDecl, isUserProvided) { + return Node.isUserProvided(); +} + /// \brief Matches member expressions that are called with '->' as opposed /// to '.'. /// @@ -3533,6 +4067,34 @@ AST_MATCHER(QualType, isInteger) { return Node->isIntegerType(); } +/// \brief Matches QualType nodes that are of unsigned integer type. +/// +/// Given +/// \code +/// void a(int); +/// void b(unsigned long); +/// void c(double); +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isInteger()))) +/// matches "b(unsigned long)", but not "a(int)" and "c(double)". +AST_MATCHER(QualType, isUnsignedInteger) { + return Node->isUnsignedIntegerType(); +} + +/// \brief Matches QualType nodes that are of signed integer type. +/// +/// Given +/// \code +/// void a(int); +/// void b(unsigned long); +/// void c(double); +/// \endcode +/// functionDecl(hasAnyParameter(hasType(isInteger()))) +/// matches "a(int)", but not "b(unsigned long)" and "c(double)". +AST_MATCHER(QualType, isSignedInteger) { + return Node->isSignedIntegerType(); +} + /// \brief Matches QualType nodes that are of character type. /// /// Given @@ -3547,6 +4109,26 @@ AST_MATCHER(QualType, isAnyCharacter) { return Node->isAnyCharacterType(); } +/// \brief Matches QualType nodes that are of any pointer type; this includes +/// the Objective-C object pointer type, which is different despite being +/// syntactically similar. +/// +/// Given +/// \code +/// int *i = nullptr; +/// +/// @interface Foo +/// @end +/// Foo *f; +/// +/// int j; +/// \endcode +/// varDecl(hasType(isAnyPointer())) +/// matches "int *i" and "Foo *f", but not "int j". +AST_MATCHER(QualType, isAnyPointer) { + return Node->isAnyPointerType(); +} + /// \brief Matches QualType nodes that are const-qualified, i.e., that /// include "top-level" const. /// @@ -3822,6 +4404,19 @@ AST_TYPE_MATCHER(ArrayType, arrayType); /// matches "_Complex float f" AST_TYPE_MATCHER(ComplexType, complexType); +/// \brief Matches any real floating-point type (float, double, long double). +/// +/// Given +/// \code +/// int i; +/// float f; +/// \endcode +/// realFloatingPointType() +/// matches "float f" but not "int i" +AST_MATCHER(Type, realFloatingPointType) { + return Node.isRealFloatingType(); +} + /// \brief Matches arrays and C99 complex types that have a specific element /// type. /// @@ -3853,18 +4448,26 @@ AST_TYPELOC_TRAVERSE_MATCHER(hasElementType, getElement, /// matches "int a[2]" AST_TYPE_MATCHER(ConstantArrayType, constantArrayType); -/// \brief Matches \c ConstantArrayType nodes that have the specified size. +/// \brief Matches nodes that have the specified size. /// /// Given /// \code /// int a[42]; /// int b[2 * 21]; /// int c[41], d[43]; +/// char *s = "abcd"; +/// wchar_t *ws = L"abcd"; +/// char *w = "a"; /// \endcode /// constantArrayType(hasSize(42)) /// matches "int a[42]" and "int b[2 * 21]" -AST_MATCHER_P(ConstantArrayType, hasSize, unsigned, N) { - return Node.getSize() == N; +/// stringLiteral(hasSize(4)) +/// matches "abcd", L"abcd" +AST_POLYMORPHIC_MATCHER_P(hasSize, + AST_POLYMORPHIC_SUPPORTED_TYPES(ConstantArrayType, + StringLiteral), + unsigned, N) { + return internal::HasSizeMatcher::hasSize(Node, N); } /// \brief Matches C++ arrays whose size is a value-dependent expression. @@ -3988,6 +4591,18 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, /// matches "int (*f)(int)" and the type of "g". AST_TYPE_MATCHER(FunctionType, functionType); +/// \brief Matches \c FunctionProtoType nodes. +/// +/// Given +/// \code +/// int (*f)(int); +/// void g(); +/// \endcode +/// functionProtoType() +/// matches "int (*f)(int)" and the type of "g" in C++ mode. +/// In C mode, "g" is not matched because it does not contain a prototype. +AST_TYPE_MATCHER(FunctionProtoType, functionProtoType); + /// \brief Matches \c ParenType nodes. /// /// Given @@ -4143,6 +4758,21 @@ AST_TYPELOC_TRAVERSE_MATCHER(pointee, getPointee, /// matches "typedef int X" AST_TYPE_MATCHER(TypedefType, typedefType); +/// \brief Matches enum types. +/// +/// Given +/// \code +/// enum C { Green }; +/// enum class S { Red }; +/// +/// C c; +/// S s; +/// \endcode +// +/// \c enumType() matches the type of the variable declarations of both \c c and +/// \c s. +AST_TYPE_MATCHER(EnumType, enumType); + /// \brief Matches template specialization types. /// /// Given @@ -4563,6 +5193,23 @@ AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) { return Node.isDefaultConstructor(); } +/// \brief Matches constructors that delegate to another constructor. +/// +/// Given +/// \code +/// struct S { +/// S(); // #1 +/// S(int) {} // #2 +/// S(S &&) : S() {} // #3 +/// }; +/// S::S() : S(0) {} // #4 +/// \endcode +/// cxxConstructorDecl(isDelegatingConstructor()) will match #3 and #4, but not +/// #1 or #2. +AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) { + return Node.isDelegatingConstructor(); +} + /// \brief Matches constructor and conversion declarations that are marked with /// the explicit keyword. /// @@ -4655,6 +5302,24 @@ AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) { return false; } +/// \brief Matches the return value expression of a return statement +/// +/// Given +/// \code +/// return a + b; +/// \endcode +/// hasReturnValue(binaryOperator()) +/// matches 'return a + b' +/// with binaryOperator() +/// matching 'a + b' +AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher, + InnerMatcher) { + if (const auto *RetValue = Node.getRetValue()) + return InnerMatcher.matches(*RetValue, Finder, Builder); + return false; +} + + /// \brief Matches CUDA kernel call expression. /// /// Example matches, @@ -4665,6 +5330,66 @@ const internal::VariadicDynCastAllOfMatcher< Stmt, CUDAKernelCallExpr> cudaKernelCallExpr; + +/// \brief Matches expressions that resolve to a null pointer constant, such as +/// GNU's __null, C++11's nullptr, or C's NULL macro. +/// +/// Given: +/// \code +/// void *v1 = NULL; +/// void *v2 = nullptr; +/// void *v3 = __null; // GNU extension +/// char *cp = (char *)0; +/// int *ip = 0; +/// int i = 0; +/// \endcode +/// expr(nullPointerConstant()) +/// matches the initializer for v1, v2, v3, cp, and ip. Does not match the +/// initializer for i. +AST_MATCHER_FUNCTION(internal::Matcher, nullPointerConstant) { + return anyOf( + gnuNullExpr(), cxxNullPtrLiteralExpr(), + integerLiteral(equals(0), hasParent(expr(hasType(pointerType()))))); +} + +/// \brief Matches declaration of the function the statemenet belongs to +/// +/// Given: +/// \code +/// F& operator=(const F& o) { +/// std::copy_if(o.begin(), o.end(), begin(), [](V v) { return v > 0; }); +/// return *this; +/// } +/// \endcode +/// returnStmt(forFunction(hasName("operator="))) +/// matches 'return *this' +/// but does match 'return > 0' +AST_MATCHER_P(Stmt, forFunction, internal::Matcher, + InnerMatcher) { + const auto &Parents = Finder->getASTContext().getParents(Node); + + llvm::SmallVector Stack(Parents.begin(), + Parents.end()); + while(!Stack.empty()) { + const auto &CurNode = Stack.back(); + Stack.pop_back(); + if(const auto *FuncDeclNode = CurNode.get()) { + if(InnerMatcher.matches(*FuncDeclNode, Finder, Builder)) { + return true; + } + } else if(const auto *LambdaExprNode = CurNode.get()) { + if(InnerMatcher.matches(*LambdaExprNode->getCallOperator(), + Finder, Builder)) { + return true; + } + } else { + for(const auto &Parent: Finder->getASTContext().getParents(CurNode)) + Stack.push_back(Parent); + } + } + return false; +} + } // end namespace ast_matchers } // end namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 1d1d7952c1667..c2c01fbd78ea3 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -46,8 +46,9 @@ #include "clang/AST/StmtCXX.h" #include "clang/AST/StmtObjC.h" #include "clang/AST/Type.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" -#include "llvm/ADT/VariadicFunction.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/ManagedStatic.h" #include #include @@ -60,6 +61,62 @@ class BoundNodes; namespace internal { +/// \brief Variadic function object. +/// +/// Most of the functions below that use VariadicFunction could be implemented +/// using plain C++11 variadic functions, but the function object allows us to +/// capture it on the dynamic matcher registry. +template )> +struct VariadicFunction { + ResultT operator()() const { return Func(None); } + + template + ResultT operator()(const ArgT &Arg1, const ArgsT &... Args) const { + return Execute(Arg1, static_cast(Args)...); + } + + // We also allow calls with an already created array, in case the caller + // already had it. + ResultT operator()(ArrayRef Args) const { + SmallVector InnerArgs; + for (const ArgT &Arg : Args) + InnerArgs.push_back(&Arg); + return Func(InnerArgs); + } + +private: + // Trampoline function to allow for implicit conversions to take place + // before we make the array. + template ResultT Execute(const ArgsT &... Args) const { + const ArgT *const ArgsArray[] = {&Args...}; + return Func(ArrayRef(ArgsArray, sizeof...(ArgsT))); + } +}; + +/// \brief Unifies obtaining the underlying type of a regular node through +/// `getType` and a TypedefNameDecl node through `getUnderlyingType`. +inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); } + +inline QualType getUnderlyingType(const ValueDecl &Node) { + return Node.getType(); +} + +inline QualType getUnderlyingType(const TypedefNameDecl &Node) { + return Node.getUnderlyingType(); +} + +/// \brief Unifies obtaining the FunctionProtoType pointer from both +/// FunctionProtoType and FunctionDecl nodes.. +inline const FunctionProtoType * +getFunctionProtoType(const FunctionProtoType &Node) { + return &Node; +} + +inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) { + return Node.getType()->getAs(); +} + /// \brief Internal version of BoundNodes. Holds all the bound nodes. class BoundNodesMap { public: @@ -420,7 +477,7 @@ public: template Matcher(const Matcher &Other, typename std::enable_if::value && - !std::is_same::value>::type * = 0) + !std::is_same::value>::type * = nullptr) : Implementation(restrictMatcher(Other.Implementation)) { assert(Implementation.getSupportedKind().isSame( ast_type_traits::ASTNodeKind::getFromNodeKind())); @@ -433,7 +490,7 @@ public: Matcher(const Matcher &Other, typename std::enable_if< std::is_same::value && - std::is_same::value>::type* = 0) + std::is_same::value>::type* = nullptr) : Implementation(new TypeToQualType(Other)) {} /// \brief Convert \c this into a \c Matcher by applying dyn_cast<> to the @@ -558,32 +615,21 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, return false; } -// Metafunction to determine if type T has a member called -// getDecl. -#if defined(_MSC_VER) && !defined(__clang__) -// For MSVC, we use a weird nonstandard __if_exists statement, as it -// is not standards-conformant enough to properly compile the standard -// code below. (At least up through MSVC 2015 require this workaround) -template struct has_getDecl { - __if_exists(T::getDecl) { - enum { value = 1 }; - } - __if_not_exists(T::getDecl) { - enum { value = 0 }; - } +// Metafunction to determine if type T has a member called getDecl. +template +class has_getDecl { + typedef char yes[1]; + typedef char no[2]; + + template + static yes& test(Inner *I, decltype(I->getDecl()) * = nullptr); + + template + static no& test(...); + +public: + static const bool value = sizeof(test(nullptr)) == sizeof(yes); }; -#else -// There is a default template inheriting from "false_type". Then, a -// partial specialization inherits from "true_type". However, this -// specialization will only exist when the call to getDecl() isn't an -// error -- it vanishes by SFINAE when the member doesn't exist. -template struct type_sink_to_void { typedef void type; }; -template struct has_getDecl : std::false_type {}; -template -struct has_getDecl< - T, typename type_sink_to_void().getDecl())>::type> - : std::true_type {}; -#endif /// \brief Matches overloaded operators with a specific name. /// @@ -626,10 +672,10 @@ private: /// \brief Matches named declarations with a specific name. /// -/// See \c hasName() in ASTMatchers.h for details. +/// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details. class HasNameMatcher : public SingleNodeMatcherInterface { public: - explicit HasNameMatcher(StringRef Name); + explicit HasNameMatcher(std::vector Names); bool matchesNode(const NamedDecl &Node) const override; @@ -640,17 +686,29 @@ class HasNameMatcher : public SingleNodeMatcherInterface { /// matches. bool matchesNodeUnqualified(const NamedDecl &Node) const; + /// \brief Full match routine + /// + /// Fast implementation for the simple case of a named declaration at + /// namespace or RecordDecl scope. + /// It is slower than matchesNodeUnqualified, but faster than + /// matchesNodeFullSlow. + bool matchesNodeFullFast(const NamedDecl &Node) const; + /// \brief Full match routine /// /// It generates the fully qualified name of the declaration (which is /// expensive) before trying to match. /// It is slower but simple and works on all cases. - bool matchesNodeFull(const NamedDecl &Node) const; + bool matchesNodeFullSlow(const NamedDecl &Node) const; const bool UseUnqualifiedMatch; - const std::string Name; + const std::vector Names; }; +/// \brief Trampoline function to use VariadicFunction<> to construct a +/// HasNameMatcher. +Matcher hasAnyNameFunc(ArrayRef NameRefs); + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but @@ -737,6 +795,14 @@ private: return matchesDecl(Node.getMemberDecl(), Finder, Builder); } + /// \brief Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns + /// whether the inner matcher matches on it. + bool matchesSpecialized(const AddrLabelExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getLabel(), Finder, Builder); + } + /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node /// is \c NULL. bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, @@ -942,8 +1008,8 @@ typedef TypeList HasDeclarationSupportedTypes; @@ -1110,8 +1176,6 @@ public: /// ChildT must be an AST base type. template class HasMatcher : public WrapperMatcherInterface { - static_assert(IsBaseType::value, - "has only accepts base type matcher"); public: explicit HasMatcher(const Matcher &ChildMatcher) @@ -1119,10 +1183,9 @@ public: bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const override { - return Finder->matchesChildOf( - Node, this->InnerMatcher, Builder, - ASTMatchFinder::TK_IgnoreImplicitCastsAndParentheses, - ASTMatchFinder::BK_First); + return Finder->matchesChildOf(Node, this->InnerMatcher, Builder, + ASTMatchFinder::TK_AsIs, + ASTMatchFinder::BK_First); } }; @@ -1385,9 +1448,8 @@ inline bool ValueEqualsMatcher::matchesNode( /// casted to CXXRecordDecl and all given matchers match. template class VariadicDynCastAllOfMatcher - : public llvm::VariadicFunction< - BindableMatcher, Matcher, - makeDynCastAllOfComposite > { + : public VariadicFunction, Matcher, + makeDynCastAllOfComposite> { public: VariadicDynCastAllOfMatcher() {} }; @@ -1403,9 +1465,9 @@ public: /// \c Matcher. /// The returned matcher matches if all given matchers match. template -class VariadicAllOfMatcher : public llvm::VariadicFunction< - BindableMatcher, Matcher, - makeAllOfComposite > { +class VariadicAllOfMatcher + : public VariadicFunction, Matcher, + makeAllOfComposite> { public: VariadicAllOfMatcher() {} }; @@ -1526,8 +1588,8 @@ public: new MatcherImpl(InnerMatcher, Getter::value())); } - struct Func : public llvm::VariadicFunction, - &Self::create> { + struct Func + : public VariadicFunction, &Self::create> { Func() {} }; @@ -1584,8 +1646,60 @@ struct NotEqualsBoundNodePredicate { ast_type_traits::DynTypedNode Node; }; +template +struct GetBodyMatcher { + static const Stmt *get(const Ty &Node) { + return Node.getBody(); + } +}; + +template <> +inline const Stmt *GetBodyMatcher::get(const FunctionDecl &Node) { + return Node.doesThisDeclarationHaveABody() ? Node.getBody() : nullptr; +} + +template +struct HasSizeMatcher { + static bool hasSize(const Ty &Node, unsigned int N) { + return Node.getSize() == N; + } +}; + +template <> +inline bool HasSizeMatcher::hasSize( + const StringLiteral &Node, unsigned int N) { + return Node.getLength() == N; +} + +template +struct GetSourceExpressionMatcher { + static const Expr *get(const Ty &Node) { + return Node.getSubExpr(); + } +}; + +template <> +inline const Expr *GetSourceExpressionMatcher::get( + const OpaqueValueExpr &Node) { + return Node.getSourceExpr(); +} + +template +struct CompoundStmtMatcher { + static const CompoundStmt *get(const Ty &Node) { + return &Node; + } +}; + +template <> +inline const CompoundStmt * +CompoundStmtMatcher::get(const StmtExpr &Node) { + return Node.getSubStmt(); +} + + } // end namespace internal } // end namespace ast_matchers } // end namespace clang -#endif +#endif // LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 4471311a3390a..74803a295d712 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -210,11 +210,16 @@ public: unsigned getLength() const { return EndScanList ? EndScanList - Position : 1; } + void setEndScanList(const char *pos) { EndScanList = pos; } bool isIntArg() const { return (kind >= IntArgBeg && kind <= IntArgEnd) || kind == FreeBSDrArg || kind == FreeBSDyArg; } bool isUIntArg() const { return kind >= UIntArgBeg && kind <= UIntArgEnd; } bool isAnyIntArg() const { return kind >= IntArgBeg && kind <= UIntArgEnd; } + bool isDoubleArg() const { + return kind >= DoubleArgBeg && kind <= DoubleArgEnd; + } + const char *toString() const; bool isPrintfKind() const { return IsPrintf; } @@ -413,11 +418,6 @@ public: bool isObjCArg() const { return kind >= ObjCBeg && kind <= ObjCEnd; } bool isDoubleArg() const { return kind >= DoubleArgBeg && kind <= DoubleArgEnd; } - unsigned getLength() const { - // Conversion specifiers currently only are represented by - // single characters, but we be flexible. - return 1; - } static bool classof(const analyze_format_string::ConversionSpecifier *CS) { return CS->isPrintfKind(); @@ -546,8 +546,6 @@ public: ScanfConversionSpecifier(const char *pos, Kind k) : ConversionSpecifier(false, pos, k) {} - void setEndScanList(const char *pos) { EndScanList = pos; } - static bool classof(const analyze_format_string::ConversionSpecifier *CS) { return !CS->isPrintfKind(); } diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h index 4d3402f8c00b1..6ea93653b91aa 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h @@ -58,18 +58,15 @@ private: llvm::BumpPtrAllocator *Allocator; }; - } // end namespace til } // end namespace threadSafety } // end namespace clang - inline void *operator new(size_t Sz, clang::threadSafety::til::MemRegionRef &R) { return R.allocate(Sz); } - namespace clang { namespace threadSafety { @@ -80,7 +77,6 @@ using clang::SourceLocation; namespace til { - // A simple fixed size array class that does not manage its own memory, // suitable for use with bump pointer allocation. template class SimpleArray { @@ -117,7 +113,6 @@ public: Data = A.allocateT(Ncp); Capacity = Ncp; memcpy(Data, Odata, sizeof(T) * Size); - return; } // Reserve space for at least N more items. @@ -221,10 +216,8 @@ private: size_t Capacity; }; - } // end namespace til - // A copy on write vector. // The vector can be in one of three states: // * invalid -- no operations are permitted. @@ -346,13 +339,11 @@ private: VectorData *Data; }; - inline std::ostream& operator<<(std::ostream& ss, const StringRef str) { return ss.write(str.data(), str.size()); } - } // end namespace threadSafety } // end namespace clang -#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H +#endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 931190e43a668..4324a0352e3a1 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -201,6 +201,10 @@ public: } return static_cast(data); } + + /// Returns true if the root namespace of the given declaration is the 'std' + /// C++ namespace. + static bool isInStdNamespace(const Decl *D); private: ManagedAnalysis *&getAnalysisImpl(const void* tag); diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 6d816fd733ec5..5045194ef8646 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -595,6 +595,13 @@ public: return static_cast(getData2()); } + /// Returns the entry block in the CFG for the entered function. + const CFGBlock *getEntry() const { + const StackFrameContext *CalleeCtx = getCalleeContext(); + const CFG *CalleeCFG = CalleeCtx->getCFG(); + return &(CalleeCFG->getEntry()); + } + private: friend class ProgramPoint; CallEnter() {} diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 8dd75660c6728..63df61bedbc60 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -25,7 +25,7 @@ namespace LangAS { /// This uses a high starting offset so as not to conflict with any address /// space used by a target. enum ID { - Offset = 0xFFFF00, + Offset = 0x7FFF00, opencl_global = Offset, opencl_local, diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index d5ba722616444..7da1efe5ff405 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -82,6 +82,8 @@ def NormalVar : SubsetSubjectgetKind() != Decl::ImplicitParam && S->getKind() != Decl::ParmVar && S->getKind() != Decl::NonTypeTemplateParm}]>; +def NonParmVar : SubsetSubjectgetKind() != Decl::ParmVar}]>; def NonBitField : SubsetSubjectisBitField()}]>; @@ -239,6 +241,8 @@ def MicrosoftExt : LangOpt<"MicrosoftExt">; def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; def COnly : LangOpt<"CPlusPlus", 1>; +def OpenCL : LangOpt<"OpenCL">; +def RenderScript : LangOpt<"RenderScript">; // Defines targets for target-specific attributes. The list of strings should // specify architectures for which the target applies, based off the ArchType @@ -252,6 +256,7 @@ def TargetARM : TargetArch<["arm", "thumb"]>; def TargetMips : TargetArch<["mips", "mipsel"]>; def TargetMSP430 : TargetArch<["msp430"]>; def TargetX86 : TargetArch<["x86"]>; +def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb"]> { let OSes = ["Win32"]; } @@ -310,6 +315,9 @@ class TypeAttr : Attr { let ASTNode = 0; } +/// A stmt attribute is not processed on a declaration or a type. +class StmtAttr : Attr; + /// An inheritable attribute is inherited by later redeclarations. class InheritableAttr : Attr; @@ -337,6 +345,11 @@ class TargetSpecificAttr { /// redeclarations, even when it's written on a parameter. class InheritableParamAttr : InheritableAttr; +/// An attribute which changes the ABI rules for a specific parameter. +class ParameterABIAttr : InheritableParamAttr { + let Subjects = SubjectList<[ParmVar]>; +} + /// An ignored attribute, which we parse but discard with no checking. class IgnoredAttr : Attr { let Ignored = 1; @@ -349,6 +362,14 @@ class IgnoredAttr : Attr { // Attributes begin here // +def AbiTag : Attr { + let Spellings = [GCC<"abi_tag">]; + let Args = [VariadicStringArgument<"Tags">]; + let Subjects = SubjectList<[Struct, Var, Function, Namespace], ErrorDiag, + "ExpectedStructClassVariableFunctionOrInlineNamespace">; + let Documentation = [AbiTagsDocs]; +} + def AddressSpace : TypeAttr { let Spellings = [GNU<"address_space">]; let Args = [IntArgument<"AddressSpace">]; @@ -407,6 +428,22 @@ def AlwaysInline : InheritableAttr { let Documentation = [Undocumented]; } +def XRayInstrument : InheritableAttr { + let Spellings = [GNU<"xray_always_instrument">, + CXX11<"clang", "xray_always_instrument">, + GNU<"xray_never_instrument">, + CXX11<"clang", "xray_never_instrument">]; + let Subjects = SubjectList<[CXXMethod, ObjCMethod, Function], WarnDiag, + "ExpectedFunctionOrMethod">; + let Accessors = [Accessor<"alwaysXRayInstrument", + [GNU<"xray_always_instrument">, + CXX11<"clang", "xray_always_instrument">]>, + Accessor<"neverXRayInstrument", + [GNU<"xray_never_instrument">, + CXX11<"clang", "xray_never_instrument">]>]; + let Documentation = [XRayDocs]; +} + def TLSModel : InheritableAttr { let Spellings = [GCC<"tls_model">]; let Subjects = SubjectList<[TLSVar], ErrorDiag, "ExpectedTLSVar">; @@ -426,8 +463,8 @@ def Annotate : InheritableParamAttr { } def ARMInterrupt : InheritableAttr, TargetSpecificAttr { - // NOTE: If you add any additional spellings, MSP430Interrupt's and - // MipsInterrupt's spellings must match. + // NOTE: If you add any additional spellings, MSP430Interrupt's, + // MipsInterrupt's and AnyX86Interrupt's spellings must match. let Spellings = [GNU<"interrupt">]; let Args = [EnumArgument<"Interrupt", "InterruptType", ["IRQ", "FIQ", "SWI", "ABORT", "UNDEF", ""], @@ -449,17 +486,18 @@ def Availability : InheritableAttr { let Spellings = [GNU<"availability">]; let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, VersionArgument<"deprecated">, VersionArgument<"obsoleted">, - BoolArgument<"unavailable">, StringArgument<"message">]; + BoolArgument<"unavailable">, StringArgument<"message">, + BoolArgument<"strict">, StringArgument<"replacement">]; let AdditionalMembers = [{static llvm::StringRef getPrettyPlatformName(llvm::StringRef Platform) { return llvm::StringSwitch(Platform) .Case("android", "Android") .Case("ios", "iOS") - .Case("macosx", "OS X") + .Case("macos", "macOS") .Case("tvos", "tvOS") .Case("watchos", "watchOS") .Case("ios_app_extension", "iOS (App Extension)") - .Case("macosx_app_extension", "OS X (App Extension)") + .Case("macos_app_extension", "macOS (App Extension)") .Case("tvos_app_extension", "tvOS (App Extension)") .Case("watchos_app_extension", "watchOS (App Extension)") .Default(llvm::StringRef()); @@ -654,20 +692,27 @@ def OpenCLKernel : InheritableAttr { let Documentation = [Undocumented]; } +def OpenCLUnrollHint : InheritableAttr { + let Spellings = [GNU<"opencl_unroll_hint">]; + let Args = [UnsignedArgument<"UnrollHint">]; + let Documentation = [OpenCLUnrollHintDocs]; +} + // This attribute is both a type attribute, and a declaration attribute (for // parameter variables). -def OpenCLImageAccess : Attr { +def OpenCLAccess : Attr { let Spellings = [Keyword<"__read_only">, Keyword<"read_only">, Keyword<"__write_only">, Keyword<"write_only">, Keyword<"__read_write">, Keyword<"read_write">]; - let Subjects = SubjectList<[ParmVar], ErrorDiag>; + let Subjects = SubjectList<[ParmVar, TypedefName], ErrorDiag, + "ExpectedParameterOrTypedef">; let Accessors = [Accessor<"isReadOnly", [Keyword<"__read_only">, Keyword<"read_only">]>, Accessor<"isReadWrite", [Keyword<"__read_write">, Keyword<"read_write">]>, Accessor<"isWriteOnly", [Keyword<"__write_only">, Keyword<"write_only">]>]; - let Documentation = [Undocumented]; + let Documentation = [OpenCLAccessDocs]; } def OpenCLPrivateAddressSpace : TypeAttr { @@ -695,11 +740,29 @@ def OpenCLGenericAddressSpace : TypeAttr { let Documentation = [OpenCLAddressSpaceGenericDocs]; } +def OpenCLNoSVM : Attr { + let Spellings = [GNU<"nosvm">]; + let Subjects = SubjectList<[Var]>; + let Documentation = [OpenCLNoSVMDocs]; + let LangOpts = [OpenCL]; + let ASTNode = 0; +} + +def RenderScriptKernel : Attr { + let Spellings = [GNU<"kernel">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [RenderScriptKernelAttributeDocs]; + let LangOpts = [RenderScript]; +} + def Deprecated : InheritableAttr { let Spellings = [GCC<"deprecated">, Declspec<"deprecated">, CXX11<"","deprecated", 201309>]; - let Args = [StringArgument<"Message", 1>]; - let Documentation = [Undocumented]; + let Args = [StringArgument<"Message", 1>, + // An optional string argument that enables us to provide a + // Fix-It. + StringArgument<"Replacement", 1>]; + let Documentation = [DeprecatedDocs]; } def Destructor : InheritableAttr { @@ -709,6 +772,12 @@ def Destructor : InheritableAttr { let Documentation = [Undocumented]; } +def EmptyBases : InheritableAttr, TargetSpecificAttr { + let Spellings = [Declspec<"empty_bases">]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [EmptyBasesDocs]; +} + def EnableIf : InheritableAttr { let Spellings = [GNU<"enable_if">]; let Subjects = SubjectList<[Function]>; @@ -725,8 +794,9 @@ def ExtVectorType : Attr { let Documentation = [Undocumented]; } -def FallThrough : Attr { - let Spellings = [CXX11<"clang", "fallthrough">]; +def FallThrough : StmtAttr { + let Spellings = [CXX11<"", "fallthrough", 201603>, + CXX11<"clang", "fallthrough">]; // let Subjects = [NullStmt]; let Documentation = [FallthroughDocs]; } @@ -818,12 +888,26 @@ def IBOutletCollection : InheritableAttr { let Documentation = [Undocumented]; } +def IFunc : Attr { + let Spellings = [GCC<"ifunc">]; + let Args = [StringArgument<"Resolver">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [IFuncDocs]; +} + def Restrict : InheritableAttr { let Spellings = [Declspec<"restrict">, GCC<"malloc">]; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } +def LayoutVersion : InheritableAttr, TargetSpecificAttr { + let Spellings = [Declspec<"layout_version">]; + let Args = [UnsignedArgument<"Version">]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [LayoutVersionDocs]; +} + def MaxFieldAlignment : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; @@ -845,8 +929,8 @@ def MSABI : InheritableAttr { } def MSP430Interrupt : InheritableAttr, TargetSpecificAttr { - // NOTE: If you add any additional spellings, ARMInterrupt's and - // MipsInterrupt's spellings must match. + // NOTE: If you add any additional spellings, ARMInterrupt's, MipsInterrupt's + // and AnyX86Interrupt's spellings must match. let Spellings = [GNU<"interrupt">]; let Args = [UnsignedArgument<"Number">]; let ParseKind = "Interrupt"; @@ -861,8 +945,8 @@ def Mips16 : InheritableAttr, TargetSpecificAttr { } def MipsInterrupt : InheritableAttr, TargetSpecificAttr { - // NOTE: If you add any additional spellings, ARMInterrupt's and - // MSP430Interrupt's spellings must match. + // NOTE: If you add any additional spellings, ARMInterrupt's, + // MSP430Interrupt's and AnyX86Interrupt's spellings must match. let Spellings = [GNU<"interrupt">]; let Subjects = SubjectList<[Function]>; let Args = [EnumArgument<"Interrupt", "InterruptType", @@ -878,6 +962,8 @@ def MipsInterrupt : InheritableAttr, TargetSpecificAttr { def Mode : Attr { let Spellings = [GCC<"mode">]; + let Subjects = SubjectList<[Var, Enum, TypedefName, Field], ErrorDiag, + "ExpectedVariableEnumFieldOrTypedef">; let Args = [IdentifierArgument<"Mode">]; let Documentation = [Undocumented]; } @@ -927,7 +1013,9 @@ def NoCommon : InheritableAttr { def NoDebug : InheritableAttr { let Spellings = [GCC<"nodebug">]; - let Documentation = [Undocumented]; + let Subjects = SubjectList<[FunctionLike, ObjCMethod, NonParmVar], WarnDiag, + "ExpectedVariableOrFunction">; + let Documentation = [NoDebugDocs]; } def NoDuplicate : InheritableAttr { @@ -1202,6 +1290,12 @@ def ObjCRuntimeName : Attr { let Documentation = [ObjCRuntimeNameDocs]; } +def ObjCRuntimeVisible : Attr { + let Spellings = [GNU<"objc_runtime_visible">]; + let Subjects = SubjectList<[ObjCInterface], ErrorDiag>; + let Documentation = [ObjCRuntimeVisibleDocs]; +} + def ObjCBoxable : Attr { let Spellings = [GNU<"objc_boxable">]; let Subjects = SubjectList<[Record], ErrorDiag, "ExpectedStructOrUnion">; @@ -1325,6 +1419,27 @@ def StdCall : InheritableAttr { let Documentation = [StdCallDocs]; } +def SwiftCall : InheritableAttr { + let Spellings = [GCC<"swiftcall">]; +// let Subjects = SubjectList<[Function]>; + let Documentation = [SwiftCallDocs]; +} + +def SwiftContext : ParameterABIAttr { + let Spellings = [GCC<"swift_context">]; + let Documentation = [SwiftContextDocs]; +} + +def SwiftErrorResult : ParameterABIAttr { + let Spellings = [GCC<"swift_error_result">]; + let Documentation = [SwiftErrorResultDocs]; +} + +def SwiftIndirectResult : ParameterABIAttr { + let Spellings = [GCC<"swift_indirect_result">]; + let Documentation = [SwiftIndirectResultDocs]; +} + def SysVABI : InheritableAttr { let Spellings = [GCC<"sysv_abi">]; // let Subjects = [Function, ObjCMethod]; @@ -1351,6 +1466,16 @@ def Pascal : InheritableAttr { let Documentation = [Undocumented]; } +def PreserveMost : InheritableAttr { + let Spellings = [GNU<"preserve_most">]; + let Documentation = [PreserveMostDocs]; +} + +def PreserveAll : InheritableAttr { + let Spellings = [GNU<"preserve_all">]; + let Documentation = [PreserveAllDocs]; +} + def Target : InheritableAttr { let Spellings = [GCC<"target">]; let Args = [StringArgument<"featuresStr">]; @@ -1436,11 +1561,11 @@ def ObjCRequiresPropertyDefs : InheritableAttr { } def Unused : InheritableAttr { - let Spellings = [GCC<"unused">]; - let Subjects = SubjectList<[Var, ObjCIvar, Type, Label, Field, ObjCMethod, - FunctionLike], WarnDiag, - "ExpectedVariableFunctionOrLabel">; - let Documentation = [Undocumented]; + let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">]; + let Subjects = SubjectList<[Var, ObjCIvar, Type, Enum, EnumConstant, Label, + Field, ObjCMethod, FunctionLike], WarnDiag, + "ExpectedForMaybeUnused">; + let Documentation = [WarnMaybeUnusedDocs]; } def Used : InheritableAttr { @@ -1501,11 +1626,12 @@ def WarnUnused : InheritableAttr { } def WarnUnusedResult : InheritableAttr { - let Spellings = [GCC<"warn_unused_result">, - CXX11<"clang", "warn_unused_result">]; - let Subjects = SubjectList<[ObjCMethod, CXXRecord, FunctionLike], WarnDiag, - "ExpectedFunctionMethodOrClass">; - let Documentation = [Undocumented]; + let Spellings = [CXX11<"", "nodiscard", 201603>, + CXX11<"clang", "warn_unused_result">, + GCC<"warn_unused_result">]; + let Subjects = SubjectList<[ObjCMethod, Enum, CXXRecord, FunctionLike], + WarnDiag, "ExpectedFunctionMethodEnumOrClass">; + let Documentation = [WarnUnusedResultsDocs]; } def Weak : InheritableAttr { @@ -1527,6 +1653,22 @@ def WeakRef : InheritableAttr { let Documentation = [Undocumented]; } +def LTOVisibilityPublic : InheritableAttr { + let Spellings = [CXX11<"clang", "lto_visibility_public">]; + let Subjects = SubjectList<[Record]>; + let Documentation = [LTOVisibilityDocs]; +} + +def AnyX86Interrupt : InheritableAttr, TargetSpecificAttr { + // NOTE: If you add any additional spellings, ARMInterrupt's, + // MSP430Interrupt's and MipsInterrupt's spellings must match. + let Spellings = [GNU<"interrupt">]; + let Subjects = SubjectList<[HasFunctionProto]>; + let ParseKind = "Interrupt"; + let HasCustomParsing = 1; + let Documentation = [AnyX86InterruptDocs]; +} + def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr { let Spellings = [GNU<"force_align_arg_pointer">]; // Technically, this appertains to a FunctionDecl, but the target-specific @@ -1945,14 +2087,14 @@ def MSStruct : InheritableAttr { def DLLExport : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"dllexport">, GCC<"dllexport">]; - let Subjects = SubjectList<[Function, Var, CXXRecord]>; - let Documentation = [Undocumented]; + let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; + let Documentation = [DLLExportDocs]; } def DLLImport : InheritableAttr, TargetSpecificAttr { let Spellings = [Declspec<"dllimport">, GCC<"dllimport">]; - let Subjects = SubjectList<[Function, Var, CXXRecord]>; - let Documentation = [Undocumented]; + let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; + let Documentation = [DLLImportDocs]; } def SelectAny : InheritableAttr { @@ -2055,10 +2197,6 @@ def InitSeg : Attr { }]; } -def Unaligned : IgnoredAttr { - let Spellings = [Keyword<"__unaligned">]; -} - def LoopHint : Attr { /// #pragma clang loop