diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2015-01-18 16:23:48 +0000 |
commit | 06d4ba388873e6d1cfa9cd715a8935ecc8cd2097 (patch) | |
tree | 3eb853da77d46cc77c4b017525a422f9ddb1385b /include | |
parent | 30d791273d07fac9c0c1641a0731191bca6e8606 (diff) | |
download | src-test2-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.tar.gz src-test2-06d4ba388873e6d1cfa9cd715a8935ecc8cd2097.zip |
Notes
Diffstat (limited to 'include')
329 files changed, 9487 insertions, 3754 deletions
diff --git a/include/clang-c/BuildSystem.h b/include/clang-c/BuildSystem.h index ed3e8d9a28b3..7aa01914cf24 100644 --- a/include/clang-c/BuildSystem.h +++ b/include/clang-c/BuildSystem.h @@ -11,8 +11,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_C_BUILD_SYSTEM_H -#define CLANG_C_BUILD_SYSTEM_H +#ifndef LLVM_CLANG_C_BUILDSYSTEM_H +#define LLVM_CLANG_C_BUILDSYSTEM_H #include "clang-c/Platform.h" #include "clang-c/CXErrorCode.h" diff --git a/include/clang-c/CXCompilationDatabase.h b/include/clang-c/CXCompilationDatabase.h index fd65418f607c..068a677a95ed 100644 --- a/include/clang-c/CXCompilationDatabase.h +++ b/include/clang-c/CXCompilationDatabase.h @@ -12,8 +12,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_CXCOMPILATIONDATABASE_H -#define CLANG_CXCOMPILATIONDATABASE_H +#ifndef LLVM_CLANG_C_CXCOMPILATIONDATABASE_H +#define LLVM_CLANG_C_CXCOMPILATIONDATABASE_H #include "clang-c/Platform.h" #include "clang-c/CXString.h" diff --git a/include/clang-c/CXErrorCode.h b/include/clang-c/CXErrorCode.h index a026c95a5bb9..aff73b746763 100644 --- a/include/clang-c/CXErrorCode.h +++ b/include/clang-c/CXErrorCode.h @@ -11,8 +11,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_C_CXERRORCODE_H -#define CLANG_C_CXERRORCODE_H +#ifndef LLVM_CLANG_C_CXERRORCODE_H +#define LLVM_CLANG_C_CXERRORCODE_H #include "clang-c/Platform.h" diff --git a/include/clang-c/CXString.h b/include/clang-c/CXString.h index cf198cbf5d0f..a649cdf82fc7 100644 --- a/include/clang-c/CXString.h +++ b/include/clang-c/CXString.h @@ -11,8 +11,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_CXSTRING_H -#define CLANG_CXSTRING_H +#ifndef LLVM_CLANG_C_CXSTRING_H +#define LLVM_CLANG_C_CXSTRING_H #include "clang-c/Platform.h" diff --git a/include/clang-c/Documentation.h b/include/clang-c/Documentation.h index ad2da0778315..89373b11457d 100644 --- a/include/clang-c/Documentation.h +++ b/include/clang-c/Documentation.h @@ -12,8 +12,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_C_DOCUMENTATION_H -#define CLANG_C_DOCUMENTATION_H +#ifndef LLVM_CLANG_C_DOCUMENTATION_H +#define LLVM_CLANG_C_DOCUMENTATION_H #include "clang-c/Index.h" diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index f69f567c2690..ed7bd169f6fc 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -13,8 +13,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_C_INDEX_H -#define CLANG_C_INDEX_H +#ifndef LLVM_CLANG_C_INDEX_H +#define LLVM_CLANG_C_INDEX_H #include <time.h> @@ -32,7 +32,7 @@ * compatible, thus CINDEX_VERSION_MAJOR is expected to remain stable. */ #define CINDEX_VERSION_MAJOR 0 -#define CINDEX_VERSION_MINOR 27 +#define CINDEX_VERSION_MINOR 29 #define CINDEX_VERSION_ENCODE(major, minor) ( \ ((major) * 10000) \ @@ -336,6 +336,12 @@ CINDEX_LINKAGE CXFile clang_getFile(CXTranslationUnit tu, const char *file_name); /** + * \brief Returns non-zero if the \c file1 and \c file2 point to the same file, + * or they are both NULL. + */ +CINDEX_LINKAGE int clang_File_isEqual(CXFile file1, CXFile file2); + +/** * @} */ @@ -2120,7 +2126,7 @@ enum CXCursorKind { */ CXCursor_MSAsmStmt = 229, - /** \brief The null satement ";": C99 6.8.3p3. + /** \brief The null statement ";": C99 6.8.3p3. * * This cursor kind is used to describe the null statement. */ @@ -2135,7 +2141,7 @@ enum CXCursorKind { */ CXCursor_OMPParallelDirective = 232, - /** \brief OpenMP simd directive. + /** \brief OpenMP SIMD directive. */ CXCursor_OMPSimdDirective = 233, @@ -2195,7 +2201,31 @@ enum CXCursorKind { */ CXCursor_SEHLeaveStmt = 247, - CXCursor_LastStmt = CXCursor_SEHLeaveStmt, + /** \brief OpenMP ordered directive. + */ + CXCursor_OMPOrderedDirective = 248, + + /** \brief OpenMP atomic directive. + */ + CXCursor_OMPAtomicDirective = 249, + + /** \brief OpenMP for SIMD directive. + */ + CXCursor_OMPForSimdDirective = 250, + + /** \brief OpenMP parallel for SIMD directive. + */ + CXCursor_OMPParallelForSimdDirective = 251, + + /** \brief OpenMP target directive. + */ + CXCursor_OMPTargetDirective = 252, + + /** \brief OpenMP teams directive. + */ + CXCursor_OMPTeamsDirective = 253, + + CXCursor_LastStmt = CXCursor_OMPTeamsDirective, /** * \brief Cursor that represents the translation unit itself. @@ -2228,7 +2258,8 @@ enum CXCursorKind { CXCursor_CUDADeviceAttr = 413, CXCursor_CUDAGlobalAttr = 414, CXCursor_CUDAHostAttr = 415, - CXCursor_LastAttr = CXCursor_CUDAHostAttr, + CXCursor_CUDASharedAttr = 416, + CXCursor_LastAttr = CXCursor_CUDASharedAttr, /* Preprocessing */ CXCursor_PreprocessingDirective = 500, @@ -2822,6 +2853,7 @@ enum CXCallingConv { CXCallingConv_IntelOclBicc = 9, CXCallingConv_X86_64Win64 = 10, CXCallingConv_X86_64SysV = 11, + CXCallingConv_X86VectorCall = 12, CXCallingConv_Invalid = 100, CXCallingConv_Unexposed = 200 @@ -2912,6 +2944,124 @@ CINDEX_LINKAGE int clang_Cursor_getNumArguments(CXCursor C); CINDEX_LINKAGE CXCursor clang_Cursor_getArgument(CXCursor C, unsigned i); /** + * \brief Describes the kind of a template argument. + * + * See the definition of llvm::clang::TemplateArgument::ArgKind for full + * element descriptions. + */ +enum CXTemplateArgumentKind { + CXTemplateArgumentKind_Null, + CXTemplateArgumentKind_Type, + CXTemplateArgumentKind_Declaration, + CXTemplateArgumentKind_NullPtr, + CXTemplateArgumentKind_Integral, + CXTemplateArgumentKind_Template, + CXTemplateArgumentKind_TemplateExpansion, + CXTemplateArgumentKind_Expression, + CXTemplateArgumentKind_Pack, + /* Indicates an error case, preventing the kind from being deduced. */ + CXTemplateArgumentKind_Invalid +}; + +/** + *\brief Returns the number of template args of a function decl representing a + * template specialization. + * + * If the argument cursor cannot be converted into a template function + * declaration, -1 is returned. + * + * For example, for the following declaration and specialization: + * template <typename T, int kInt, bool kBool> + * void foo() { ... } + * + * template <> + * void foo<float, -7, true>(); + * + * The value 3 would be returned from this call. + */ +CINDEX_LINKAGE int clang_Cursor_getNumTemplateArguments(CXCursor C); + +/** + * \brief Retrieve the kind of the I'th template argument of the CXCursor C. + * + * If the argument CXCursor does not represent a FunctionDecl, an invalid + * template argument kind is returned. + * + * For example, for the following declaration and specialization: + * template <typename T, int kInt, bool kBool> + * void foo() { ... } + * + * template <> + * void foo<float, -7, true>(); + * + * For I = 0, 1, and 2, Type, Integral, and Integral will be returned, + * respectively. + */ +CINDEX_LINKAGE enum CXTemplateArgumentKind clang_Cursor_getTemplateArgumentKind( + CXCursor C, unsigned I); + +/** + * \brief Retrieve a CXType representing the type of a TemplateArgument of a + * function decl representing a template specialization. + * + * If the argument CXCursor does not represent a FunctionDecl whose I'th + * template argument has a kind of CXTemplateArgKind_Integral, an invalid type + * is returned. + * + * For example, for the following declaration and specialization: + * template <typename T, int kInt, bool kBool> + * void foo() { ... } + * + * template <> + * void foo<float, -7, true>(); + * + * If called with I = 0, "float", will be returned. + * Invalid types will be returned for I == 1 or 2. + */ +CINDEX_LINKAGE CXType clang_Cursor_getTemplateArgumentType(CXCursor C, + unsigned I); + +/** + * \brief Retrieve the value of an Integral TemplateArgument (of a function + * decl representing a template specialization) as a signed long long. + * + * It is undefined to call this function on a CXCursor that does not represent a + * FunctionDecl or whose I'th template argument is not an integral value. + * + * For example, for the following declaration and specialization: + * template <typename T, int kInt, bool kBool> + * void foo() { ... } + * + * template <> + * void foo<float, -7, true>(); + * + * If called with I = 1 or 2, -7 or true will be returned, respectively. + * For I == 0, this function's behavior is undefined. + */ +CINDEX_LINKAGE long long clang_Cursor_getTemplateArgumentValue(CXCursor C, + unsigned I); + +/** + * \brief Retrieve the value of an Integral TemplateArgument (of a function + * decl representing a template specialization) as an unsigned long long. + * + * It is undefined to call this function on a CXCursor that does not represent a + * FunctionDecl or whose I'th template argument is not an integral value. + * + * For example, for the following declaration and specialization: + * template <typename T, int kInt, bool kBool> + * void foo() { ... } + * + * template <> + * void foo<float, 2147483649, true>(); + * + * If called with I = 1 or 2, 2147483649 or true will be returned, respectively. + * For I == 0, this function's behavior is undefined. + */ +CINDEX_LINKAGE unsigned long long clang_Cursor_getTemplateArgumentUnsignedValue( + CXCursor C, unsigned I); + +/** * \brief Determine whether two CXTypes represent the same type. * * \returns non-zero if the CXTypes represent the same type and @@ -3194,6 +3344,29 @@ enum CX_CXXAccessSpecifier { CINDEX_LINKAGE enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor); /** + * \brief Represents the storage classes as declared in the source. CX_SC_Invalid + * was added for the case that the passed cursor in not a declaration. + */ +enum CX_StorageClass { + CX_SC_Invalid, + CX_SC_None, + CX_SC_Extern, + CX_SC_Static, + CX_SC_PrivateExtern, + CX_SC_OpenCLWorkGroupLocal, + CX_SC_Auto, + CX_SC_Register +}; + +/** + * \brief Returns the storage class for a function or variable declaration. + * + * If the passed in Cursor is not a function or variable declaration, + * CX_SC_Invalid is returned else the storage class. + */ +CINDEX_LINKAGE enum CX_StorageClass clang_Cursor_getStorageClass(CXCursor); + +/** * \brief Determine the number of overloaded declarations referenced by a * \c CXCursor_OverloadedDeclRef cursor. * @@ -3631,6 +3804,20 @@ CINDEX_LINKAGE CXString clang_Cursor_getBriefCommentText(CXCursor C); * @} */ +/** \defgroup CINDEX_MANGLE Name Mangling API Functions + * + * @{ + */ + +/** + * \brief Retrieve the CXString representing the mangled name of the cursor. + */ +CINDEX_LINKAGE CXString clang_Cursor_getMangling(CXCursor); + +/** + * @} + */ + /** * \defgroup CINDEX_MODULE Module introspection * diff --git a/include/clang-c/Platform.h b/include/clang-c/Platform.h index 0f866c64563c..e2a4dccbdaf0 100644 --- a/include/clang-c/Platform.h +++ b/include/clang-c/Platform.h @@ -11,8 +11,8 @@ |* *| \*===----------------------------------------------------------------------===*/ -#ifndef CLANG_C_PLATFORM_H -#define CLANG_C_PLATFORM_H +#ifndef LLVM_CLANG_C_PLATFORM_H +#define LLVM_CLANG_C_PLATFORM_H #ifdef __cplusplus extern "C" { diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h index b3e74b996678..c830aa3d7874 100644 --- a/include/clang/ARCMigrate/ARCMTActions.h +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H -#define LLVM_CLANG_ARCMIGRATE_ARCMT_ACTION_H +#ifndef LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H +#define LLVM_CLANG_ARCMIGRATE_ARCMTACTIONS_H #include "clang/ARCMigrate/FileRemapper.h" #include "clang/Frontend/FrontendAction.h" @@ -37,8 +37,8 @@ class MigrateSourceAction : public ASTFrontendAction { FileRemapper Remapper; protected: bool BeginInvocation(CompilerInstance &CI) override; - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class MigrateAction : public WrapperFrontendAction { @@ -65,8 +65,8 @@ public: unsigned migrateAction); protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; bool BeginInvocation(CompilerInstance &CI) override; }; diff --git a/include/clang/ARCMigrate/FileRemapper.h b/include/clang/ARCMigrate/FileRemapper.h index e094301ae6c4..53b88e9eb5e5 100644 --- a/include/clang/ARCMigrate/FileRemapper.h +++ b/include/clang/ARCMigrate/FileRemapper.h @@ -52,14 +52,14 @@ public: bool overwriteOriginal(DiagnosticsEngine &Diag, StringRef outputDir = StringRef()); - void remap(StringRef filePath, llvm::MemoryBuffer *memBuf); + void remap(StringRef filePath, std::unique_ptr<llvm::MemoryBuffer> memBuf); void applyMappings(PreprocessorOptions &PPOpts) const; void clear(StringRef outputDir = StringRef()); private: - void remap(const FileEntry *file, llvm::MemoryBuffer *memBuf); + void remap(const FileEntry *file, std::unique_ptr<llvm::MemoryBuffer> memBuf); void remap(const FileEntry *file, const FileEntry *newfile); const FileEntry *getOriginalFile(StringRef filePath); diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index 8134f6b080b7..195d748b5be8 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -30,6 +30,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SanitizerBlacklist.h" #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" @@ -74,6 +75,15 @@ namespace clang { class FullComment; } + struct TypeInfo { + uint64_t Width; + unsigned Align; + bool AlignIsRequired : 1; + TypeInfo() : Width(0), Align(0), AlignIsRequired(false) {} + TypeInfo(uint64_t Width, unsigned Align, bool AlignIsRequired) + : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} + }; + /// \brief Holds long-lived AST nodes (such as types and decls) that can be /// referred to throughout the semantic analysis of a file. class ASTContext : public RefCountedBase<ASTContext> { @@ -144,8 +154,7 @@ class ASTContext : public RefCountedBase<ASTContext> { ObjCLayouts; /// \brief A cache from types to size and alignment information. - typedef llvm::DenseMap<const Type*, - std::pair<uint64_t, unsigned> > TypeInfoMap; + typedef llvm::DenseMap<const Type *, struct TypeInfo> TypeInfoMap; mutable TypeInfoMap MemoizedTypeInfo; /// \brief A cache mapping from CXXRecordDecls to key functions. @@ -264,8 +273,6 @@ class ASTContext : public RefCountedBase<ASTContext> { /// \brief Declaration for the CUDA cudaConfigureCall function. FunctionDecl *cudaConfigureCallDecl; - TypeSourceInfo NullTypeSourceInfo; - /// \brief Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of @@ -384,6 +391,10 @@ private: /// this ASTContext object. LangOptions &LangOpts; + /// \brief Blacklist object that is used by sanitizers to decide which + /// entities should not be instrumented. + std::unique_ptr<SanitizerBlacklist> SanitizerBL; + /// \brief The allocator used to create AST objects. /// /// AST objects are never destructed; rather, all memory associated with the @@ -453,11 +464,12 @@ public: /// 'NodeT' can be one of Decl, Stmt, Type, TypeLoc, /// NestedNameSpecifier or NestedNameSpecifierLoc. template <typename NodeT> - ParentVector getParents(const NodeT &Node) { + ArrayRef<ast_type_traits::DynTypedNode> getParents(const NodeT &Node) { return getParents(ast_type_traits::DynTypedNode::create(Node)); } - ParentVector getParents(const ast_type_traits::DynTypedNode &Node); + ArrayRef<ast_type_traits::DynTypedNode> + getParents(const ast_type_traits::DynTypedNode &Node); const clang::PrintingPolicy &getPrintingPolicy() const { return PrintingPolicy; @@ -508,6 +520,10 @@ public: const LangOptions& getLangOpts() const { return LangOpts; } + const SanitizerBlacklist &getSanitizerBlacklist() const { + return *SanitizerBL; + } + DiagnosticsEngine &getDiagnostics() const; FullSourceLoc getFullLoc(SourceLocation Loc) const { @@ -912,6 +928,12 @@ public: /// \brief Change the result type of a function type once it is deduced. void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); + /// \brief Change the exception specification on a function once it is + /// delay-parsed, instantiated, or computed. + void adjustExceptionSpec(FunctionDecl *FD, + const FunctionProtoType::ExceptionSpecInfo &ESI, + bool AsWritten = false); + /// \brief Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T) const; @@ -1371,7 +1393,8 @@ public: /// /// If \p Field is specified then record field names are also encoded. void getObjCEncodingForType(QualType T, std::string &S, - const FieldDecl *Field=nullptr) const; + const FieldDecl *Field=nullptr, + QualType *NotEncodedT=nullptr) const; /// \brief Emit the Objective-C property type encoding for the given /// type \p T into \p S. @@ -1581,7 +1604,7 @@ public: private: CanQualType getFromTargetType(unsigned Type) const; - std::pair<uint64_t, unsigned> getTypeInfoImpl(const Type *T) const; + TypeInfo getTypeInfoImpl(const Type *T) const; //===--------------------------------------------------------------------===// // Type Predicates. @@ -1614,18 +1637,12 @@ public: const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; /// \brief Get the size and alignment of the specified complete type in bits. - std::pair<uint64_t, unsigned> getTypeInfo(const Type *T) const; - std::pair<uint64_t, unsigned> getTypeInfo(QualType T) const { - return getTypeInfo(T.getTypePtr()); - } + TypeInfo getTypeInfo(const Type *T) const; + TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); } /// \brief Return the size of the specified (complete) type \p T, in bits. - uint64_t getTypeSize(QualType T) const { - return getTypeInfo(T).first; - } - uint64_t getTypeSize(const Type *T) const { - return getTypeInfo(T).first; - } + uint64_t getTypeSize(QualType T) const { return getTypeInfo(T).Width; } + uint64_t getTypeSize(const Type *T) const { return getTypeInfo(T).Width; } /// \brief Return the size of the character type, in bits. uint64_t getCharWidth() const { @@ -1645,12 +1662,8 @@ public: /// \brief Return the ABI-specified alignment of a (complete) type \p T, in /// bits. - unsigned getTypeAlign(QualType T) const { - return getTypeInfo(T).second; - } - unsigned getTypeAlign(const Type *T) const { - return getTypeInfo(T).second; - } + unsigned getTypeAlign(QualType T) const { return getTypeInfo(T).Align; } + unsigned getTypeAlign(const Type *T) const { return getTypeInfo(T).Align; } /// \brief Return the ABI-specified alignment of a (complete) type \p T, in /// characters. @@ -1664,6 +1677,11 @@ public: std::pair<CharUnits, CharUnits> getTypeInfoInChars(const Type *T) const; std::pair<CharUnits, CharUnits> getTypeInfoInChars(QualType T) const; + /// \brief Determine if the alignment the type has was required using an + /// alignment attribute. + bool isAlignmentRequired(const Type *T) const; + bool isAlignmentRequired(QualType T) const; + /// \brief Return the "preferred" alignment of the specified type \p T for /// the current target, in bits. /// @@ -2153,8 +2171,6 @@ public: getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()) const; - TypeSourceInfo *getNullTypeSourceInfo() { return &NullTypeSourceInfo; } - /// \brief Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// @@ -2272,12 +2288,14 @@ private: bool StructField = false, bool EncodeBlockParameters = false, bool EncodeClassNames = false, - bool EncodePointerToObjCTypedef = false) const; + bool EncodePointerToObjCTypedef = false, + QualType *NotEncodedT=nullptr) const; // Adds the encoding of the structure's members. void getObjCEncodingForStructureImpl(RecordDecl *RD, std::string &S, const FieldDecl *Field, - bool includeVBases = true) const; + bool includeVBases = true, + QualType *NotEncodedT=nullptr) const; public: // Adds the encoding of a method parameter or return type. void getObjCEncodingForMethodParameter(Decl::ObjCDeclQualifier QT, @@ -2312,6 +2330,31 @@ private: std::unique_ptr<ParentMap> AllParents; std::unique_ptr<VTableContextBase> VTContext; + +public: + enum PragmaSectionFlag : unsigned { + PSF_None = 0, + PSF_Read = 0x1, + PSF_Write = 0x2, + PSF_Execute = 0x4, + PSF_Implicit = 0x8, + PSF_Invalid = 0x80000000U, + }; + + struct SectionInfo { + DeclaratorDecl *Decl; + SourceLocation PragmaSectionLocation; + int SectionFlags; + SectionInfo() {} + SectionInfo(DeclaratorDecl *Decl, + SourceLocation PragmaSectionLocation, + int SectionFlags) + : Decl(Decl), + PragmaSectionLocation(PragmaSectionLocation), + SectionFlags(SectionFlags) {} + }; + + llvm::StringMap<SectionInfo> SectionInfos; }; /// \brief Utility function for constructing a nullary selector. @@ -2349,9 +2392,9 @@ static inline Selector GetUnarySelector(StringRef name, ASTContext& Ctx) { /// // Specific alignment /// IntegerLiteral *Ex2 = new (Context, 4) IntegerLiteral(arguments); /// @endcode -/// Please note that you cannot use delete on the pointer; it must be -/// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// Memory allocated through this placement new operator does not need to be +/// explicitly freed, as ASTContext will free all of this memory when it gets +/// destroyed. Please note that you cannot use delete on the pointer. /// /// @param Bytes The number of bytes to allocate. Calculated by the compiler. /// @param C The ASTContext that provides the allocator. @@ -2386,9 +2429,9 @@ inline void operator delete(void *Ptr, const clang::ASTContext &C, size_t) { /// // Specific alignment /// char *data = new (Context, 4) char[10]; /// @endcode -/// Please note that you cannot use delete on the pointer; it must be -/// deallocated using an explicit destructor call followed by -/// @c Context.Deallocate(Ptr). +/// Memory allocated through this placement new[] operator does not need to be +/// explicitly freed, as ASTContext will free all of this memory when it gets +/// destroyed. Please note that you cannot use delete on the pointer. /// /// @param Bytes The number of bytes to allocate. Calculated by the compiler. /// @param C The ASTContext that provides the allocator. diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 484ca4cb8632..27c85e65f2c1 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICAST_H -#define LLVM_CLANG_DIAGNOSTICAST_H +#ifndef LLVM_CLANG_AST_ASTDIAGNOSTIC_H +#define LLVM_CLANG_AST_ASTDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h index 4f3279874b16..003d489c1ca4 100644 --- a/include/clang/AST/ASTFwd.h +++ b/include/clang/AST/ASTFwd.h @@ -12,6 +12,9 @@ /// //===-------------------------------------------------------------===// +#ifndef LLVM_CLANG_AST_ASTFWD_H +#define LLVM_CLANG_AST_ASTFWD_H + namespace clang { class Decl; @@ -26,3 +29,5 @@ class Type; class CXXCtorInitializer; } // end namespace clang + +#endif diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h index 9af016b13d45..69df2d8c0113 100644 --- a/include/clang/AST/ASTLambda.h +++ b/include/clang/AST/ASTLambda.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_LAMBDA_H -#define LLVM_CLANG_AST_LAMBDA_H +#ifndef LLVM_CLANG_AST_ASTLAMBDA_H +#define LLVM_CLANG_AST_ASTLAMBDA_H #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" @@ -77,4 +77,4 @@ inline DeclContext *getLambdaAwareParentOfDeclContext(DeclContext *DC) { } // clang -#endif // LLVM_CLANG_AST_LAMBDA_H +#endif diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index a89bfed53fbd..48eb6292772c 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -102,6 +102,12 @@ public: /// \param D the declaration marked used virtual void DeclarationMarkedUsed(const Decl *D) {} + /// \brief A declaration is marked as OpenMP threadprivate which was not + /// previously marked as threadprivate. + /// + /// \param D the declaration marked OpenMP threadprivate. + virtual void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) {} + // NOTE: If new methods are added they should also be added to // MultiplexASTMutationListener. }; diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 0e06e26e6d80..dc3c34f28d94 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_AST_TYPE_TRAITS_H -#define LLVM_CLANG_AST_AST_TYPE_TRAITS_H +#ifndef LLVM_CLANG_AST_ASTTYPETRAITS_H +#define LLVM_CLANG_AST_ASTTYPETRAITS_H #include "clang/AST/ASTFwd.h" #include "clang/AST/Decl.h" @@ -23,6 +23,7 @@ #include "clang/AST/TemplateBase.h" #include "clang/AST/TypeLoc.h" #include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/AlignOf.h" namespace llvm { @@ -53,9 +54,19 @@ public: return ASTNodeKind(KindToKindId<T>::Id); } + /// \{ + /// \brief Construct an identifier for the dynamic type of the node + static ASTNodeKind getFromNode(const Decl &D); + static ASTNodeKind getFromNode(const Stmt &S); + static ASTNodeKind getFromNode(const Type &T); + /// \} + /// \brief Returns \c true if \c this and \c Other represent the same kind. bool isSame(ASTNodeKind Other) const; + /// \brief Returns \c true only for the default \c ASTNodeKind() + bool isNone() const { return KindId == NKI_None; } + /// \brief Returns \c true if \c this is a base kind of (or same as) \c Other. /// \param Distance If non-null, used to return the distance between \c this /// and \c Other in the class hierarchy. @@ -69,6 +80,32 @@ public: return KindId < Other.KindId; } + /// \brief Return the most derived type between \p Kind1 and \p Kind2. + /// + /// Return ASTNodeKind() if they are not related. + static ASTNodeKind getMostDerivedType(ASTNodeKind Kind1, ASTNodeKind Kind2); + + /// \brief Return the most derived common ancestor between Kind1 and Kind2. + /// + /// Return ASTNodeKind() if they are not related. + static ASTNodeKind getMostDerivedCommonAncestor(ASTNodeKind Kind1, + ASTNodeKind Kind2); + + /// \brief Hooks for using ASTNodeKind as a key in a DenseMap. + struct DenseMapInfo { + // ASTNodeKind() is a good empty key because it is represented as a 0. + static inline ASTNodeKind getEmptyKey() { return ASTNodeKind(); } + // NKI_NumberOfKinds is not a valid value, so it is good for a + // tombstone key. + static inline ASTNodeKind getTombstoneKey() { + return ASTNodeKind(NKI_NumberOfKinds); + } + static unsigned getHashValue(const ASTNodeKind &Val) { return Val.KindId; } + static bool isEqual(const ASTNodeKind &LHS, const ASTNodeKind &RHS) { + return LHS.KindId == RHS.KindId; + } + }; + private: /// \brief Kind ids. /// @@ -108,6 +145,8 @@ private: template <class T> struct KindToKindId { static const NodeKindId Id = NKI_None; }; + template <class T> + struct KindToKindId<const T> : KindToKindId<T> {}; /// \brief Per kind info. struct KindInfo { @@ -184,12 +223,22 @@ public: return BaseConverter<T>::get(NodeKind, Storage.buffer); } + /// \brief Retrieve the stored node as type \c T. + /// + /// Similar to \c get(), but asserts that the type is what we are expecting. + template <typename T> + const T &getUnchecked() const { + return BaseConverter<T>::getUnchecked(NodeKind, Storage.buffer); + } + + ASTNodeKind getNodeKind() const { return NodeKind; } + /// \brief Returns a pointer that identifies the stored AST node. /// /// Note that this is not supported by all AST nodes. For AST nodes /// that don't have a pointer-defined identity inside the AST, this /// method returns NULL. - const void *getMemoizationData() const; + const void *getMemoizationData() const { return MemoizationData; } /// \brief Prints the node to the given output stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; @@ -212,14 +261,15 @@ public: return getMemoizationData() < Other.getMemoizationData(); } bool operator==(const DynTypedNode &Other) const { - if (!NodeKind.isBaseOf(Other.NodeKind) && - !Other.NodeKind.isBaseOf(NodeKind)) + // DynTypedNode::create() stores the exact kind of the node in NodeKind. + // If they contain the same node, their NodeKind must be the same. + if (!NodeKind.isSame(Other.NodeKind)) return false; // FIXME: Implement for other types. - if (ASTNodeKind::getFromNodeKind<QualType>().isBaseOf(NodeKind)) { - return *get<QualType>() == *Other.get<QualType>(); - } + if (ASTNodeKind::getFromNodeKind<QualType>().isSame(NodeKind)) + return getUnchecked<QualType>() == Other.getUnchecked<QualType>(); + assert(getMemoizationData() && Other.getMemoizationData()); return getMemoizationData() == Other.getMemoizationData(); } @@ -235,13 +285,18 @@ private: /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. template <typename T, typename BaseT> struct DynCastPtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { - if (ASTNodeKind::getFromNodeKind<BaseT>().isBaseOf(NodeKind)) - return dyn_cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + if (ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)) + return cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isBaseOf(NodeKind)); + return *cast<T>(*reinterpret_cast<BaseT *const *>(Storage)); + } static DynTypedNode create(const BaseT &Node) { DynTypedNode Result; - Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.NodeKind = ASTNodeKind::getFromNode(Node); + Result.MemoizationData = &Node; new (Result.Storage.buffer) const BaseT * (&Node); return Result; } @@ -254,9 +309,14 @@ private: return *reinterpret_cast<T *const *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return **reinterpret_cast<T *const *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.MemoizationData = &Node; new (Result.Storage.buffer) const T * (&Node); return Result; } @@ -269,15 +329,21 @@ private: return reinterpret_cast<const T *>(Storage); return nullptr; } + static const T &getUnchecked(ASTNodeKind NodeKind, const char Storage[]) { + assert(ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)); + return *reinterpret_cast<const T *>(Storage); + } static DynTypedNode create(const T &Node) { DynTypedNode Result; Result.NodeKind = ASTNodeKind::getFromNodeKind<T>(); + Result.MemoizationData = nullptr; new (Result.Storage.buffer) T(Node); return Result; } }; ASTNodeKind NodeKind; + const void *MemoizationData; /// \brief Stores the data of the node. /// @@ -345,20 +411,15 @@ template <typename T, typename EnablerT> struct DynTypedNode::BaseConverter { } }; -inline const void *DynTypedNode::getMemoizationData() const { - if (ASTNodeKind::getFromNodeKind<Decl>().isBaseOf(NodeKind)) { - return BaseConverter<Decl>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<Stmt>().isBaseOf(NodeKind)) { - return BaseConverter<Stmt>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<Type>().isBaseOf(NodeKind)) { - return BaseConverter<Type>::get(NodeKind, Storage.buffer); - } else if (ASTNodeKind::getFromNodeKind<NestedNameSpecifier>().isBaseOf(NodeKind)) { - return BaseConverter<NestedNameSpecifier>::get(NodeKind, Storage.buffer); - } - return nullptr; -} - } // end namespace ast_type_traits } // end namespace clang -#endif // LLVM_CLANG_AST_AST_TYPE_TRAITS_H +namespace llvm { + +template <> +struct DenseMapInfo<clang::ast_type_traits::ASTNodeKind> + : clang::ast_type_traits::ASTNodeKind::DenseMapInfo {}; + +} // end namespace llvm + +#endif diff --git a/include/clang/AST/ASTVector.h b/include/clang/AST/ASTVector.h index d92167e95992..6ec054582e26 100644 --- a/include/clang/AST/ASTVector.h +++ b/include/clang/AST/ASTVector.h @@ -15,8 +15,8 @@ // FIXME: Most of this is copy-and-paste from BumpVector.h and SmallVector.h. // We can refactor this core logic into something common. -#ifndef LLVM_CLANG_AST_VECTOR -#define LLVM_CLANG_AST_VECTOR +#ifndef LLVM_CLANG_AST_ASTVECTOR_H +#define LLVM_CLANG_AST_ASTVECTOR_H #include "clang/AST/AttrIterator.h" #include "llvm/ADT/PointerIntPair.h" @@ -236,14 +236,14 @@ public: iterator insert(const ASTContext &C, iterator I, size_type NumToInsert, const T &Elt) { - if (I == this->end()) { // Important special case for empty vector. - append(C, NumToInsert, Elt); - return this->end()-1; - } - // Convert iterator to elt# to avoid invalidating iterator when we reserve() size_t InsertElt = I - this->begin(); + if (I == this->end()) { // Important special case for empty vector. + append(C, NumToInsert, Elt); + return this->begin() + InsertElt; + } + // Ensure there is enough space. reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); @@ -284,14 +284,15 @@ public: template<typename ItTy> iterator insert(const ASTContext &C, iterator I, ItTy From, ItTy To) { - if (I == this->end()) { // Important special case for empty vector. + // Convert iterator to elt# to avoid invalidating iterator when we reserve() + size_t InsertElt = I - this->begin(); + + if (I == this->end()) { // Important special case for empty vector. append(C, From, To); - return this->end()-1; + return this->begin() + InsertElt; } size_t NumToInsert = std::distance(From, To); - // Convert iterator to elt# to avoid invalidating iterator when we reserve() - size_t InsertElt = I - this->begin(); // Ensure there is enough space. reserve(C, static_cast<unsigned>(this->size() + NumToInsert)); diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index fc4881619bce..787843e64f56 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -16,6 +16,7 @@ #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/AttrKinds.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 7cccef69ddf8..aa3c84682983 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_CANONICAL_TYPE_H -#define LLVM_CLANG_AST_CANONICAL_TYPE_H +#ifndef LLVM_CLANG_AST_CANONICALTYPE_H +#define LLVM_CLANG_AST_CANONICALTYPE_H #include "clang/AST/Type.h" #include "llvm/Support/Casting.h" @@ -736,4 +736,4 @@ CanTypeIterator<InputIterator>::operator->() const { } -#endif // LLVM_CLANG_AST_CANONICAL_TYPE_H +#endif diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index e18fe9ab86a0..94470cbf305f 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -96,9 +96,10 @@ protected: unsigned : NumInlineContentCommentBits; unsigned RenderKind : 2; - unsigned CommandID : 8; + unsigned CommandID : CommandInfo::NumCommandIDBits; }; - enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 10 }; + enum { NumInlineCommandCommentBits = NumInlineContentCommentBits + 2 + + CommandInfo::NumCommandIDBits }; class HTMLTagCommentBitfields { friend class HTMLTagComment; @@ -139,13 +140,14 @@ protected: unsigned : NumCommentBits; - unsigned CommandID : 8; + unsigned CommandID : CommandInfo::NumCommandIDBits; /// Describes the syntax that was used in a documentation command. /// Contains values from CommandMarkerKind enum. unsigned CommandMarker : 1; }; - enum { NumBlockCommandCommentBits = NumCommentBits + 9 }; + enum { NumBlockCommandCommentBits = NumCommentBits + + CommandInfo::NumCommandIDBits + 1 }; class ParamCommandCommentBitfields { friend class ParamCommandComment; diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h index 5d508860635d..be5b8eeb80c3 100644 --- a/include/clang/AST/CommentBriefParser.h +++ b/include/clang/AST/CommentBriefParser.h @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H -#define LLVM_CLANG_AST_BRIEF_COMMENT_PARSER_H +#ifndef LLVM_CLANG_AST_COMMENTBRIEFPARSER_H +#define LLVM_CLANG_AST_COMMENTBRIEFPARSER_H #include "clang/AST/CommentLexer.h" diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index dde7a1442fe1..ec6d83c03021 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -13,8 +13,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H -#define LLVM_CLANG_AST_COMMENT_COMMAND_TRAITS_H +#ifndef LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H +#define LLVM_CLANG_AST_COMMENTCOMMANDTRAITS_H #include "clang/Basic/CommentOptions.h" #include "clang/Basic/LLVM.h" @@ -40,7 +40,11 @@ struct CommandInfo { /// Name of the command that ends the verbatim block. const char *EndCommandName; - unsigned ID : 8; + /// DRY definition of the number of bits used for a command ID. + enum { NumCommandIDBits = 20 }; + + /// The ID of the command. + unsigned ID : NumCommandIDBits; /// Number of word-like arguments for a given block command, except for /// \\param and \\tparam commands -- these have special argument parsers. diff --git a/include/clang/AST/CommentDiagnostic.h b/include/clang/AST/CommentDiagnostic.h index 312da065ff59..f3a209bf6e7c 100644 --- a/include/clang/AST/CommentDiagnostic.h +++ b/include/clang/AST/CommentDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_COMMENTDIAGNOSTIC_H -#define LLVM_CLANG_COMMENTDIAGNOSTIC_H +#ifndef LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H +#define LLVM_CLANG_AST_COMMENTDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index a6e3ed89b27e..d995df921282 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_LEXER_H -#define LLVM_CLANG_AST_COMMENT_LEXER_H +#ifndef LLVM_CLANG_AST_COMMENTLEXER_H +#define LLVM_CLANG_AST_COMMENTLEXER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" diff --git a/include/clang/AST/CommentParser.h b/include/clang/AST/CommentParser.h index 7e008131d205..2c444f0dc3a6 100644 --- a/include/clang/AST/CommentParser.h +++ b/include/clang/AST/CommentParser.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_PARSER_H -#define LLVM_CLANG_AST_COMMENT_PARSER_H +#ifndef LLVM_CLANG_AST_COMMENTPARSER_H +#define LLVM_CLANG_AST_COMMENTPARSER_H #include "clang/AST/Comment.h" #include "clang/AST/CommentLexer.h" diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 027c3b929df6..4ae6fe0c613d 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_COMMENT_SEMA_H -#define LLVM_CLANG_AST_COMMENT_SEMA_H +#ifndef LLVM_CLANG_AST_COMMENTSEMA_H +#define LLVM_CLANG_AST_COMMENTSEMA_H #include "clang/AST/Comment.h" #include "clang/Basic/Diagnostic.h" @@ -85,7 +85,7 @@ public: std::uninitialized_copy(Source.begin(), Source.end(), Mem); return llvm::makeArrayRef(Mem, Size); } - return ArrayRef<T>(); + return None; } ParagraphComment *actOnParagraphComment( diff --git a/include/clang/AST/DataRecursiveASTVisitor.h b/include/clang/AST/DataRecursiveASTVisitor.h index 9ef008717b1b..c0526e1cfd45 100644 --- a/include/clang/AST/DataRecursiveASTVisitor.h +++ b/include/clang/AST/DataRecursiveASTVisitor.h @@ -424,6 +424,7 @@ private: bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); + bool TraverseOMPLoopDirective(OMPLoopDirective *S); bool TraverseOMPClause(OMPClause *C); #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" @@ -623,6 +624,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -647,6 +649,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -875,6 +878,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) @@ -1083,6 +1089,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) @@ -2122,21 +2131,29 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { TRY_TO(TraverseLambdaCapture(S, C)); } - if (S->hasExplicitParameters() || S->hasExplicitResultType()) { - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); - } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { - if (S->hasExplicitParameters()) { - // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getParam(I))); - } - } else { - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>(); + + if (S->hasExplicitParameters() && S->hasExplicitResultType()) { + // Visit the whole type. + TRY_TO(TraverseTypeLoc(TL)); + } else { + if (S->hasExplicitParameters()) { + // Visit parameters. + for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getParam(I))); } + } else if (S->hasExplicitResultType()) { + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + } + + auto *T = Proto.getTypePtr(); + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); } TRY_TO(TraverseLambdaBody(S)); @@ -2237,6 +2254,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) +DEF_TRAVERSE_STMT(TypoExpr, {}) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) // These operators (all of them) do not need any action except @@ -2253,6 +2271,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) +DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) // These literals (all of them) do not need any action. @@ -2279,6 +2298,12 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( return true; } +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { + return TraverseOMPExecutableDirective(S); +} + DEF_TRAVERSE_STMT(OMPParallelDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2288,6 +2313,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective, DEF_TRAVERSE_STMT(OMPForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2308,6 +2336,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, { DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2326,6 +2357,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPOrderedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPAtomicDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTeamsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { @@ -2415,6 +2458,31 @@ RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2426,6 +2494,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } return true; } @@ -2433,6 +2504,12 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( OMPFirstprivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->inits()) { + TRY_TO(TraverseStmt(E)); + } return true; } diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index ce8b8b7dbcd6..a39888f9e1f0 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -43,6 +43,7 @@ class Stmt; class StringLiteral; class TemplateArgumentList; class TemplateParameterList; +class TypeAliasTemplateDecl; class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; @@ -67,6 +68,9 @@ public: /// \brief Return the TypeLoc wrapper for the type source info. TypeLoc getTypeLoc() const; // implemented in TypeLoc.h + + /// \brief Override the type stored in this TypeSourceInfo. Use with caution! + void overrideType(QualType T) { Ty = T; } }; /// TranslationUnitDecl - The top declaration context. @@ -288,6 +292,8 @@ public: return const_cast<NamedDecl*>(this)->getMostRecentDecl(); } + ObjCStringFormatFamily getObjCFStringFormattingFamily() const; + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstNamed && K <= lastNamed; } }; @@ -305,6 +311,8 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { class LabelDecl : public NamedDecl { void anchor() override; LabelStmt *TheStmt; + StringRef MSAsmName; + bool MSAsmNameResolved; /// LocStart - For normal labels, this is the same as the main declaration /// label, i.e., the location of the identifier; for GNU local labels, /// this is the location of the __label__ keyword. @@ -312,7 +320,10 @@ class LabelDecl : public NamedDecl { LabelDecl(DeclContext *DC, SourceLocation IdentL, IdentifierInfo *II, LabelStmt *S, SourceLocation StartL) - : NamedDecl(Label, DC, IdentL, II), TheStmt(S), LocStart(StartL) {} + : NamedDecl(Label, DC, IdentL, II), + TheStmt(S), + MSAsmNameResolved(false), + LocStart(StartL) {} public: static LabelDecl *Create(ASTContext &C, DeclContext *DC, @@ -332,6 +343,12 @@ public: return SourceRange(LocStart, getLocation()); } + bool isMSAsmLabel() const { return MSAsmName.size() != 0; } + bool isResolvedMSAsmLabel() const { return isMSAsmLabel() && MSAsmNameResolved; } + void setMSAsmLabel(StringRef Name); + StringRef getMSAsmLabel() const { return MSAsmName; } + void setMSAsmLabelResolved() { MSAsmNameResolved = true; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Label; } @@ -648,8 +665,6 @@ struct EvaluatedStmt { /// declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: - typedef clang::StorageClass StorageClass; - /// getStorageClassSpecifierString - Return the string used to /// specify the storage class \p SC. /// @@ -891,6 +906,11 @@ public: return false; } + /// \brief Similar to isLocalVarDecl but also includes parameters. + bool isLocalVarDeclOrParm() const { + return isLocalVarDecl() || getKind() == Decl::ParmVar; + } + /// isFunctionOrMethodVarDecl - Similar to isLocalVarDecl, but /// excludes variables declared in blocks. bool isFunctionOrMethodVarDecl() const { @@ -1423,8 +1443,6 @@ private: class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: - typedef clang::StorageClass StorageClass; - /// \brief The kind of templated function a FunctionDecl can be. enum TemplatedKind { TK_NonTemplate, @@ -1650,7 +1668,7 @@ public: /// unnecessary AST de-serialization of the body. Stmt *getBody(const FunctionDecl *&Definition) const; - Stmt *getBody() const override { + Stmt *getBody() const override { const FunctionDecl* Definition; return getBody(Definition); } @@ -1880,7 +1898,7 @@ public: return llvm::makeArrayRef(ParamInfo, getNumParams()); } - const ArrayRef<NamedDecl *> &getDeclsInPrototypeScope() const { + ArrayRef<NamedDecl *> getDeclsInPrototypeScope() const { return DeclsInPrototypeScope; } void setDeclsInPrototypeScope(ArrayRef<NamedDecl *> NewDecls); @@ -2154,17 +2172,41 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { bool Mutable : 1; mutable unsigned CachedFieldIndex : 31; - /// \brief An InClassInitStyle value, and either a bit width expression (if - /// the InClassInitStyle value is ICIS_NoInit), or a pointer to the in-class - /// initializer for this field (otherwise). + /// The kinds of value we can store in InitializerOrBitWidth. /// - /// We can safely combine these two because in-class initializers are not - /// permitted for bit-fields. + /// Note that this is compatible with InClassInitStyle except for + /// ISK_CapturedVLAType. + enum InitStorageKind { + /// If the pointer is null, there's nothing special. Otherwise, + /// this is a bitfield and the pointer is the Expr* storing the + /// bit-width. + ISK_BitWidthOrNothing = (unsigned) ICIS_NoInit, + + /// The pointer is an (optional due to delayed parsing) Expr* + /// holding the copy-initializer. + ISK_InClassCopyInit = (unsigned) ICIS_CopyInit, + + /// The pointer is an (optional due to delayed parsing) Expr* + /// holding the list-initializer. + ISK_InClassListInit = (unsigned) ICIS_ListInit, + + /// The pointer is a VariableArrayType* that's been captured; + /// the enclosing context is a lambda or captured statement. + ISK_CapturedVLAType, + }; + + /// \brief Storage for either the bit-width, the in-class + /// initializer, or the captured variable length array bound. + /// + /// We can safely combine these because in-class initializers are + /// not permitted for bit-fields, and both are exclusive with VLA + /// captures. /// - /// If the InClassInitStyle is not ICIS_NoInit and the initializer is null, - /// then this field has an in-class initializer which has not yet been parsed + /// If the storage kind is ISK_InClassCopyInit or + /// ISK_InClassListInit, but the initializer is null, then this + /// field has an in-class initializer which has not yet been parsed /// and attached. - llvm::PointerIntPair<Expr *, 2, unsigned> InitializerOrBitWidth; + llvm::PointerIntPair<void *, 2, InitStorageKind> InitStorage; protected: FieldDecl(Kind DK, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -2172,7 +2214,7 @@ protected: InClassInitStyle InitStyle) : DeclaratorDecl(DK, DC, IdLoc, Id, T, TInfo, StartLoc), Mutable(Mutable), CachedFieldIndex(0), - InitializerOrBitWidth(BW, InitStyle) { + InitStorage(BW, (InitStorageKind) InitStyle) { assert((!BW || InitStyle == ICIS_NoInit) && "got initializer for bitfield"); } @@ -2192,10 +2234,10 @@ public: /// isMutable - Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } - /// isBitfield - Determines whether this field is a bitfield. + /// \brief Determines whether this field is a bitfield. bool isBitField() const { - return getInClassInitStyle() == ICIS_NoInit && - InitializerOrBitWidth.getPointer(); + return InitStorage.getInt() == ISK_BitWidthOrNothing && + InitStorage.getPointer() != nullptr; } /// @brief Determines whether this is an unnamed bitfield. @@ -2208,24 +2250,34 @@ public: bool isAnonymousStructOrUnion() const; Expr *getBitWidth() const { - return isBitField() ? InitializerOrBitWidth.getPointer() : nullptr; + return isBitField() + ? static_cast<Expr *>(InitStorage.getPointer()) + : nullptr; } unsigned getBitWidthValue(const ASTContext &Ctx) const; /// setBitWidth - Set the bit-field width for this member. // Note: used by some clients (i.e., do not remove it). - void setBitWidth(Expr *Width); + void setBitWidth(Expr *Width) { + assert(InitStorage.getInt() == ISK_BitWidthOrNothing && + InitStorage.getPointer() == nullptr && + "bit width, initializer or captured type already set"); + InitStorage.setPointerAndInt(Width, ISK_BitWidthOrNothing); + } + /// removeBitWidth - Remove the bit-field width from this member. // Note: used by some clients (i.e., do not remove it). void removeBitWidth() { assert(isBitField() && "no bitfield width to remove"); - InitializerOrBitWidth.setPointer(nullptr); + InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); } /// getInClassInitStyle - Get the kind of (C++11) in-class initializer which /// this field has. InClassInitStyle getInClassInitStyle() const { - return static_cast<InClassInitStyle>(InitializerOrBitWidth.getInt()); + InitStorageKind storageKind = InitStorage.getInt(); + return (storageKind == ISK_CapturedVLAType + ? ICIS_NoInit : (InClassInitStyle) storageKind); } /// hasInClassInitializer - Determine whether this member has a C++11 in-class @@ -2233,24 +2285,47 @@ public: bool hasInClassInitializer() const { return getInClassInitStyle() != ICIS_NoInit; } + /// getInClassInitializer - Get the C++11 in-class initializer for this /// member, or null if one has not been set. If a valid declaration has an /// in-class initializer, but this returns null, then we have not parsed and /// attached it yet. Expr *getInClassInitializer() const { - return hasInClassInitializer() ? InitializerOrBitWidth.getPointer() - : nullptr; + return hasInClassInitializer() + ? static_cast<Expr *>(InitStorage.getPointer()) + : nullptr; } + /// setInClassInitializer - Set the C++11 in-class initializer for this /// member. - void setInClassInitializer(Expr *Init); + void setInClassInitializer(Expr *Init) { + assert(hasInClassInitializer() && + InitStorage.getPointer() == nullptr && + "bit width, initializer or captured type already set"); + InitStorage.setPointer(Init); + } + /// removeInClassInitializer - Remove the C++11 in-class initializer from this /// member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); - InitializerOrBitWidth.setPointer(nullptr); - InitializerOrBitWidth.setInt(ICIS_NoInit); + InitStorage.setPointerAndInt(nullptr, ISK_BitWidthOrNothing); + } + + /// \brief Determine whether this member captures the variable length array + /// type. + bool hasCapturedVLAType() const { + return InitStorage.getInt() == ISK_CapturedVLAType; + } + + /// \brief Get the captured variable length array type. + const VariableArrayType *getCapturedVLAType() const { + return hasCapturedVLAType() ? static_cast<const VariableArrayType *>( + InitStorage.getPointer()) + : nullptr; } + /// \brief Set the captured variable length array type for this field. + void setCapturedVLAType(const VariableArrayType *VLAType); /// getParent - Returns the parent of this field declaration, which /// is the struct in which this method is defined. @@ -2492,9 +2567,13 @@ public: /// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x /// alias-declaration. class TypeAliasDecl : public TypedefNameDecl { + /// The template for which this is the pattern, if any. + TypeAliasTemplateDecl *Template; + TypeAliasDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) - : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo) {} + : TypedefNameDecl(TypeAlias, C, DC, StartLoc, IdLoc, Id, TInfo), + Template(nullptr) {} public: static TypeAliasDecl *Create(ASTContext &C, DeclContext *DC, @@ -2504,6 +2583,9 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + TypeAliasTemplateDecl *getDescribedAliasTemplate() const { return Template; } + void setDescribedAliasTemplate(TypeAliasTemplateDecl *TAT) { Template = TAT; } + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TypeAlias; } @@ -2647,7 +2729,7 @@ public: } /// isThisDeclarationADefinition() - Return true if this declaration - /// is a completion definintion of the type. Provided for consistency. + /// is a completion definition of the type. Provided for consistency. bool isThisDeclarationADefinition() const { return isCompleteDefinition(); } @@ -3136,6 +3218,17 @@ public: /// \endcode bool isInjectedClassName() const; + /// \brief Determine whether this record is a class describing a lambda + /// function object. + bool isLambda() const; + + /// \brief Determine whether this record is a record for captured variables in + /// CapturedStmt construct. + bool isCapturedRecord() const; + /// \brief Mark the record as a record for captured variables in CapturedStmt + /// construct. + void setCapturedRecord(); + /// getDefinition - Returns the RecordDecl that actually defines /// this struct/union/class. When determining whether or not a /// struct/union/class is completely defined, one should use this @@ -3181,6 +3274,15 @@ public: /// commandline option. bool isMsStruct(const ASTContext &C) const; + /// \brief Whether we are allowed to insert extra padding between fields. + /// These padding are added to help AddressSanitizer detect + /// intra-object-overflow bugs. + bool mayInsertExtraPadding(bool EmitRemark = false) const; + + /// Finds the first data member which has a name. + /// nullptr is returned if no named data member exists. + const FieldDecl *findFirstNamedDataMember() const; + private: /// \brief Deserialize just the fields. void LoadFieldsFromExternalStorage() const; diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 607ca4ec27c6..984ab13df426 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -48,6 +48,7 @@ class ObjCInterfaceDecl; class ObjCMethodDecl; class ObjCProtocolDecl; struct PrintingPolicy; +class RecordDecl; class Stmt; class StoredDeclsMap; class TranslationUnitDecl; @@ -515,9 +516,13 @@ public: /// indicating the declaration is used. void markUsed(ASTContext &C); - /// \brief Whether this declaration was referenced. + /// \brief Whether any declaration of this entity was referenced. bool isReferenced() const; + /// \brief Whether this declaration was referenced. This should not be relied + /// upon for anything other than debugging. + bool isThisDeclarationReferenced() const { return Referenced; } + void setReferenced(bool R = true) { Referenced = R; } /// \brief Whether this declaration is a top-level declaration (function, @@ -675,9 +680,9 @@ public: return const_cast<Decl*>(this)->getLexicalDeclContext(); } - virtual bool isOutOfLine() const { - return getLexicalDeclContext() != getDeclContext(); - } + /// Determine whether this declaration is declared out of line (outside its + /// semantic context). + virtual bool isOutOfLine() const; /// setDeclContext - Set both the semantic and lexical DeclContext /// to DC. @@ -1234,6 +1239,12 @@ public: return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); } + /// \brief Retrieve the outermost lexically enclosing record context. + RecordDecl *getOuterLexicalRecordContext(); + const RecordDecl *getOuterLexicalRecordContext() const { + return const_cast<DeclContext *>(this)->getOuterLexicalRecordContext(); + } + /// \brief Test if this context is part of the enclosing namespace set of /// the context NS, as defined in C++0x [namespace.def]p9. If either context /// isn't a namespace, this is equivalent to Equals(). @@ -1642,7 +1653,7 @@ public: void dumpDeclContext() const; void dumpLookups() const; - void dumpLookups(llvm::raw_ostream &OS) const; + void dumpLookups(llvm::raw_ostream &OS, bool DumpDecls = false) const; private: void reconcileExternalVisibleStorage() const; diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 72fad7c28e49..027b41e27da3 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -538,6 +538,12 @@ class CXXRecordDecl : public RecordDecl { ManglingNumber(0), ContextDecl(nullptr), Captures(nullptr), MethodTyInfo(Info) { IsLambda = true; + + // C++11 [expr.prim.lambda]p3: + // This class type is neither an aggregate nor a literal type. + Aggregate = false; + PlainOldData = false; + HasNonLiteralTypeFieldsOrBases = true; } /// \brief Whether this lambda is known to be dependent, even if its @@ -820,7 +826,11 @@ public: /// This value is used for lazy creation of default constructors. bool needsImplicitDefaultConstructor() const { return !data().UserDeclaredConstructor && - !(data().DeclaredSpecialMembers & SMF_DefaultConstructor); + !(data().DeclaredSpecialMembers & SMF_DefaultConstructor) && + // C++14 [expr.prim.lambda]p20: + // The closure type associated with a lambda-expression has no + // default constructor. + !isLambda(); } /// \brief Determine whether this class has any user-declared constructors. @@ -1371,6 +1381,15 @@ public: /// \brief Set the kind of specialization or template instantiation this is. void setTemplateSpecializationKind(TemplateSpecializationKind TSK); + /// \brief Retrieve the record declaration from which this record could be + /// instantiated. Returns null if this class is not a template instantiation. + const CXXRecordDecl *getTemplateInstantiationPattern() const; + + CXXRecordDecl *getTemplateInstantiationPattern() { + return const_cast<CXXRecordDecl *>(const_cast<const CXXRecordDecl *>(this) + ->getTemplateInstantiationPattern()); + } + /// \brief Returns the destructor decl for this class. CXXDestructorDecl *getDestructor() const; @@ -2104,8 +2123,8 @@ public: } ArrayRef<VarDecl *> getArrayIndexes() { assert(getNumArrayIndices() != 0 && "Getting indexes for non-array init"); - return ArrayRef<VarDecl *>(reinterpret_cast<VarDecl **>(this + 1), - getNumArrayIndices()); + return llvm::makeArrayRef(reinterpret_cast<VarDecl **>(this + 1), + getNumArrayIndices()); } /// \brief Get the initializer. @@ -2636,7 +2655,8 @@ public: /// \code /// namespace Foo = Bar; /// \endcode -class NamespaceAliasDecl : public NamedDecl { +class NamespaceAliasDecl : public NamedDecl, + public Redeclarable<NamespaceAliasDecl> { void anchor() override; /// \brief The location of the \c namespace keyword. @@ -2654,17 +2674,47 @@ class NamespaceAliasDecl : public NamedDecl { /// a NamespaceAliasDecl. NamedDecl *Namespace; - NamespaceAliasDecl(DeclContext *DC, SourceLocation NamespaceLoc, - SourceLocation AliasLoc, IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, + NamespaceAliasDecl(ASTContext &C, DeclContext *DC, + SourceLocation NamespaceLoc, SourceLocation AliasLoc, + IdentifierInfo *Alias, NestedNameSpecifierLoc QualifierLoc, SourceLocation IdentLoc, NamedDecl *Namespace) - : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), - NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), - QualifierLoc(QualifierLoc), Namespace(Namespace) { } + : NamedDecl(NamespaceAlias, DC, AliasLoc, Alias), redeclarable_base(C), + NamespaceLoc(NamespaceLoc), IdentLoc(IdentLoc), + QualifierLoc(QualifierLoc), Namespace(Namespace) {} + + typedef Redeclarable<NamespaceAliasDecl> redeclarable_base; + NamespaceAliasDecl *getNextRedeclarationImpl() override; + NamespaceAliasDecl *getPreviousDeclImpl() override; + NamespaceAliasDecl *getMostRecentDeclImpl() override; friend class ASTDeclReader; public: + static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, + SourceLocation NamespaceLoc, + SourceLocation AliasLoc, + IdentifierInfo *Alias, + NestedNameSpecifierLoc QualifierLoc, + SourceLocation IdentLoc, + NamedDecl *Namespace); + + static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); + + typedef redeclarable_base::redecl_range redecl_range; + typedef redeclarable_base::redecl_iterator redecl_iterator; + using redeclarable_base::redecls_begin; + using redeclarable_base::redecls_end; + using redeclarable_base::redecls; + using redeclarable_base::getPreviousDecl; + using redeclarable_base::getMostRecentDecl; + + NamespaceAliasDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const NamespaceAliasDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + /// \brief Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } @@ -2701,16 +2751,6 @@ public: /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } - static NamespaceAliasDecl *Create(ASTContext &C, DeclContext *DC, - SourceLocation NamespaceLoc, - SourceLocation AliasLoc, - IdentifierInfo *Alias, - NestedNameSpecifierLoc QualifierLoc, - SourceLocation IdentLoc, - NamedDecl *Namespace); - - static NamespaceAliasDecl *CreateDeserialized(ASTContext &C, unsigned ID); - SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(NamespaceLoc, IdentLoc); } @@ -2824,7 +2864,7 @@ public: /// \code /// using someNameSpace::someIdentifier; /// \endcode -class UsingDecl : public NamedDecl { +class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { void anchor() override; /// \brief The source location of the 'using' keyword itself. @@ -2948,6 +2988,10 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + /// Retrieves the canonical declaration of this declaration. + UsingDecl *getCanonicalDecl() override { return getFirstDecl(); } + const UsingDecl *getCanonicalDecl() const { return getFirstDecl(); } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == Using; } @@ -2966,7 +3010,8 @@ public: /// using Base<T>::foo; /// }; /// \endcode -class UnresolvedUsingValueDecl : public ValueDecl { +class UnresolvedUsingValueDecl : public ValueDecl, + public Mergeable<UnresolvedUsingValueDecl> { void anchor() override; /// \brief The source location of the 'using' keyword @@ -3022,6 +3067,14 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; + /// Retrieves the canonical declaration of this declaration. + UnresolvedUsingValueDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const UnresolvedUsingValueDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } @@ -3040,7 +3093,9 @@ public: /// /// The type associated with an unresolved using typename decl is /// currently always a typename type. -class UnresolvedUsingTypenameDecl : public TypeDecl { +class UnresolvedUsingTypenameDecl + : public TypeDecl, + public Mergeable<UnresolvedUsingTypenameDecl> { void anchor() override; /// \brief The source location of the 'typename' keyword @@ -3084,6 +3139,14 @@ public: static UnresolvedUsingTypenameDecl * CreateDeserialized(ASTContext &C, unsigned ID); + /// Retrieves the canonical declaration of this declaration. + UnresolvedUsingTypenameDecl *getCanonicalDecl() override { + return getFirstDecl(); + } + const UnresolvedUsingTypenameDecl *getCanonicalDecl() const { + return getFirstDecl(); + } + static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h index d2016af89f13..eba2266724fd 100644 --- a/include/clang/AST/DeclLookups.h +++ b/include/clang/AST/DeclLookups.h @@ -75,7 +75,10 @@ inline DeclContext::lookups_range DeclContext::lookups() const { if (StoredDeclsMap *Map = Primary->buildLookup()) return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), all_lookups_iterator(Map->end(), Map->end())); - return lookups_range(); + + // Synthesize an empty range. This requires that two default constructed + // versions of these iterators form a valid empty range. + return lookups_range(all_lookups_iterator(), all_lookups_iterator()); } inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { @@ -91,7 +94,10 @@ inline DeclContext::lookups_range DeclContext::noload_lookups() const { if (StoredDeclsMap *Map = Primary->getLookupPtr()) return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), all_lookups_iterator(Map->end(), Map->end())); - return lookups_range(); + + // Synthesize an empty range. This requires that two default constructed + // versions of these iterators form a valid empty range. + return lookups_range(all_lookups_iterator(), all_lookups_iterator()); } inline diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index db3b0849382a..55d4b0f16953 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -329,6 +329,7 @@ public: QualType getReturnType() const { return MethodDeclType; } void setReturnType(QualType T) { MethodDeclType = T; } + SourceRange getReturnTypeSourceRange() const; /// \brief Determine the type of an expression that sends a message to this /// function. @@ -378,8 +379,7 @@ public: /// ignored. void setMethodParams(ASTContext &C, ArrayRef<ParmVarDecl*> Params, - ArrayRef<SourceLocation> SelLocs = - ArrayRef<SourceLocation>()); + ArrayRef<SourceLocation> SelLocs = llvm::None); // Iterator access to parameter types. typedef std::const_mem_fun_t<QualType, ParmVarDecl> deref_fun; @@ -591,7 +591,8 @@ public: bool HasUserDeclaredSetterMethod(const ObjCPropertyDecl *P) const; ObjCIvarDecl *getIvarDecl(IdentifierInfo *Id) const; - ObjCPropertyDecl *FindPropertyDeclaration(IdentifierInfo *PropertyId) const; + ObjCPropertyDecl * + FindPropertyDeclaration(const IdentifierInfo *PropertyId) const; typedef llvm::DenseMap<IdentifierInfo*, ObjCPropertyDecl*> PropertyMap; @@ -2354,7 +2355,7 @@ public: /// Lookup a property by name in the specified DeclContext. static ObjCPropertyDecl *findPropertyDecl(const DeclContext *DC, - IdentifierInfo *propertyID); + const IdentifierInfo *propertyID); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == ObjCProperty; } diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index 1b329dcd0052..7f0616f1e603 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -12,13 +12,14 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_OPENMP_H -#define LLVM_CLANG_AST_OPENMP_H +#ifndef LLVM_CLANG_AST_DECLOPENMP_H +#define LLVM_CLANG_AST_DECLOPENMP_H #include "clang/AST/DeclBase.h" #include "llvm/ADT/ArrayRef.h" namespace clang { +class Expr; /// \brief This represents '#pragma omp threadprivate ...' directive. /// For example, in the following, both 'a' and 'A::b' are threadprivate: @@ -42,9 +43,8 @@ class OMPThreadPrivateDecl : public Decl { Decl(DK, DC, L), NumVars(0) { } ArrayRef<const Expr *> getVars() const { - return ArrayRef<const Expr *>( - reinterpret_cast<const Expr * const *>(this + 1), - NumVars); + return llvm::makeArrayRef(reinterpret_cast<const Expr * const *>(this + 1), + NumVars); } MutableArrayRef<Expr *> getVars() { diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 980a06e35b70..9283d2dc4350 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -87,10 +87,10 @@ public: unsigned size() const { return NumParams; } ArrayRef<NamedDecl*> asArray() { - return ArrayRef<NamedDecl*>(begin(), size()); + return llvm::makeArrayRef(begin(), end()); } ArrayRef<const NamedDecl*> asArray() const { - return ArrayRef<const NamedDecl*>(begin(), size()); + return llvm::makeArrayRef(begin(), size()); } NamedDecl* getParam(unsigned Idx) { @@ -204,7 +204,7 @@ public: /// \brief Produce this as an array ref. ArrayRef<TemplateArgument> asArray() const { - return ArrayRef<TemplateArgument>(data(), size()); + return llvm::makeArrayRef(data(), size()); } /// \brief Retrieve the number of template arguments in this @@ -236,7 +236,7 @@ protected: TemplateParams(nullptr) {} // Construct a template decl with the given name and parameters. - // Used when there is not templated element (tt-params, alias?). + // 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), diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 3076b30cd377..49e51e09b830 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -59,6 +59,7 @@ public: CXXLiteralOperatorName, CXXUsingDirective }; + static const unsigned NumNameKinds = CXXUsingDirective + 1; private: /// StoredNameKind - The kind of name that is actually stored in the diff --git a/include/clang/AST/DependentDiagnostic.h b/include/clang/AST/DependentDiagnostic.h index 63047ec4db84..8e038c83c989 100644 --- a/include/clang/AST/DependentDiagnostic.h +++ b/include/clang/AST/DependentDiagnostic.h @@ -15,8 +15,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H -#define LLVM_CLANG_AST_DEPENDENT_DIAGNOSTIC_H +#ifndef LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H +#define LLVM_CLANG_AST_DEPENDENTDIAGNOSTIC_H #include "clang/AST/DeclBase.h" #include "clang/AST/DeclContextInternals.h" @@ -178,7 +178,8 @@ inline DeclContext::ddiag_range DeclContext::ddiags() const { = static_cast<DependentStoredDeclsMap*>(getPrimaryContext()->getLookupPtr()); if (!Map) - return ddiag_range(); + // Return an empty range using the always-end default constructor. + return ddiag_range(ddiag_iterator(), ddiag_iterator()); return ddiag_range(ddiag_iterator(Map->FirstDiagnostic), ddiag_iterator()); } diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index 12c4fcc49b01..59de104b83f9 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -56,6 +56,17 @@ public: return this->Visit(E->getChosenSubExpr()); } + void VisitGenericSelectionExpr(GenericSelectionExpr *E) { + // The controlling expression of a generic selection is not evaluated. + + // Don't visit either child expression if the condition is type-dependent. + if (E->isResultDependent()) + return; + // Only the selected subexpression matters; the other subexpressions and the + // controlling expression are not evaluated. + return this->Visit(E->getResultExpr()); + } + void VisitDesignatedInitExpr(DesignatedInitExpr *E) { // Only the actual initializer matters; the designators are all constant // expressions. diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index b4bb0b6b6440..c410f2358bc7 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -45,6 +45,7 @@ namespace clang { class ObjCPropertyRefExpr; class OpaqueValueExpr; class ParmVarDecl; + class StringLiteral; class TargetInfo; class ValueDecl; @@ -124,8 +125,7 @@ public: QualType getType() const { return TR; } void setType(QualType t) { // In C++, the type of an expression is always adjusted so that it - // will not have reference type an expression will never have - // reference type (C++ [expr]p6). Use + // will not have reference type (C++ [expr]p6). Use // QualType::getNonReferenceType() to retrieve the non-reference // type. Additionally, inspect Expr::isLvalue to determine whether // an expression that is adjusted in this manner should be @@ -586,8 +586,13 @@ public: /// HasSideEffects - This routine returns true for all those expressions /// which have any effect other than producing a value. Example is a function - /// call, volatile variable read, or throwing an exception. - bool HasSideEffects(const ASTContext &Ctx) const; + /// call, volatile variable read, or throwing an exception. If + /// IncludePossibleEffects is false, this call treats certain expressions with + /// potential side effects (such as function call-like expressions, + /// instantiation-dependent expressions, or invocations from a macro) as not + /// having side effects. + bool HasSideEffects(const ASTContext &Ctx, + bool IncludePossibleEffects = true) const; /// \brief Determine whether this expression involves a call to any function /// that is not trivial. @@ -886,9 +891,9 @@ public: /// DeclRefExprBits.HasTemplateKWAndArgsInfo: /// Specifies when this declaration reference expression has an explicit /// C++ template keyword and/or template argument list. -/// DeclRefExprBits.RefersToEnclosingLocal +/// DeclRefExprBits.RefersToEnclosingVariableOrCapture /// Specifies when this declaration reference expression (validly) -/// refers to a local variable from a different function. +/// refers to an enclosed local or a captured variable. class DeclRefExpr : public Expr { /// \brief The declaration that we are referencing. ValueDecl *D; @@ -933,7 +938,7 @@ class DeclRefExpr : public Expr { DeclRefExpr(const ASTContext &Ctx, NestedNameSpecifierLoc QualifierLoc, SourceLocation TemplateKWLoc, - ValueDecl *D, bool refersToEnclosingLocal, + ValueDecl *D, bool RefersToEnlosingVariableOrCapture, const DeclarationNameInfo &NameInfo, NamedDecl *FoundD, const TemplateArgumentListInfo *TemplateArgs, @@ -948,7 +953,7 @@ class DeclRefExpr : public Expr { void computeDependence(const ASTContext &C); public: - DeclRefExpr(ValueDecl *D, bool refersToEnclosingLocal, QualType T, + DeclRefExpr(ValueDecl *D, bool RefersToEnclosingVariableOrCapture, QualType T, ExprValueKind VK, SourceLocation L, const DeclarationNameLoc &LocInfo = DeclarationNameLoc()) : Expr(DeclRefExprClass, T, VK, OK_Ordinary, false, false, false, false), @@ -957,20 +962,22 @@ public: DeclRefExprBits.HasTemplateKWAndArgsInfo = 0; DeclRefExprBits.HasFoundDecl = 0; DeclRefExprBits.HadMultipleCandidates = 0; - DeclRefExprBits.RefersToEnclosingLocal = refersToEnclosingLocal; + DeclRefExprBits.RefersToEnclosingVariableOrCapture = + RefersToEnclosingVariableOrCapture; computeDependence(D->getASTContext()); } static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal, - SourceLocation NameLoc, QualType T, ExprValueKind VK, - NamedDecl *FoundD = nullptr, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, SourceLocation NameLoc, + QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr); static DeclRefExpr * Create(const ASTContext &Context, NestedNameSpecifierLoc QualifierLoc, - SourceLocation TemplateKWLoc, ValueDecl *D, bool isEnclosingLocal, + SourceLocation TemplateKWLoc, ValueDecl *D, + bool RefersToEnclosingVariableOrCapture, const DeclarationNameInfo &NameInfo, QualType T, ExprValueKind VK, NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr); @@ -1144,10 +1151,10 @@ public: DeclRefExprBits.HadMultipleCandidates = V; } - /// Does this DeclRefExpr refer to a local declaration from an - /// enclosing function scope? - bool refersToEnclosingLocal() const { - return DeclRefExprBits.RefersToEnclosingLocal; + /// \brief Does this DeclRefExpr refer to an enclosing local or a captured + /// variable? + bool refersToEnclosingVariableOrCapture() const { + return DeclRefExprBits.RefersToEnclosingVariableOrCapture; } static bool classof(const Stmt *T) { @@ -1161,7 +1168,7 @@ public: friend class ASTStmtWriter; }; -/// PredefinedExpr - [C99 6.4.2.2] - A predefined identifier such as __func__. +/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr : public Expr { public: enum IdentType { @@ -1171,7 +1178,7 @@ public: FuncDName, FuncSig, PrettyFunction, - /// PrettyFunctionNoVirtual - The same as PrettyFunction, except that the + /// \brief The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. PrettyFunctionNoVirtual }; @@ -1179,24 +1186,27 @@ public: private: SourceLocation Loc; IdentType Type; + Stmt *FnName; + public: - PredefinedExpr(SourceLocation l, QualType type, IdentType IT) - : Expr(PredefinedExprClass, type, VK_LValue, OK_Ordinary, - type->isDependentType(), type->isDependentType(), - type->isInstantiationDependentType(), - /*ContainsUnexpandedParameterPack=*/false), - Loc(l), Type(IT) {} + PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, + StringLiteral *SL); /// \brief Construct an empty predefined expression. explicit PredefinedExpr(EmptyShell Empty) - : Expr(PredefinedExprClass, Empty) { } + : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} IdentType getIdentType() const { return Type; } - void setIdentType(IdentType IT) { Type = IT; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation L) { Loc = L; } + StringLiteral *getFunctionName(); + const StringLiteral *getFunctionName() const { + return const_cast<PredefinedExpr *>(this)->getFunctionName(); + } + + static StringRef getIdentTypeName(IdentType IT); static std::string ComputeName(IdentType IT, const Decl *CurrentDecl); SourceLocation getLocStart() const LLVM_READONLY { return Loc; } @@ -1207,7 +1217,9 @@ public: } // Iterators - child_range children() { return child_range(); } + child_range children() { return child_range(&FnName, &FnName + 1); } + + friend class ASTStmtReader; }; /// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without @@ -2212,11 +2224,11 @@ public: /// getArg - Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]); + return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); } const Expr *getArg(unsigned Arg) const { assert(Arg < NumArgs && "Arg access out of range!"); - return cast<Expr>(SubExprs[Arg+getNumPreArgs()+PREARGS_START]); + return cast_or_null<Expr>(SubExprs[Arg + getNumPreArgs() + PREARGS_START]); } /// setArg - Set the specified argument. @@ -2256,8 +2268,8 @@ public: /// interface. This provides efficient reverse iteration of the /// subexpressions. This is currently used for CFG construction. ArrayRef<Stmt*> getRawSubExprs() { - return ArrayRef<Stmt*>(SubExprs, - getNumPreArgs() + PREARGS_START + getNumArgs()); + return llvm::makeArrayRef(SubExprs, + getNumPreArgs() + PREARGS_START + getNumArgs()); } /// getNumCommas - Return the number of commas that must have been present in @@ -2653,9 +2665,6 @@ public: /// representation in the source code (ExplicitCastExpr's derived /// classes). class CastExpr : public Expr { -public: - typedef clang::CastKind CastKind; - private: Stmt *Op; @@ -2673,20 +2682,23 @@ private: } protected: - CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, - const CastKind kind, Expr *op, unsigned BasePathSize) : - Expr(SC, ty, VK, OK_Ordinary, - // Cast expressions are type-dependent if the type is - // dependent (C++ [temp.dep.expr]p3). - ty->isDependentType(), - // Cast expressions are value-dependent if the type is - // dependent or if the subexpression is value-dependent. - ty->isDependentType() || (op && op->isValueDependent()), - (ty->isInstantiationDependentType() || - (op && op->isInstantiationDependent())), - (ty->containsUnexpandedParameterPack() || - (op && op->containsUnexpandedParameterPack()))), - Op(op) { + CastExpr(StmtClass SC, QualType ty, ExprValueKind VK, const CastKind kind, + Expr *op, unsigned BasePathSize) + : Expr(SC, ty, VK, OK_Ordinary, + // Cast expressions are type-dependent if the type is + // dependent (C++ [temp.dep.expr]p3). + ty->isDependentType(), + // Cast expressions are value-dependent if the type is + // dependent or if the subexpression is value-dependent. + ty->isDependentType() || (op && op->isValueDependent()), + (ty->isInstantiationDependentType() || + (op && op->isInstantiationDependent())), + // An implicit cast expression doesn't (lexically) contain an + // unexpanded pack, even if its target type does. + ((SC != ImplicitCastExprClass && + ty->containsUnexpandedParameterPack()) || + (op && op->containsUnexpandedParameterPack()))), + Op(op) { assert(kind != CK_Invalid && "creating cast with invalid cast kind"); CastExprBits.Kind = kind; setBasePathSize(BasePathSize); @@ -4841,6 +4853,24 @@ public: return child_range(SubExprs, SubExprs+NumSubExprs); } }; + +/// TypoExpr - Internal placeholder for expressions where typo correction +/// still needs to be performed and/or an error diagnostic emitted. +class TypoExpr : public Expr { +public: + TypoExpr(QualType T) + : Expr(TypoExprClass, T, VK_LValue, OK_Ordinary, + /*isTypeDependent*/ true, + /*isValueDependent*/ true, + /*isInstantiationDependent*/ true, + /*containsUnexpandedParameterPack*/ false) { + assert(T->isDependentType() && "TypoExpr given a non-dependent type"); + } + + child_range children() { return child_range(); } + SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } +}; } // end namespace clang #endif diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 3a43d6dac140..176817823ea9 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -17,10 +17,10 @@ #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" +#include "clang/AST/LambdaCapture.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/AST/LambdaCapture.h" #include "clang/Basic/TypeTraits.h" #include "llvm/Support/Compiler.h" @@ -967,8 +967,14 @@ public: const FieldDecl *getField() const { return Field; } /// \brief Get the initialization expression that will be used. - const Expr *getExpr() const { return Field->getInClassInitializer(); } - Expr *getExpr() { return Field->getInClassInitializer(); } + const Expr *getExpr() const { + assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); + return Field->getInClassInitializer(); + } + Expr *getExpr() { + assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); + return Field->getInClassInitializer(); + } SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } @@ -1165,6 +1171,13 @@ public: typedef ExprIterator arg_iterator; typedef ConstExprIterator const_arg_iterator; + typedef llvm::iterator_range<arg_iterator> arg_range; + typedef llvm::iterator_range<const_arg_iterator> arg_const_range; + + arg_range arguments() { return arg_range(arg_begin(), arg_end()); } + arg_const_range arguments() const { + return arg_const_range(arg_begin(), arg_end()); + } arg_iterator arg_begin() { return Args; } arg_iterator arg_end() { return Args + NumArgs; } @@ -1569,12 +1582,12 @@ class CXXScalarValueInitExpr : public Expr { public: /// \brief Create an explicitly-written scalar-value initialization /// expression. - CXXScalarValueInitExpr(QualType Type, - TypeSourceInfo *TypeInfo, - SourceLocation rParenLoc ) : - Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, - false, false, Type->isInstantiationDependentType(), false), - RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} + CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, + SourceLocation rParenLoc) + : Expr(CXXScalarValueInitExprClass, Type, VK_RValue, OK_Ordinary, + false, false, Type->isInstantiationDependentType(), + Type->containsUnexpandedParameterPack()), + RParenLoc(rParenLoc), TypeInfo(TypeInfo) {} explicit CXXScalarValueInitExpr(EmptyShell Shell) : Expr(CXXScalarValueInitExprClass, Shell) { } @@ -2113,7 +2126,7 @@ public: /// \brief Retrieve the argument types. ArrayRef<TypeSourceInfo *> getArgs() const { - return ArrayRef<TypeSourceInfo *>(getTypeSourceInfos(), getNumArgs()); + return llvm::makeArrayRef(getTypeSourceInfos(), getNumArgs()); } typedef TypeSourceInfo **arg_iterator; @@ -2767,7 +2780,7 @@ public: ArrayRef<CleanupObject> objects); ArrayRef<CleanupObject> getObjects() const { - return ArrayRef<CleanupObject>(getObjectsBuffer(), getNumObjects()); + return llvm::makeArrayRef(getObjectsBuffer(), getNumObjects()); } unsigned getNumObjects() const { return ExprWithCleanupsBits.NumObjects; } @@ -2902,8 +2915,9 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY { - assert(RParenLoc.isValid() || NumArgs == 1); - return RParenLoc.isValid() ? RParenLoc : getArg(0)->getLocEnd(); + if (!RParenLoc.isValid() && NumArgs > 0) + return getArg(NumArgs - 1)->getLocEnd(); + return RParenLoc; } static bool classof(const Stmt *T) { @@ -3811,6 +3825,69 @@ public: } }; +/// \brief Represents a folding of a pack over an operator. +/// +/// This expression is always dependent and represents a pack expansion of the +/// forms: +/// +/// ( expr op ... ) +/// ( ... op expr ) +/// ( expr op ... op expr ) +class CXXFoldExpr : public Expr { + SourceLocation LParenLoc; + SourceLocation EllipsisLoc; + SourceLocation RParenLoc; + Stmt *SubExprs[2]; + BinaryOperatorKind Opcode; + + friend class ASTStmtReader; + friend class ASTStmtWriter; +public: + CXXFoldExpr(QualType T, SourceLocation LParenLoc, Expr *LHS, + BinaryOperatorKind Opcode, SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc) + : Expr(CXXFoldExprClass, T, VK_RValue, OK_Ordinary, + /*Dependent*/ true, true, true, + /*ContainsUnexpandedParameterPack*/ false), + LParenLoc(LParenLoc), EllipsisLoc(EllipsisLoc), RParenLoc(RParenLoc), + Opcode(Opcode) { + SubExprs[0] = LHS; + SubExprs[1] = RHS; + } + CXXFoldExpr(EmptyShell Empty) : Expr(CXXFoldExprClass, Empty) {} + + Expr *getLHS() const { return static_cast<Expr*>(SubExprs[0]); } + Expr *getRHS() const { return static_cast<Expr*>(SubExprs[1]); } + + /// Does this produce a right-associated sequence of operators? + bool isRightFold() const { + return getLHS() && getLHS()->containsUnexpandedParameterPack(); + } + /// Does this produce a left-associated sequence of operators? + bool isLeftFold() const { return !isRightFold(); } + /// Get the pattern, that is, the operand that contains an unexpanded pack. + Expr *getPattern() const { return isLeftFold() ? getRHS() : getLHS(); } + /// Get the operand that doesn't contain a pack, for a binary fold. + Expr *getInit() const { return isLeftFold() ? getLHS() : getRHS(); } + + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + BinaryOperatorKind getOperator() const { return Opcode; } + + SourceLocation getLocStart() const LLVM_READONLY { + return LParenLoc; + } + SourceLocation getLocEnd() const LLVM_READONLY { + return RParenLoc; + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == CXXFoldExprClass; + } + + // Iterators + child_range children() { return child_range(SubExprs, SubExprs + 2); } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index 817c0cc43131..f296e8f71d30 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -124,6 +124,15 @@ public: // Iterators child_range children() { return child_range(&SubExpr, &SubExpr+1); } + + typedef ConstExprIterator const_arg_iterator; + + const_arg_iterator arg_begin() const { + return reinterpret_cast<Stmt const * const*>(&SubExpr); + } + const_arg_iterator arg_end() const { + return reinterpret_cast<Stmt const * const*>(&SubExpr + 1); + } friend class ASTStmtReader; }; diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index 1e8eff38d3ec..ff1d180ee8c6 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -11,8 +11,8 @@ // construction of AST nodes from some external source. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H -#define LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#ifndef LLVM_CLANG_AST_EXTERNALASTSOURCE_H +#define LLVM_CLANG_AST_EXTERNALASTSOURCE_H #include "clang/AST/CharUnits.h" #include "clang/AST/DeclBase.h" @@ -650,4 +650,4 @@ typedef LazyOffsetPtr<CXXBaseSpecifier, uint64_t, } // end namespace clang -#endif // LLVM_CLANG_AST_EXTERNAL_AST_SOURCE_H +#endif diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h index 8633c9796523..a7468a0fd53f 100644 --- a/include/clang/AST/LambdaCapture.h +++ b/include/clang/AST/LambdaCapture.h @@ -68,13 +68,23 @@ public: /// \brief Determine whether this capture handles the C++ \c this /// pointer. - bool capturesThis() const { return DeclAndBits.getPointer() == nullptr; } + bool capturesThis() const { + return (DeclAndBits.getPointer() == nullptr) && + !(DeclAndBits.getInt() & Capture_ByCopy); + } /// \brief Determine whether this capture handles a variable. bool capturesVariable() const { return dyn_cast_or_null<VarDecl>(DeclAndBits.getPointer()); } + /// \brief Determine whether this captures a variable length array bound + /// expression. + bool capturesVLAType() const { + return (DeclAndBits.getPointer() == nullptr) && + (DeclAndBits.getInt() & Capture_ByCopy); + } + /// \brief Determine whether this is an init-capture. bool isInitCapture() const { return capturesVariable() && getCapturedVar()->isInitCapture(); diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index a8d119971b33..cbe08a1a765e 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -156,6 +156,11 @@ public: virtual void mangleItaniumThreadLocalWrapper(const VarDecl *D, raw_ostream &) = 0; + virtual void mangleCXXCtorComdat(const CXXConstructorDecl *D, + raw_ostream &) = 0; + virtual void mangleCXXDtorComdat(const CXXDestructorDecl *D, + raw_ostream &) = 0; + static bool classof(const MangleContext *C) { return C->getKind() == MK_Itanium; } diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h index 56c995264b32..7a818557fdb7 100644 --- a/include/clang/AST/MangleNumberingContext.h +++ b/include/clang/AST/MangleNumberingContext.h @@ -12,8 +12,8 @@ // literals. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_MANGLENUMBERINGCONTEXT_H -#define LLVM_CLANG_MANGLENUMBERINGCONTEXT_H +#ifndef LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H +#define LLVM_CLANG_AST_MANGLENUMBERINGCONTEXT_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" @@ -30,23 +30,20 @@ class VarDecl; /// \brief Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. -class MangleNumberingContext - : public RefCountedBase<MangleNumberingContext> { - llvm::DenseMap<const Type *, unsigned> ManglingNumbers; - +class MangleNumberingContext : public RefCountedBase<MangleNumberingContext> { public: virtual ~MangleNumberingContext() {} /// \brief Retrieve the mangling number of a new lambda expression with the /// given call operator within this context. - unsigned getManglingNumber(const CXXMethodDecl *CallOperator); + virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0; /// \brief Retrieve the mangling number of a new block literal within this /// context. - unsigned getManglingNumber(const BlockDecl *BD); + virtual unsigned getManglingNumber(const BlockDecl *BD) = 0; /// Static locals are numbered by source order. - unsigned getStaticLocalNumber(const VarDecl *VD); + virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0; /// \brief Retrieve the mangling number of a static local variable within /// this context. @@ -58,6 +55,6 @@ public: virtual unsigned getManglingNumber(const TagDecl *TD, unsigned MSLocalManglingNumber) = 0; }; - + } // end namespace clang #endif diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 0b21b0334812..33fcce2109aa 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -42,7 +42,8 @@ public: NSStr_stringWithUTF8String, NSStr_stringWithCStringEncoding, NSStr_stringWithCString, - NSStr_initWithString + NSStr_initWithString, + NSStr_initWithUTF8String }; static const unsigned NumNSStringMethods = 5; @@ -100,8 +101,8 @@ public: NSDict_objectForKey, NSMutableDict_setObjectForKey }; - static const unsigned NumNSDictionaryMethods = 11; - + static const unsigned NumNSDictionaryMethods = 12; + /// \brief The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; @@ -184,6 +185,9 @@ public: bool isObjCNSIntegerType(QualType T) const; /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. bool isObjCNSUIntegerType(QualType T) const; + /// \brief Returns one of NSIntegral typedef names if \param T is a typedef + /// of that name in objective-c. + StringRef GetNSIntegralKind(QualType T) const; private: bool isObjCTypedef(QualType T, StringRef name, IdentifierInfo *&II) const; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index fc719bdc16c3..518f1232fe8f 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -22,6 +22,7 @@ namespace clang { class ASTContext; +class CXXRecordDecl; class NamespaceAliasDecl; class NamespaceDecl; class IdentifierInfo; @@ -45,7 +46,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// \brief Enumeration describing enum StoredSpecifierKind { StoredIdentifier = 0, - StoredNamespaceOrAlias = 1, + StoredDecl = 1, StoredTypeSpec = 2, StoredTypeSpecWithTemplate = 3 }; @@ -83,7 +84,10 @@ public: /// stored as a Type*. TypeSpecWithTemplate, /// \brief The global specifier '::'. There is no stored value. - Global + Global, + /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of + /// the class it appeared in. + Super }; private: @@ -143,6 +147,11 @@ public: /// scope. static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); + /// \brief Returns the nested name specifier representing the __super scope + /// for the given CXXRecordDecl. + static NestedNameSpecifier *SuperSpecifier(const ASTContext &Context, + CXXRecordDecl *RD); + /// \brief Return the prefix of this nested name specifier. /// /// The prefix contains all of the parts of the nested name @@ -172,6 +181,10 @@ public: /// specifier. NamespaceAliasDecl *getAsNamespaceAlias() const; + /// \brief Retrieve the record declaration stored in this nested name + /// specifier. + CXXRecordDecl *getAsRecordDecl() const; + /// \brief Retrieve the type stored in this nested name specifier. const Type *getAsType() const { if (Prefix.getInt() == StoredTypeSpec || @@ -421,7 +434,22 @@ public: /// \brief Turn this (empty) nested-name-specifier into the global /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); - + + /// \brief Turns this (empty) nested-name-specifier into '__super' + /// nested-name-specifier. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param RD The declaration of the class in which nested-name-specifier + /// appeared. + /// + /// \param SuperLoc The location of the '__super' keyword. + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, SourceLocation ColonColonLoc); /// \brief Make a new nested-name-specifier from incomplete source-location /// information. /// diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 3345959653a6..0c3002c103e2 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -61,7 +61,7 @@ public: ConstStmtRange children() const { return const_cast<OMPClause *>(this)->children(); } - static bool classof(const OMPClause *T) { return true; } + static bool classof(const OMPClause *) { return true; } }; /// \brief This represents clauses with the list of variables like 'private', @@ -135,10 +135,10 @@ public: /// \brief Fetches list of all variables in the clause. ArrayRef<const Expr *> getVarRefs() const { - return ArrayRef<const Expr *>( + return llvm::makeArrayRef( reinterpret_cast<const Expr *const *>( reinterpret_cast<const char *>(this) + - llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<Expr *>())), + llvm::RoundUpToAlignment(sizeof(T), llvm::alignOf<const Expr *>())), NumVars); } }; @@ -770,6 +770,153 @@ public: StmtRange children() { return StmtRange(); } }; +/// \brief This represents 'read' clause in the '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic read +/// \endcode +/// In this example directive '#pragma omp atomic' has 'read' clause. +/// +class OMPReadClause : public OMPClause { +public: + /// \brief Build 'read' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_read, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_read; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'write' clause in the '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic write +/// \endcode +/// In this example directive '#pragma omp atomic' has 'write' clause. +/// +class OMPWriteClause : public OMPClause { +public: + /// \brief Build 'write' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_write, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPWriteClause() + : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_write; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'update' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic update +/// \endcode +/// In this example directive '#pragma omp atomic' has 'update' clause. +/// +class OMPUpdateClause : public OMPClause { +public: + /// \brief Build 'update' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_update, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPUpdateClause() + : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_update; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'capture' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic capture +/// \endcode +/// In this example directive '#pragma omp atomic' has 'capture' clause. +/// +class OMPCaptureClause : public OMPClause { +public: + /// \brief Build 'capture' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_capture, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPCaptureClause() + : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_capture; + } + + StmtRange children() { return StmtRange(); } +}; + +/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic' +/// directive. +/// +/// \code +/// #pragma omp atomic seq_cst +/// \endcode +/// In this example directive '#pragma omp atomic' has 'seq_cst' clause. +/// +class OMPSeqCstClause : public OMPClause { +public: + /// \brief Build 'seq_cst' clause. + /// + /// \param StartLoc Starting location of the clause. + /// \param EndLoc Ending location of the clause. + /// + OMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPClause(OMPC_seq_cst, StartLoc, EndLoc) {} + + /// \brief Build an empty clause. + /// + OMPSeqCstClause() + : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {} + + static bool classof(const OMPClause *T) { + return T->getClauseKind() == OMPC_seq_cst; + } + + StmtRange children() { return StmtRange(); } +}; + /// \brief This represents clause 'private' in the '#pragma omp ...' directives. /// /// \code @@ -779,6 +926,7 @@ public: /// with the variables 'a' and 'b'. /// class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> { + friend class OMPClauseReader; /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -800,6 +948,20 @@ class OMPPrivateClause : public OMPVarListClause<OMPPrivateClause> { SourceLocation(), SourceLocation(), N) {} + /// \brief Sets the list of references to private copies with initializers for + /// new private variables. + /// \param VL List of references. + void setPrivateCopies(ArrayRef<Expr *> VL); + + /// \brief Gets the list of references to private copies with initializers for + /// new private variables. + MutableArrayRef<Expr *> getPrivateCopies() { + return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + } + ArrayRef<const Expr *> getPrivateCopies() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + public: /// \brief Creates clause with a list of variables \a VL. /// @@ -808,10 +970,12 @@ public: /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. /// \param VL List of references to the variables. + /// \param PrivateVL List of references to private copies with initializers. /// static OMPPrivateClause *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL); + SourceLocation EndLoc, ArrayRef<Expr *> VL, + ArrayRef<Expr *> PrivateVL); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -819,6 +983,21 @@ public: /// static OMPPrivateClause *CreateEmpty(const ASTContext &C, unsigned N); + typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; + typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; + typedef llvm::iterator_range<private_copies_iterator> private_copies_range; + typedef llvm::iterator_range<private_copies_const_iterator> + private_copies_const_range; + + private_copies_range private_copies() { + return private_copies_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + private_copies_const_range private_copies() const { + return private_copies_const_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + StmtRange children() { return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); @@ -839,6 +1018,8 @@ public: /// with the variables 'a' and 'b'. /// class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> { + friend class OMPClauseReader; + /// \brief Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. @@ -859,6 +1040,33 @@ class OMPFirstprivateClause : public OMPVarListClause<OMPFirstprivateClause> { : OMPVarListClause<OMPFirstprivateClause>( OMPC_firstprivate, SourceLocation(), SourceLocation(), SourceLocation(), N) {} + /// \brief Sets the list of references to private copies with initializers for + /// new private variables. + /// \param VL List of references. + void setPrivateCopies(ArrayRef<Expr *> VL); + + /// \brief Gets the list of references to private copies with initializers for + /// new private variables. + MutableArrayRef<Expr *> getPrivateCopies() { + return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); + } + ArrayRef<const Expr *> getPrivateCopies() const { + return llvm::makeArrayRef(varlist_end(), varlist_size()); + } + + /// \brief Sets the list of references to initializer variables for new + /// private variables. + /// \param VL List of references. + void setInits(ArrayRef<Expr *> VL); + + /// \brief Gets the list of references to initializer variables for new + /// private variables. + MutableArrayRef<Expr *> getInits() { + return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); + } + ArrayRef<const Expr *> getInits() const { + return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); + } public: /// \brief Creates clause with a list of variables \a VL. @@ -867,11 +1075,16 @@ public: /// \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. + /// \param VL List of references to the original variables. + /// \param PrivateVL List of references to private copies with initializers. + /// \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. /// static OMPFirstprivateClause * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation LParenLoc, - SourceLocation EndLoc, ArrayRef<Expr *> VL); + SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, + ArrayRef<Expr *> InitVL); /// \brief Creates an empty clause with the place for \a N variables. /// /// \param C AST context. @@ -879,6 +1092,33 @@ public: /// static OMPFirstprivateClause *CreateEmpty(const ASTContext &C, unsigned N); + typedef MutableArrayRef<Expr *>::iterator private_copies_iterator; + typedef ArrayRef<const Expr *>::iterator private_copies_const_iterator; + typedef llvm::iterator_range<private_copies_iterator> private_copies_range; + typedef llvm::iterator_range<private_copies_const_iterator> + private_copies_const_range; + + private_copies_range private_copies() { + return private_copies_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + private_copies_const_range private_copies() const { + return private_copies_const_range(getPrivateCopies().begin(), + getPrivateCopies().end()); + } + + typedef MutableArrayRef<Expr *>::iterator inits_iterator; + typedef ArrayRef<const Expr *>::iterator inits_const_iterator; + typedef llvm::iterator_range<inits_iterator> inits_range; + typedef llvm::iterator_range<inits_const_iterator> inits_const_range; + + inits_range inits() { + return inits_range(getInits().begin(), getInits().end()); + } + inits_const_range inits() const { + return inits_const_range(getInits().begin(), getInits().end()); + } + StmtRange children() { return StmtRange(reinterpret_cast<Stmt **>(varlist_begin()), reinterpret_cast<Stmt **>(varlist_end())); @@ -1390,13 +1630,17 @@ public: } }; -/// \brief This represents pseudo clause 'flush' for the '#pragma omp flush' +/// \brief This represents implicit clause 'flush' for the '#pragma omp flush' /// directive. +/// This clause does not exist by itself, it can be only as a part of 'omp +/// flush' directive. This clause is introduced to keep the original structure +/// of \a OMPExecutableDirective class and its derivatives and to use the +/// existing infrastructure of clauses with the list of variables. /// /// \code /// #pragma omp flush(a,b) /// \endcode -/// In this example directive '#pragma omp flush' has pseudo clause 'flush' +/// In this example directive '#pragma omp flush' has implicit clause 'flush' /// with the variables 'a' and 'b'. /// class OMPFlushClause : public OMPVarListClause<OMPFlushClause> { @@ -1453,3 +1697,4 @@ public: } // end namespace clang #endif + diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index aba88d6c5419..e3f012667727 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_OPERATION_KINDS_H -#define LLVM_CLANG_AST_OPERATION_KINDS_H +#ifndef LLVM_CLANG_AST_OPERATIONKINDS_H +#define LLVM_CLANG_AST_OPERATIONKINDS_H namespace clang { diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index eece8510e9c4..8945c413d268 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARENTMAP_H -#define LLVM_CLANG_PARENTMAP_H +#ifndef LLVM_CLANG_AST_PARENTMAP_H +#define LLVM_CLANG_AST_PARENTMAP_H namespace clang { class Stmt; diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index 349f4c44a4e0..35ceabbd6b71 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_PRETTY_PRINTER_H -#define LLVM_CLANG_AST_PRETTY_PRINTER_H +#ifndef LLVM_CLANG_AST_PRETTYPRINTER_H +#define LLVM_CLANG_AST_PRETTYPRINTER_H #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 8ba85c43f657..2e005ddbd027 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_RAW_COMMENT_LIST_H -#define LLVM_CLANG_AST_RAW_COMMENT_LIST_H +#ifndef LLVM_CLANG_AST_RAWCOMMENTLIST_H +#define LLVM_CLANG_AST_RAWCOMMENTLIST_H #include "clang/Basic/CommentOptions.h" #include "clang/Basic/SourceManager.h" diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 4befb4506212..7b7799884a3d 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_LAYOUTINFO_H -#define LLVM_CLANG_AST_LAYOUTINFO_H +#ifndef LLVM_CLANG_AST_RECORDLAYOUT_H +#define LLVM_CLANG_AST_RECORDLAYOUT_H #include "clang/AST/CharUnits.h" #include "clang/AST/DeclCXX.h" diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index ff46ffb94e70..a1d36180d737 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -429,6 +429,7 @@ private: bool TraverseFunctionHelper(FunctionDecl *D); bool TraverseVarHelper(VarDecl *D); bool TraverseOMPExecutableDirective(OMPExecutableDirective *S); + bool TraverseOMPLoopDirective(OMPLoopDirective *S); bool TraverseOMPClause(OMPClause *C); #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" @@ -689,6 +690,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -713,6 +715,7 @@ bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc( case NestedNameSpecifier::Namespace: case NestedNameSpecifier::NamespaceAlias: case NestedNameSpecifier::Global: + case NestedNameSpecifier::Super: return true; case NestedNameSpecifier::TypeSpec: @@ -940,6 +943,9 @@ DEF_TRAVERSE_TYPE(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPE(UnresolvedUsingType, {}) @@ -1148,6 +1154,9 @@ DEF_TRAVERSE_TYPELOC(FunctionProtoType, { for (const auto &E : T->exceptions()) { TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); }) DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, {}) @@ -2144,21 +2153,29 @@ bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) { TRY_TO(TraverseLambdaCapture(S, C)); } - if (S->hasExplicitParameters() || S->hasExplicitResultType()) { - TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); - if (S->hasExplicitParameters() && S->hasExplicitResultType()) { - // Visit the whole type. - TRY_TO(TraverseTypeLoc(TL)); - } else if (FunctionProtoTypeLoc Proto = TL.getAs<FunctionProtoTypeLoc>()) { - if (S->hasExplicitParameters()) { - // Visit parameters. - for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { - TRY_TO(TraverseDecl(Proto.getParam(I))); - } - } else { - TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc(); + FunctionProtoTypeLoc Proto = TL.castAs<FunctionProtoTypeLoc>(); + + if (S->hasExplicitParameters() && S->hasExplicitResultType()) { + // Visit the whole type. + TRY_TO(TraverseTypeLoc(TL)); + } else { + if (S->hasExplicitParameters()) { + // Visit parameters. + for (unsigned I = 0, N = Proto.getNumParams(); I != N; ++I) { + TRY_TO(TraverseDecl(Proto.getParam(I))); } + } else if (S->hasExplicitResultType()) { + TRY_TO(TraverseTypeLoc(Proto.getReturnLoc())); + } + + auto *T = Proto.getTypePtr(); + for (const auto &E : T->exceptions()) { + TRY_TO(TraverseType(E)); } + + if (Expr *NE = T->getNoexceptExpr()) + TRY_TO(TraverseStmt(NE)); } TRY_TO(TraverseLambdaBody(S)); @@ -2259,6 +2276,7 @@ DEF_TRAVERSE_STMT(CapturedStmt, { TRY_TO(TraverseDecl(S->getCapturedDecl())); }) DEF_TRAVERSE_STMT(CXXOperatorCallExpr, {}) DEF_TRAVERSE_STMT(OpaqueValueExpr, {}) +DEF_TRAVERSE_STMT(TypoExpr, {}) DEF_TRAVERSE_STMT(CUDAKernelCallExpr, {}) // These operators (all of them) do not need any action except @@ -2275,6 +2293,7 @@ DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, {}) DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, {}) DEF_TRAVERSE_STMT(FunctionParmPackExpr, {}) DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, {}) +DEF_TRAVERSE_STMT(CXXFoldExpr, {}) DEF_TRAVERSE_STMT(AtomicExpr, {}) // These literals (all of them) do not need any action. @@ -2301,6 +2320,12 @@ bool RecursiveASTVisitor<Derived>::TraverseOMPExecutableDirective( return true; } +template <typename Derived> +bool +RecursiveASTVisitor<Derived>::TraverseOMPLoopDirective(OMPLoopDirective *S) { + return TraverseOMPExecutableDirective(S); +} + DEF_TRAVERSE_STMT(OMPParallelDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2310,6 +2335,9 @@ DEF_TRAVERSE_STMT(OMPSimdDirective, DEF_TRAVERSE_STMT(OMPForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2330,6 +2358,9 @@ DEF_TRAVERSE_STMT(OMPCriticalDirective, { DEF_TRAVERSE_STMT(OMPParallelForDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPParallelForSimdDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + DEF_TRAVERSE_STMT(OMPParallelSectionsDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) @@ -2348,6 +2379,18 @@ DEF_TRAVERSE_STMT(OMPTaskwaitDirective, DEF_TRAVERSE_STMT(OMPFlushDirective, { TRY_TO(TraverseOMPExecutableDirective(S)); }) +DEF_TRAVERSE_STMT(OMPOrderedDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPAtomicDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTargetDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + +DEF_TRAVERSE_STMT(OMPTeamsDirective, + { TRY_TO(TraverseOMPExecutableDirective(S)); }) + // OpenMP clauses. template <typename Derived> bool RecursiveASTVisitor<Derived>::TraverseOMPClause(OMPClause *C) { @@ -2437,6 +2480,31 @@ RecursiveASTVisitor<Derived>::VisitOMPMergeableClause(OMPMergeableClause *) { } template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPReadClause(OMPReadClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPWriteClause(OMPWriteClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPUpdateClause(OMPUpdateClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPCaptureClause(OMPCaptureClause *) { + return true; +} + +template <typename Derived> +bool RecursiveASTVisitor<Derived>::VisitOMPSeqCstClause(OMPSeqCstClause *) { + return true; +} + +template <typename Derived> template <typename T> bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { for (auto *E : Node->varlists()) { @@ -2448,6 +2516,9 @@ bool RecursiveASTVisitor<Derived>::VisitOMPClauseList(T *Node) { template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPPrivateClause(OMPPrivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } return true; } @@ -2455,6 +2526,12 @@ template <typename Derived> bool RecursiveASTVisitor<Derived>::VisitOMPFirstprivateClause( OMPFirstprivateClause *C) { TRY_TO(VisitOMPClauseList(C)); + for (auto *E : C->private_copies()) { + TRY_TO(TraverseStmt(E)); + } + for (auto *E : C->inits()) { + TRY_TO(TraverseStmt(E)); + } return true; } diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index fb94097cfac7..eb6836f88699 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -212,7 +212,7 @@ protected: unsigned HasTemplateKWAndArgsInfo : 1; unsigned HasFoundDecl : 1; unsigned HadMultipleCandidates : 1; - unsigned RefersToEnclosingLocal : 1; + unsigned RefersToEnclosingVariableOrCapture : 1; }; class CastExprBitfields { @@ -393,6 +393,10 @@ public: /// statement, such as ExprWithCleanups or ImplicitCastExpr nodes. Stmt *IgnoreImplicit(); + /// \brief Skip no-op (attributed, compound) container stmts and skip captured + /// stmt at the top, if \a IgnoreCaptured is true. + Stmt *IgnoreContainers(bool IgnoreCaptured = false); + const Stmt *stripLabelLikeStatements() const; Stmt *stripLabelLikeStatements() { return const_cast<Stmt*>( @@ -548,14 +552,17 @@ public: /// class CompoundStmt : public Stmt { Stmt** Body; - SourceLocation LBracLoc, RBracLoc; + SourceLocation LBraceLoc, RBraceLoc; + + friend class ASTStmtReader; + public: CompoundStmt(const ASTContext &C, ArrayRef<Stmt*> Stmts, SourceLocation LB, SourceLocation RB); // \brief Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) - : Stmt(CompoundStmtClass), Body(nullptr), LBracLoc(Loc), RBracLoc(Loc) { + : Stmt(CompoundStmtClass), Body(nullptr), LBraceLoc(Loc), RBraceLoc(Loc) { CompoundStmtBits.NumStmts = 0; } @@ -614,13 +621,11 @@ public: return const_reverse_body_iterator(body_begin()); } - SourceLocation getLocStart() const LLVM_READONLY { return LBracLoc; } - SourceLocation getLocEnd() const LLVM_READONLY { return RBracLoc; } + SourceLocation getLocStart() const LLVM_READONLY { return LBraceLoc; } + SourceLocation getLocEnd() const LLVM_READONLY { return RBraceLoc; } - SourceLocation getLBracLoc() const { return LBracLoc; } - void setLBracLoc(SourceLocation L) { LBracLoc = L; } - SourceLocation getRBracLoc() const { return RBracLoc; } - void setRBracLoc(SourceLocation L) { RBracLoc = L; } + SourceLocation getLBracLoc() const { return LBraceLoc; } + SourceLocation getRBracLoc() const { return RBraceLoc; } static bool classof(const Stmt *T) { return T->getStmtClass() == CompoundStmtClass; @@ -846,7 +851,7 @@ public: SourceLocation getAttrLoc() const { return AttrLoc; } ArrayRef<const Attr*> getAttrs() const { - return ArrayRef<const Attr*>(getAttrArrayPtr(), NumAttrs); + return llvm::makeArrayRef(getAttrArrayPtr(), NumAttrs); } Stmt *getSubStmt() { return SubStmt; } const Stmt *getSubStmt() const { return SubStmt; } @@ -1010,7 +1015,7 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return SwitchLoc; } SourceLocation getLocEnd() const LLVM_READONLY { - return SubExprs[BODY]->getLocEnd(); + return SubExprs[BODY] ? SubExprs[BODY]->getLocEnd() : SubExprs[COND]->getLocEnd(); } // Iterators @@ -1580,18 +1585,21 @@ public: Kind MyKind; std::string Str; unsigned OperandNo; + + // Source range for operand references. + CharSourceRange Range; public: AsmStringPiece(const std::string &S) : MyKind(String), Str(S) {} - AsmStringPiece(unsigned OpNo, char Modifier) - : MyKind(Operand), Str(), OperandNo(OpNo) { - Str += Modifier; + AsmStringPiece(unsigned OpNo, const std::string &S, SourceLocation Begin, + SourceLocation End) + : MyKind(Operand), Str(S), OperandNo(OpNo), + Range(CharSourceRange::getCharRange(Begin, End)) { } bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } const std::string &getString() const { - assert(isString()); return Str; } @@ -1600,12 +1608,14 @@ public: return OperandNo; } + CharSourceRange getRange() const { + assert(isOperand() && "Range is currently used only for Operands."); + return Range; + } + /// getModifier - Get the modifier for this operand, if present. This /// returns '\0' if there was no modifier. - char getModifier() const { - assert(isOperand()); - return Str[0]; - } + char getModifier() const; }; /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing @@ -1780,14 +1790,14 @@ public: //===--- Other ---===// ArrayRef<StringRef> getAllConstraints() const { - return ArrayRef<StringRef>(Constraints, NumInputs + NumOutputs); + return llvm::makeArrayRef(Constraints, NumInputs + NumOutputs); } ArrayRef<StringRef> getClobbers() const { - return ArrayRef<StringRef>(Clobbers, NumClobbers); + return llvm::makeArrayRef(Clobbers, NumClobbers); } ArrayRef<Expr*> getAllExprs() const { - return ArrayRef<Expr*>(reinterpret_cast<Expr**>(Exprs), - NumInputs + NumOutputs); + return llvm::makeArrayRef(reinterpret_cast<Expr**>(Exprs), + NumInputs + NumOutputs); } StringRef getClobber(unsigned i) const { return getClobbers()[i]; } @@ -1892,24 +1902,22 @@ class SEHTryStmt : public Stmt { bool IsCXXTry; SourceLocation TryLoc; Stmt *Children[2]; - int HandlerIndex; - int HandlerParentIndex; enum { TRY = 0, HANDLER = 1 }; SEHTryStmt(bool isCXXTry, // true if 'try' otherwise '__try' - SourceLocation TryLoc, Stmt *TryBlock, Stmt *Handler, - int HandlerIndex, int HandlerParentIndex); + SourceLocation TryLoc, + Stmt *TryBlock, + Stmt *Handler); friend class ASTReader; friend class ASTStmtReader; explicit SEHTryStmt(EmptyShell E) : Stmt(SEHTryStmtClass, E) { } public: - static SEHTryStmt *Create(const ASTContext &C, bool isCXXTry, + static SEHTryStmt* Create(const ASTContext &C, bool isCXXTry, SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler, int HandlerIndex, - int HandlerParentIndex); + Stmt *Handler); SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } @@ -1936,9 +1944,6 @@ public: static bool classof(const Stmt *T) { return T->getStmtClass() == SEHTryStmtClass; } - - int getHandlerIndex() const { return HandlerIndex; } - int getHandlerParentIndex() const { return HandlerParentIndex; } }; /// Represents a __leave statement. @@ -1977,15 +1982,18 @@ public: /// @endcode class CapturedStmt : public Stmt { public: - /// \brief The different capture forms: by 'this' or by reference, etc. + /// \brief The different capture forms: by 'this', by reference, capture for + /// variable-length array type etc. enum VariableCaptureKind { VCK_This, - VCK_ByRef + VCK_ByRef, + VCK_VLAType, }; - /// \brief Describes the capture of either a variable or 'this'. + /// \brief Describes the capture of either a variable, or 'this', or + /// variable-length array type. class Capture { - llvm::PointerIntPair<VarDecl *, 1, VariableCaptureKind> VarAndKind; + llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind; SourceLocation Loc; public: @@ -2007,6 +2015,10 @@ public: case VCK_ByRef: assert(Var && "capturing by reference must have a variable!"); break; + case VCK_VLAType: + assert(!Var && + "Variable-length array type capture cannot have a variable!"); + break; } } @@ -2021,13 +2033,20 @@ public: bool capturesThis() const { return getCaptureKind() == VCK_This; } /// \brief Determine whether this capture handles a variable. - bool capturesVariable() const { return getCaptureKind() != VCK_This; } + bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; } + + /// \brief Determine whether this capture handles a variable-length array + /// type. + bool capturesVariableArrayType() const { + return getCaptureKind() == VCK_VLAType; + } /// \brief Retrieve the declaration of the variable being captured. /// - /// This operation is only valid if this capture does not capture 'this'. + /// This operation is only valid if this capture captures a variable. VarDecl *getCapturedVar() const { - assert(!capturesThis() && "No variable available for 'this' capture"); + assert(capturesVariable() && + "No variable available for 'this' or VAT capture"); return VarAndKind.getPointer(); } friend class ASTStmtReader; diff --git a/include/clang/AST/StmtGraphTraits.h b/include/clang/AST/StmtGraphTraits.h index a3e9e1e093f6..ab636a5ddc48 100644 --- a/include/clang/AST/StmtGraphTraits.h +++ b/include/clang/AST/StmtGraphTraits.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_STMT_GRAPHTRAITS_H -#define LLVM_CLANG_AST_STMT_GRAPHTRAITS_H +#ifndef LLVM_CLANG_AST_STMTGRAPHTRAITS_H +#define LLVM_CLANG_AST_STMTGRAPHTRAITS_H #include "clang/AST/Stmt.h" #include "llvm/ADT/DepthFirstIterator.h" diff --git a/include/clang/AST/StmtIterator.h b/include/clang/AST/StmtIterator.h index 18c55166beba..6ffe74f2d7fb 100644 --- a/include/clang/AST/StmtIterator.h +++ b/include/clang/AST/StmtIterator.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_STMT_ITR_H -#define LLVM_CLANG_AST_STMT_ITR_H +#ifndef LLVM_CLANG_AST_STMTITERATOR_H +#define LLVM_CLANG_AST_STMTITERATOR_H #include "llvm/Support/Compiler.h" #include "llvm/Support/DataTypes.h" diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index db02afe0568b..aed7691cf73a 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -128,6 +128,13 @@ public: operator bool() { return Current != End; } }; + /// \brief Gets a single clause of the specified kind \a K associated with the + /// current directive iff there is only one clause of this kind (and assertion + /// is fired if there is more than one clause is associated with the + /// directive). Returns nullptr if no clause of kind \a K is associated with + /// the directive. + const OMPClause *getSingleClause(OpenMPClauseKind K) const; + /// \brief Returns starting location of directive kind. SourceLocation getLocStart() const { return StartLoc; } /// \brief Returns ending location of directive. @@ -238,6 +245,353 @@ public: } }; +/// \brief This is a common base class for loop directives ('omp simd', 'omp +/// for', 'omp for simd' etc.). It is responsible for the loop code generation. +/// +class OMPLoopDirective : public OMPExecutableDirective { + friend class ASTStmtReader; + /// \brief Number of collapsed loops as specified by 'collapse' clause. + unsigned CollapsedNum; + + /// \brief Offsets to the stored exprs. + /// 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. + /// After the fixed children, three arrays of length CollapsedNum are + /// allocated: loop counters, their updates and final values. + /// + enum { + AssociatedStmtOffset = 0, + IterationVariableOffset = 1, + LastIterationOffset = 2, + CalcLastIterationOffset = 3, + PreConditionOffset = 4, + CondOffset = 5, + SeparatedCondOffset = 6, + InitOffset = 7, + IncOffset = 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 = 9, + // The following 7 exprs are used by worksharing loops only. + IsLastIterVariableOffset = 9, + LowerBoundVariableOffset = 10, + UpperBoundVariableOffset = 11, + StrideVariableOffset = 12, + EnsureUpperBoundOffset = 13, + NextLowerBoundOffset = 14, + NextUpperBoundOffset = 15, + // Offset to the end (and start of the following counters/updates/finals + // arrays) for worksharing loop directives. + WorksharingEnd = 16, + }; + + /// \brief Get the counters storage. + MutableArrayRef<Expr *> getCounters() { + Expr **Storage = reinterpret_cast<Expr **>( + &(*(std::next(child_begin(), getArraysOffset(getDirectiveKind()))))); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the updates storage. + MutableArrayRef<Expr *> getUpdates() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + + /// \brief Get the final counter updates storage. + MutableArrayRef<Expr *> getFinals() { + Expr **Storage = reinterpret_cast<Expr **>( + &*std::next(child_begin(), + getArraysOffset(getDirectiveKind()) + 2 * CollapsedNum)); + return MutableArrayRef<Expr *>(Storage, CollapsedNum); + } + +protected: + /// \brief Build instance of loop directive of class \a Kind. + /// + /// \param SC Statement class. + /// \param Kind Kind of OpenMP directive. + /// \param StartLoc Starting location of the directive (directive keyword). + /// \param EndLoc Ending location of the directive. + /// \param CollapsedNum Number of collapsed loops from 'collapse' clause. + /// \param NumClauses Number of clauses. + /// \param NumSpecialChildren Number of additional directive-specific stmts. + /// + template <typename T> + OMPLoopDirective(const T *That, StmtClass SC, OpenMPDirectiveKind Kind, + SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses, + unsigned NumSpecialChildren = 0) + : OMPExecutableDirective(That, SC, Kind, StartLoc, EndLoc, NumClauses, + numLoopChildren(CollapsedNum, Kind) + + NumSpecialChildren), + CollapsedNum(CollapsedNum) {} + + /// \brief Offset to the start of children expression arrays. + static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { + return isOpenMPWorksharingDirective(Kind) ? WorksharingEnd + : DefaultEnd; + } + + /// \brief Children number. + static unsigned numLoopChildren(unsigned CollapsedNum, + OpenMPDirectiveKind Kind) { + return getArraysOffset(Kind) + + 3 * CollapsedNum; // Counters, Updates and Finals + } + + void setIterationVariable(Expr *IV) { + *std::next(child_begin(), IterationVariableOffset) = IV; + } + void setLastIteration(Expr *LI) { + *std::next(child_begin(), LastIterationOffset) = LI; + } + void setCalcLastIteration(Expr *CLI) { + *std::next(child_begin(), CalcLastIterationOffset) = CLI; + } + void setPreCond(Expr *PC) { + *std::next(child_begin(), PreConditionOffset) = PC; + } + void setCond(Expr *Cond, Expr *SeparatedCond) { + *std::next(child_begin(), CondOffset) = Cond; + *std::next(child_begin(), SeparatedCondOffset) = SeparatedCond; + } + void setInit(Expr *Init) { *std::next(child_begin(), InitOffset) = Init; } + void setInc(Expr *Inc) { *std::next(child_begin(), IncOffset) = Inc; } + void setIsLastIterVariable(Expr *IL) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), IsLastIterVariableOffset) = IL; + } + void setLowerBoundVariable(Expr *LB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), LowerBoundVariableOffset) = LB; + } + void setUpperBoundVariable(Expr *UB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), UpperBoundVariableOffset) = UB; + } + void setStrideVariable(Expr *ST) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), StrideVariableOffset) = ST; + } + void setEnsureUpperBound(Expr *EUB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), EnsureUpperBoundOffset) = EUB; + } + void setNextLowerBound(Expr *NLB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), NextLowerBoundOffset) = NLB; + } + void setNextUpperBound(Expr *NUB) { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + *std::next(child_begin(), NextUpperBoundOffset) = NUB; + } + void setCounters(ArrayRef<Expr *> A); + void setUpdates(ArrayRef<Expr *> A); + void setFinals(ArrayRef<Expr *> A); + +public: + /// \brief The expressions built for the OpenMP loop CodeGen for the + /// whole collapsed loop nest. + struct HelperExprs { + /// \brief Loop iteration variable. + Expr *IterationVarRef; + /// \brief Loop last iteration number. + Expr *LastIteration; + /// \brief Calculation of last iteration. + Expr *CalcLastIteration; + /// \brief Loop pre-condition. + Expr *PreCond; + /// \brief Loop condition. + Expr *Cond; + /// \brief A condition with 1 iteration separated. + Expr *SeparatedCond; + /// \brief Loop iteration variable init. + Expr *Init; + /// \brief Loop increment. + Expr *Inc; + /// \brief IsLastIteration - local flag variable passed to runtime. + Expr *IL; + /// \brief LowerBound - local variable passed to runtime. + Expr *LB; + /// \brief UpperBound - local variable passed to runtime. + Expr *UB; + /// \brief Stride - local variable passed to runtime. + Expr *ST; + /// \brief EnsureUpperBound -- expression LB = min(LB, NumIterations). + Expr *EUB; + /// \brief Update of LowerBound for statically sheduled 'omp for' loops. + Expr *NLB; + /// \brief Update of UpperBound for statically sheduled 'omp for' loops. + Expr *NUB; + /// \brief Counters Loop counters. + SmallVector<Expr *, 4> Counters; + /// \brief Expressions for loop counters update for CodeGen. + SmallVector<Expr *, 4> Updates; + /// \brief Final loop counter values for GodeGen. + SmallVector<Expr *, 4> Finals; + + /// \brief Check if all the expressions are built (does not check the + /// worksharing ones). + bool builtAll() { + return IterationVarRef != nullptr && LastIteration != nullptr && + PreCond != nullptr && Cond != nullptr && + SeparatedCond != nullptr && Init != nullptr && Inc != nullptr; + } + + /// \brief Initialize all the fields to null. + /// \param Size Number of elements in the counters/finals/updates arrays. + void clear(unsigned Size) { + IterationVarRef = nullptr; + LastIteration = nullptr; + CalcLastIteration = nullptr; + PreCond = nullptr; + Cond = nullptr; + SeparatedCond = nullptr; + Init = nullptr; + Inc = nullptr; + IL = nullptr; + LB = nullptr; + UB = nullptr; + ST = nullptr; + EUB = nullptr; + NLB = nullptr; + NUB = nullptr; + Counters.resize(Size); + Updates.resize(Size); + Finals.resize(Size); + for (unsigned i = 0; i < Size; ++i) { + Counters[i] = nullptr; + Updates[i] = nullptr; + Finals[i] = nullptr; + } + } + }; + + /// \brief Get number of collapsed loops. + unsigned getCollapsedNumber() const { return CollapsedNum; } + + Expr *getIterationVariable() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), IterationVariableOffset))); + } + Expr *getLastIteration() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), LastIterationOffset))); + } + Expr *getCalcLastIteration() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), CalcLastIterationOffset))); + } + Expr *getPreCond() const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), PreConditionOffset))); + } + Expr *getCond(bool SeparateIter) const { + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), + (SeparateIter ? SeparatedCondOffset : CondOffset)))); + } + Expr *getInit() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), InitOffset))); + } + Expr *getInc() const { + return const_cast<Expr *>( + reinterpret_cast<const Expr *>(*std::next(child_begin(), IncOffset))); + } + Expr *getIsLastIterVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), IsLastIterVariableOffset))); + } + Expr *getLowerBoundVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), LowerBoundVariableOffset))); + } + Expr *getUpperBoundVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), UpperBoundVariableOffset))); + } + Expr *getStrideVariable() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), StrideVariableOffset))); + } + Expr *getEnsureUpperBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), EnsureUpperBoundOffset))); + } + Expr *getNextLowerBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), NextLowerBoundOffset))); + } + Expr *getNextUpperBound() const { + assert(isOpenMPWorksharingDirective(getDirectiveKind()) && + "expected worksharing loop directive"); + return const_cast<Expr *>(reinterpret_cast<const Expr *>( + *std::next(child_begin(), NextUpperBoundOffset))); + } + const Stmt *getBody() const { + // This relies on the loop form is already checked by Sema. + Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); + Body = cast<ForStmt>(Body)->getBody(); + for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { + Body = Body->IgnoreContainers(); + Body = cast<ForStmt>(Body)->getBody(); + } + return Body; + } + + ArrayRef<Expr *> counters() { return getCounters(); } + + ArrayRef<Expr *> counters() const { + return const_cast<OMPLoopDirective *>(this)->getCounters(); + } + + ArrayRef<Expr *> updates() { return getUpdates(); } + + ArrayRef<Expr *> updates() const { + return const_cast<OMPLoopDirective *>(this)->getUpdates(); + } + + ArrayRef<Expr *> finals() { return getFinals(); } + + ArrayRef<Expr *> finals() const { + return const_cast<OMPLoopDirective *>(this)->getFinals(); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPSimdDirectiveClass || + T->getStmtClass() == OMPForDirectiveClass || + T->getStmtClass() == OMPForSimdDirectiveClass || + T->getStmtClass() == OMPParallelForDirectiveClass || + T->getStmtClass() == OMPParallelForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp simd' directive. /// /// \code @@ -247,10 +601,8 @@ public: /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. /// -class OMPSimdDirective : public OMPExecutableDirective { +class OMPSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -260,9 +612,8 @@ class OMPSimdDirective : public OMPExecutableDirective { /// OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, - EndLoc, NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, + EndLoc, CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -270,10 +621,9 @@ class OMPSimdDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPSimdDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPSimdDirectiveClass, OMPD_simd, - SourceLocation(), SourceLocation(), NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -284,11 +634,13 @@ public: /// \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 OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, + const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -300,8 +652,6 @@ public: static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPSimdDirectiveClass; } @@ -316,10 +666,8 @@ public: /// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c' /// and 'd'. /// -class OMPForDirective : public OMPExecutableDirective { +class OMPForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -329,9 +677,8 @@ class OMPForDirective : public OMPExecutableDirective { /// OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, - EndLoc, NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, StartLoc, EndLoc, + CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -339,10 +686,8 @@ class OMPForDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPForDirectiveClass, OMPD_for, - SourceLocation(), SourceLocation(), NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPForDirectiveClass, OMPD_for, SourceLocation(), + SourceLocation(), CollapsedNum, NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -353,11 +698,13 @@ public: /// \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 OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, + const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -369,13 +716,76 @@ public: static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPForDirectiveClass; } }; +/// \brief This represents '#pragma omp for simd' directive. +/// +/// \code +/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp for simd' has clauses 'private' +/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and +/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'. +/// +class OMPForSimdDirective : 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. + /// + OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPForSimdDirective(unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, + 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 OMPForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> 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 OMPForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp sections' directive. /// /// \code @@ -657,10 +1067,8 @@ public: /// with the variables 'a' and 'b' and 'reduction' with operator '+' and /// variables 'c' and 'd'. /// -class OMPParallelForDirective : public OMPExecutableDirective { +class OMPParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Number of collapsed loops as specified by 'collapse' clause. - unsigned CollapsedNum; /// \brief Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. @@ -670,10 +1078,8 @@ class OMPParallelForDirective : public OMPExecutableDirective { /// OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelForDirectiveClass, - OMPD_parallel_for, StartLoc, EndLoc, NumClauses, - 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, + StartLoc, EndLoc, CollapsedNum, NumClauses) {} /// \brief Build an empty directive. /// @@ -681,10 +1087,9 @@ class OMPParallelForDirective : public OMPExecutableDirective { /// \param NumClauses Number of clauses. /// explicit OMPParallelForDirective(unsigned CollapsedNum, unsigned NumClauses) - : OMPExecutableDirective(this, OMPParallelForDirectiveClass, - OMPD_parallel_for, SourceLocation(), - SourceLocation(), NumClauses, 1), - CollapsedNum(CollapsedNum) {} + : OMPLoopDirective(this, OMPParallelForDirectiveClass, OMPD_parallel_for, + SourceLocation(), SourceLocation(), CollapsedNum, + NumClauses) {} public: /// \brief Creates directive with a list of \a Clauses. @@ -695,11 +1100,12 @@ public: /// \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 OMPParallelForDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, - Stmt *AssociatedStmt); + Stmt *AssociatedStmt, const HelperExprs &Exprs); /// \brief Creates an empty directive with the place /// for \a NumClauses clauses. @@ -713,13 +1119,80 @@ public: unsigned CollapsedNum, EmptyShell); - unsigned getCollapsedNumber() const { return CollapsedNum; } - static bool classof(const Stmt *T) { return T->getStmtClass() == OMPParallelForDirectiveClass; } }; +/// \brief This represents '#pragma omp parallel for simd' directive. +/// +/// \code +/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d) +/// \endcode +/// In this example directive '#pragma omp parallel for simd' has clauses +/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j' +/// and linear step 's', 'reduction' with operator '+' and variables 'c' and +/// 'd'. +/// +class OMPParallelForSimdDirective : 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. + /// + OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, + OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum, + NumClauses) {} + + /// \brief Build an empty directive. + /// + /// \param CollapsedNum Number of collapsed nested loops. + /// \param NumClauses Number of clauses. + /// + explicit OMPParallelForSimdDirective(unsigned CollapsedNum, + unsigned NumClauses) + : OMPLoopDirective(this, OMPParallelForSimdDirectiveClass, + OMPD_parallel_for_simd, 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 OMPParallelForSimdDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + unsigned CollapsedNum, ArrayRef<OMPClause *> 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 OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, + unsigned CollapsedNum, + EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPParallelForSimdDirectiveClass; + } +}; + /// \brief This represents '#pragma omp parallel sections' directive. /// /// \code @@ -1028,6 +1501,253 @@ public: } }; +/// \brief This represents '#pragma omp ordered' directive. +/// +/// \code +/// #pragma omp ordered +/// \endcode +/// +class OMPOrderedDirective : 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. + /// + OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc) + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + StartLoc, EndLoc, 0, 1) {} + + /// \brief Build an empty directive. + /// + explicit OMPOrderedDirective() + : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, + SourceLocation(), SourceLocation(), 0, 1) {} + +public: + /// \brief Creates directive. + /// + /// \param C AST context. + /// \param StartLoc Starting location of the directive kind. + /// \param EndLoc Ending Location of the directive. + /// \param AssociatedStmt Statement, associated with the directive. + /// + static OMPOrderedDirective *Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + Stmt *AssociatedStmt); + + /// \brief Creates an empty directive. + /// + /// \param C AST context. + /// + static OMPOrderedDirective *CreateEmpty(const ASTContext &C, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPOrderedDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp atomic' directive. +/// +/// \code +/// #pragma omp atomic capture +/// \endcode +/// In this example directive '#pragma omp atomic' has clause 'capture'. +/// +class OMPAtomicDirective : 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. + /// + OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, + StartLoc, EndLoc, NumClauses, 4) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPAtomicDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPAtomicDirectiveClass, OMPD_atomic, + SourceLocation(), SourceLocation(), NumClauses, + 4) {} + + /// \brief Set 'x' part of the associated expression/statement. + void setX(Expr *X) { *std::next(child_begin()) = X; } + /// \brief Set 'v' part of the associated expression/statement. + void setV(Expr *V) { *std::next(child_begin(), 2) = V; } + /// \brief Set 'expr' part of the associated expression/statement. + void setExpr(Expr *E) { *std::next(child_begin(), 3) = E; } + +public: + /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' + /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for + /// detailed description of 'x', 'v' and 'expr'). + /// + /// \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. + /// \param X 'x' part of the associated expression/statement. + /// \param V 'v' part of the associated expression/statement. + /// \param E 'expr' part of the associated expression/statement. + /// + static OMPAtomicDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, + Expr *E); + + /// \brief Creates an empty directive with the place for \a NumClauses + /// clauses. + /// + /// \param C AST context. + /// \param NumClauses Number of clauses. + /// + static OMPAtomicDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + /// \brief Get 'x' part of the associated expression/statement. + Expr *getX() { return cast_or_null<Expr>(*std::next(child_begin())); } + const Expr *getX() const { + return cast_or_null<Expr>(*std::next(child_begin())); + } + /// \brief Get 'v' part of the associated expression/statement. + Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 2)); } + const Expr *getV() const { + return cast_or_null<Expr>(*std::next(child_begin(), 2)); + } + /// \brief Get 'expr' part of the associated expression/statement. + Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } + const Expr *getExpr() const { + return cast_or_null<Expr>(*std::next(child_begin(), 3)); + } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPAtomicDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp target' directive. +/// +/// \code +/// #pragma omp target if(a) +/// \endcode +/// In this example directive '#pragma omp target' has clause 'if' with +/// condition 'a'. +/// +class OMPTargetDirective : 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. + /// + OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTargetDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, + SourceLocation(), SourceLocation(), NumClauses, + 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 OMPTargetDirective * + Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, + ArrayRef<OMPClause *> 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 OMPTargetDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTargetDirectiveClass; + } +}; + +/// \brief This represents '#pragma omp teams' directive. +/// +/// \code +/// #pragma omp teams if(a) +/// \endcode +/// In this example directive '#pragma omp teams' has clause 'if' with +/// condition 'a'. +/// +class OMPTeamsDirective : 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. + /// + OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc, + unsigned NumClauses) + : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, + StartLoc, EndLoc, NumClauses, 1) {} + + /// \brief Build an empty directive. + /// + /// \param NumClauses Number of clauses. + /// + explicit OMPTeamsDirective(unsigned NumClauses) + : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, + SourceLocation(), SourceLocation(), NumClauses, + 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 OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> 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 OMPTeamsDirective *CreateEmpty(const ASTContext &C, + unsigned NumClauses, EmptyShell); + + static bool classof(const Stmt *T) { + return T->getStmtClass() == OMPTeamsDirectiveClass; + } +}; + } // end namespace clang #endif diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 1026a7807a60..80b68bc0569b 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -18,8 +18,8 @@ #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "llvm/ADT/APSInt.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -76,7 +76,7 @@ private: struct DA { unsigned Kind; - bool ForRefParam; + void *QT; ValueDecl *D; }; struct I { @@ -132,11 +132,11 @@ public: /// \brief Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. - TemplateArgument(ValueDecl *D, bool ForRefParam) { + TemplateArgument(ValueDecl *D, QualType QT) { assert(D && "Expected decl"); DeclArg.Kind = Declaration; + DeclArg.QT = QT.getAsOpaquePtr(); DeclArg.D = D; - DeclArg.ForRefParam = ForRefParam; } /// \brief Construct an integral constant template argument. The memory to @@ -249,11 +249,9 @@ public: return DeclArg.D; } - /// \brief Retrieve whether a declaration is binding to a - /// reference parameter in a declaration non-type template argument. - bool isDeclForReferenceParam() const { + QualType getParamTypeForDecl() const { assert(getKind() == Declaration && "Unexpected kind"); - return DeclArg.ForRefParam; + return QualType::getFromOpaquePtr(DeclArg.QT); } /// \brief Retrieve the type for null non-type template argument. @@ -344,7 +342,7 @@ public: /// \brief Return the array of arguments in this template argument pack. ArrayRef<TemplateArgument> getPackAsArray() const { assert(getKind() == Pack); - return ArrayRef<TemplateArgument>(Args.Args, Args.NumArgs); + return llvm::makeArrayRef(Args.Args, Args.NumArgs); } /// \brief Determines whether two template arguments are superficially the diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 09862e4fb7f7..1bda01fee8ad 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -16,6 +16,7 @@ #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateName.h" +#include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/LLVM.h" @@ -25,11 +26,11 @@ #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/Twine.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" namespace clang { @@ -400,21 +401,36 @@ public: Mask |= qs.Mask; } + /// \brief Returns true if this address space is a superset of the other one. + /// OpenCL v2.0 defines conversion rules (OpenCLC v2.0 s6.5.5) and notion of + /// overlapping address spaces. + /// CL1.1 or CL1.2: + /// every address space is a superset of itself. + /// CL2.0 adds: + /// __generic is a superset of any address space except for __constant. + bool isAddressSpaceSupersetOf(Qualifiers other) const { + return + // Address spaces must match exactly. + getAddressSpace() == other.getAddressSpace() || + // Otherwise in OpenCLC v2.0 s6.5.5: every address space except + // for __constant can be used as __generic. + (getAddressSpace() == LangAS::opencl_generic && + other.getAddressSpace() != LangAS::opencl_constant); + } + /// \brief Determines if these qualifiers compatibly include another set. /// Generally this answers the question of whether an object with the other /// qualifiers can be safely used as an object with these qualifiers. bool compatiblyIncludes(Qualifiers other) const { - return - // Address spaces must match exactly. - getAddressSpace() == other.getAddressSpace() && - // ObjC GC qualifiers can match, be added, or be removed, but can't be - // changed. - (getObjCGCAttr() == other.getObjCGCAttr() || - !hasObjCGCAttr() || !other.hasObjCGCAttr()) && - // ObjC lifetime qualifiers must match exactly. - getObjCLifetime() == other.getObjCLifetime() && - // CVR qualifiers may subset. - (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); + return isAddressSpaceSupersetOf(other) && + // ObjC GC qualifiers can match, be added, or be removed, but can't + // be changed. + (getObjCGCAttr() == other.getObjCGCAttr() || !hasObjCGCAttr() || + !other.hasObjCGCAttr()) && + // ObjC lifetime qualifiers must match exactly. + getObjCLifetime() == other.getObjCLifetime() && + // CVR qualifiers may subset. + (((Mask & CVRMask) | (other.Mask & CVRMask)) == (Mask & CVRMask)); } /// \brief Determines if these qualifiers compatibly include another set of @@ -1245,6 +1261,7 @@ protected: class FunctionTypeBitfields { friend class FunctionType; + friend class FunctionProtoType; unsigned : NumTypeBits; @@ -1259,6 +1276,11 @@ 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; + + /// \brief The ref-qualifier associated with a \c FunctionProtoType. + /// + /// This is a value of type \c RefQualifierKind. + unsigned RefQualifier : 2; }; class ObjCObjectTypeBitfields { @@ -1685,6 +1707,11 @@ public: /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; + /// \brief Retrieves the TagDecl that this type refers to, either + /// because the type is a TagType or because it is the injected-class-name + /// type of a class template or class template partial specialization. + TagDecl *getAsTagDecl() const; + /// If this is a pointer or reference to a RecordType, return the /// CXXRecordDecl that that type refers to. /// @@ -1982,6 +2009,22 @@ public: QualType getPointeeType() const { return PointeeType; } + /// \brief Returns true if address spaces of pointers overlap. + /// OpenCL v2.0 defines conversion rules for pointers to different + /// address spaces (OpenCLC v2.0 s6.5.5) and notion of overlapping + /// address spaces. + /// CL1.1 or CL1.2: + /// address spaces overlap iff they are they same. + /// CL2.0 adds: + /// __generic overlaps with any address space except for __constant. + bool isAddressSpaceOverlapping(const PointerType &other) const { + Qualifiers thisQuals = PointeeType.getQualifiers(); + Qualifiers otherQuals = other.getPointeeType().getQualifiers(); + // Address spaces overlap if at least one of them is a superset of another + return thisQuals.isAddressSpaceSupersetOf(otherQuals) || + otherQuals.isAddressSpaceSupersetOf(thisQuals); + } + bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } @@ -2765,7 +2808,7 @@ class FunctionType : public Type { protected: FunctionType(TypeClass tc, QualType res, - unsigned typeQuals, QualType Canonical, bool Dependent, + QualType Canonical, bool Dependent, bool InstantiationDependent, bool VariablyModified, bool ContainsUnexpandedParameterPack, ExtInfo Info) @@ -2773,7 +2816,6 @@ protected: ContainsUnexpandedParameterPack), ResultType(res) { FunctionTypeBits.ExtInfo = Info.Bits; - FunctionTypeBits.TypeQuals = typeQuals; } unsigned getTypeQuals() const { return FunctionTypeBits.TypeQuals; } @@ -2810,7 +2852,7 @@ public: /// no information available about its arguments. class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode { FunctionNoProtoType(QualType Result, QualType Canonical, ExtInfo Info) - : FunctionType(FunctionNoProto, Result, 0, Canonical, + : FunctionType(FunctionNoProto, Result, Canonical, /*Dependent=*/false, /*InstantiationDependent=*/false, Result->isVariablyModifiedType(), /*ContainsUnexpandedParameterPack=*/false, Info) {} @@ -2844,33 +2886,51 @@ public: /// type. class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode { public: + struct ExceptionSpecInfo { + ExceptionSpecInfo() + : Type(EST_None), NoexceptExpr(nullptr), + SourceDecl(nullptr), SourceTemplate(nullptr) {} + + ExceptionSpecInfo(ExceptionSpecificationType EST) + : Type(EST), NoexceptExpr(nullptr), SourceDecl(nullptr), + SourceTemplate(nullptr) {} + + /// The kind of exception specification this is. + ExceptionSpecificationType Type; + /// Explicitly-specified list of exception types. + ArrayRef<QualType> Exceptions; + /// Noexcept expression, if this is EST_ComputedNoexcept. + Expr *NoexceptExpr; + /// The function whose exception specification this is, for + /// EST_Unevaluated and EST_Uninstantiated. + FunctionDecl *SourceDecl; + /// The function template whose exception specification this is instantiated + /// from, for EST_Uninstantiated. + FunctionDecl *SourceTemplate; + }; + /// ExtProtoInfo - Extra information about a function prototype. struct ExtProtoInfo { ExtProtoInfo() : Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(nullptr), NoexceptExpr(nullptr), - ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), - ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ConsumedParameters(nullptr) {} ExtProtoInfo(CallingConv CC) : ExtInfo(CC), Variadic(false), HasTrailingReturn(false), TypeQuals(0), - ExceptionSpecType(EST_None), RefQualifier(RQ_None), NumExceptions(0), - Exceptions(nullptr), NoexceptExpr(nullptr), - ExceptionSpecDecl(nullptr), ExceptionSpecTemplate(nullptr), - ConsumedParameters(nullptr) {} + RefQualifier(RQ_None), ConsumedParameters(nullptr) {} + + ExtProtoInfo withExceptionSpec(const ExceptionSpecInfo &O) { + ExtProtoInfo Result(*this); + Result.ExceptionSpec = O; + return Result; + } FunctionType::ExtInfo ExtInfo; bool Variadic : 1; bool HasTrailingReturn : 1; unsigned char TypeQuals; - ExceptionSpecificationType ExceptionSpecType; RefQualifierKind RefQualifier; - unsigned NumExceptions; - const QualType *Exceptions; - Expr *NoexceptExpr; - FunctionDecl *ExceptionSpecDecl; - FunctionDecl *ExceptionSpecTemplate; + ExceptionSpecInfo ExceptionSpec; const bool *ConsumedParameters; }; @@ -2896,7 +2956,7 @@ private: unsigned NumExceptions : 9; /// ExceptionSpecType - The type of exception specification this function has. - unsigned ExceptionSpecType : 3; + unsigned ExceptionSpecType : 4; /// HasAnyConsumedParams - Whether this function has any consumed parameters. unsigned HasAnyConsumedParams : 1; @@ -2907,11 +2967,6 @@ private: /// HasTrailingReturn - Whether this function has a trailing return type. unsigned HasTrailingReturn : 1; - /// \brief The ref-qualifier associated with a \c FunctionProtoType. - /// - /// This is a value of type \c RefQualifierKind. - unsigned RefQualifier : 2; - // ParamInfo - There is an variable size array after the class in memory that // holds the parameter types. @@ -2952,7 +3007,7 @@ public: return param_type_begin()[i]; } ArrayRef<QualType> getParamTypes() const { - return ArrayRef<QualType>(param_type_begin(), param_type_end()); + return llvm::makeArrayRef(param_type_begin(), param_type_end()); } ExtProtoInfo getExtProtoInfo() const { @@ -2960,19 +3015,18 @@ public: EPI.ExtInfo = getExtInfo(); EPI.Variadic = isVariadic(); EPI.HasTrailingReturn = hasTrailingReturn(); - EPI.ExceptionSpecType = getExceptionSpecType(); + EPI.ExceptionSpec.Type = getExceptionSpecType(); EPI.TypeQuals = static_cast<unsigned char>(getTypeQuals()); EPI.RefQualifier = getRefQualifier(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = NumExceptions; - EPI.Exceptions = exception_begin(); - } else if (EPI.ExceptionSpecType == EST_ComputedNoexcept) { - EPI.NoexceptExpr = getNoexceptExpr(); - } else if (EPI.ExceptionSpecType == EST_Uninstantiated) { - EPI.ExceptionSpecDecl = getExceptionSpecDecl(); - EPI.ExceptionSpecTemplate = getExceptionSpecTemplate(); - } else if (EPI.ExceptionSpecType == EST_Unevaluated) { - EPI.ExceptionSpecDecl = getExceptionSpecDecl(); + if (EPI.ExceptionSpec.Type == EST_Dynamic) { + EPI.ExceptionSpec.Exceptions = exceptions(); + } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { + EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr(); + } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { + EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); + EPI.ExceptionSpec.SourceTemplate = getExceptionSpecTemplate(); + } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { + EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); } if (hasAnyConsumedParams()) EPI.ConsumedParameters = getConsumedParamsBuffer(); @@ -2995,6 +3049,8 @@ public: bool hasNoexceptExceptionSpec() const { return isNoexceptExceptionSpec(getExceptionSpecType()); } + /// \brief Return whether this function has a dependent exception spec. + bool hasDependentExceptionSpec() const; /// \brief Result type of getNoexceptSpec(). enum NoexceptResult { NR_NoNoexcept, ///< There is no noexcept specifier. @@ -3057,7 +3113,7 @@ public: /// \brief Retrieve the ref-qualifier associated with this function type. RefQualifierKind getRefQualifier() const { - return static_cast<RefQualifierKind>(RefQualifier); + return static_cast<RefQualifierKind>(FunctionTypeBits.RefQualifier); } typedef const QualType *param_type_iterator; @@ -3074,10 +3130,9 @@ public: } typedef const QualType *exception_iterator; - typedef llvm::iterator_range<exception_iterator> exception_range; - exception_range exceptions() const { - return exception_range(exception_begin(), exception_end()); + ArrayRef<QualType> exceptions() const { + return llvm::makeArrayRef(exception_begin(), exception_end()); } exception_iterator exception_begin() const { // exceptions begin where arguments end @@ -3416,6 +3471,7 @@ public: attr_stdcall, attr_thiscall, attr_pascal, + attr_vectorcall, attr_pnaclcall, attr_inteloclbicc, attr_ms_abi, @@ -5231,8 +5287,8 @@ template <typename T> const T *Type::castAs() const { ArrayType_cannot_be_used_with_getAs<T> at; (void) at; - assert(isa<T>(CanonicalType)); if (const T *ty = dyn_cast<T>(this)) return ty; + assert(isa<T>(CanonicalType)); return cast<T>(getUnqualifiedDesugaredType()); } diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index 3648d2a5c259..4f3c811ce275 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -1208,7 +1208,7 @@ public: } ArrayRef<ParmVarDecl *> getParams() const { - return ArrayRef<ParmVarDecl *>(getParmArray(), getNumParams()); + return llvm::makeArrayRef(getParmArray(), getNumParams()); } // ParmVarDecls* are stored after Info, one for each parameter. @@ -1567,6 +1567,8 @@ public: void setUnderlyingTInfo(TypeSourceInfo* TI) const { this->getLocalData()->UnderlyingTInfo = TI; } + + void initializeLocal(ASTContext &Context, SourceLocation Loc); }; // FIXME: location of the 'decltype' and parens. diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index 9c9f15e95323..392e544d90c1 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -16,8 +16,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TYPE_ORDERING_H -#define LLVM_CLANG_TYPE_ORDERING_H +#ifndef LLVM_CLANG_AST_TYPEORDERING_H +#define LLVM_CLANG_AST_TYPEORDERING_H #include "clang/AST/CanonicalType.h" #include "clang/AST/Type.h" diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 2ef5800c305f..a11f22d201b7 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -98,7 +98,7 @@ class UnresolvedSetImpl { private: template <unsigned N> friend class UnresolvedSet; UnresolvedSetImpl() {} - UnresolvedSetImpl(const UnresolvedSetImpl &) LLVM_DELETED_FUNCTION; + UnresolvedSetImpl(const UnresolvedSetImpl &) {} 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 8af0546db57b..ce2674e442da 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -38,10 +38,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H -#define LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H +#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H +#define LLVM_CLANG_ASTMATCHERS_ASTMATCHFINDER_H #include "clang/ASTMatchers/ASTMatchers.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/Support/Timer.h" namespace clang { @@ -102,6 +104,12 @@ public: /// /// Optionally override to do per translation unit tasks. virtual void onEndOfTranslationUnit() {} + + /// \brief An id used to group the matchers. + /// + /// This id is used, for example, for the profiling output. + /// It defaults to "<unknown>". + virtual StringRef getID() const; }; /// \brief Called when parsing is finished. Intended for testing only. @@ -111,7 +119,22 @@ public: virtual void run() = 0; }; - MatchFinder(); + struct MatchFinderOptions { + struct Profiling { + Profiling(llvm::StringMap<llvm::TimeRecord> &Records) + : Records(Records) {} + + /// \brief Per bucket timing information. + llvm::StringMap<llvm::TimeRecord> &Records; + }; + + /// \brief Enables per-check timers. + /// + /// It prints a report after match. + llvm::Optional<Profiling> CheckProfiling; + }; + + MatchFinder(MatchFinderOptions Options = MatchFinderOptions()); ~MatchFinder(); /// \brief Adds a matcher to execute when running over the AST. @@ -148,7 +171,7 @@ public: MatchCallback *Action); /// \brief Creates a clang ASTConsumer that finds all matches. - clang::ASTConsumer *newASTConsumer(); + std::unique_ptr<clang::ASTConsumer> newASTConsumer(); /// \brief Calls the registered callbacks on all matches on the given \p Node. /// @@ -173,11 +196,25 @@ public: /// Each call to FindAll(...) will call the closure once. void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); -private: - /// \brief For each \c DynTypedMatcher a \c MatchCallback that will be called + /// \brief For each \c Matcher<> a \c MatchCallback that will be called /// when it matches. - std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *> > - MatcherCallbackPairs; + struct MatchersByType { + std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>> + DeclOrStmt; + std::vector<std::pair<TypeMatcher, MatchCallback *>> Type; + std::vector<std::pair<NestedNameSpecifierMatcher, MatchCallback *>> + NestedNameSpecifier; + std::vector<std::pair<NestedNameSpecifierLocMatcher, MatchCallback *>> + NestedNameSpecifierLoc; + std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc; + /// \brief All the callbacks in one container to simplify iteration. + std::vector<MatchCallback *> AllCallbacks; + }; + +private: + MatchersByType Matchers; + + MatchFinderOptions Options; /// \brief Called when parsing is done. ParsingDoneTestCallback *ParsingDone; @@ -210,16 +247,14 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, /// /// This is useful in combanation with \c match(): /// \code -/// Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), -/// Node, Context)); +/// const Decl *D = selectFirst<Decl>("id", match(Matcher.bind("id"), +/// Node, Context)); /// \endcode template <typename NodeT> -NodeT * +const NodeT * selectFirst(StringRef BoundTo, const SmallVectorImpl<BoundNodes> &Results) { - for (SmallVectorImpl<BoundNodes>::const_iterator I = Results.begin(), - E = Results.end(); - I != E; ++I) { - if (NodeT *Node = I->getNodeAs<NodeT>(BoundTo)) + for (const BoundNodes &N : Results) { + if (const NodeT *Node = N.getNodeAs<NodeT>(BoundTo)) return Node; } return nullptr; @@ -243,7 +278,7 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, MatchFinder Finder; Finder.addMatcher(Matcher, &Callback); Finder.match(Node, Context); - return Callback.Nodes; + return std::move(Callback.Nodes); } template <typename MatcherT, typename NodeT> @@ -255,4 +290,4 @@ match(MatcherT Matcher, const NodeT &Node, ASTContext &Context) { } // end namespace ast_matchers } // end namespace clang -#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCH_FINDER_H +#endif diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 1ff4ab367fd5..f002cb9cbaba 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -42,9 +42,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H -#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H +#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H +#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERS_H +#include "clang/AST/ASTContext.h" #include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" @@ -140,9 +141,97 @@ typedef internal::Matcher<NestedNameSpecifierLoc> NestedNameSpecifierLocMatcher; /// \endcode /// /// Usable as: Any Matcher -inline internal::PolymorphicMatcherWithParam0<internal::TrueMatcher> -anything() { - return internal::PolymorphicMatcherWithParam0<internal::TrueMatcher>(); +inline internal::TrueMatcher anything() { return internal::TrueMatcher(); } + +/// \brief Matches typedef declarations. +/// +/// Given +/// \code +/// typedef int X; +/// \endcode +/// typedefDecl() +/// matches "typedef int X" +const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; + +/// \brief Matches AST nodes that were expanded within the main-file. +/// +/// Example matches X but not Y (matcher = recordDecl(isExpansionInMainFile()) +/// \code +/// #include <Y.h> +/// class X {}; +/// \endcode +/// Y.h: +/// \code +/// class Y {}; +/// \endcode +/// +/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc> +AST_POLYMORPHIC_MATCHER(isExpansionInMainFile, + AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt, + TypeLoc)) { + auto &SourceManager = Finder->getASTContext().getSourceManager(); + return SourceManager.isInMainFile( + SourceManager.getExpansionLoc(Node.getLocStart())); +} + +/// \brief Matches AST nodes that were expanded within system-header-files. +/// +/// Example matches Y but not X +/// (matcher = recordDecl(isExpansionInSystemHeader()) +/// \code +/// #include <SystemHeader.h> +/// class X {}; +/// \endcode +/// SystemHeader.h: +/// \code +/// class Y {}; +/// \endcode +/// +/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc> +AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader, + AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt, + TypeLoc)) { + auto &SourceManager = Finder->getASTContext().getSourceManager(); + auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart()); + if (ExpansionLoc.isInvalid()) { + return false; + } + return SourceManager.isInSystemHeader(ExpansionLoc); +} + +/// \brief Matches AST nodes that were expanded within files whose name is +/// partially matching a given regex. +/// +/// Example matches Y but not X +/// (matcher = recordDecl(isExpansionInFileMatching("AST.*")) +/// \code +/// #include "ASTMatcher.h" +/// class X {}; +/// \endcode +/// ASTMatcher.h: +/// \code +/// class Y {}; +/// \endcode +/// +/// Usable as: Matcher<Decl>, Matcher<Stmt>, Matcher<TypeLoc> +AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching, + AST_POLYMORPHIC_SUPPORTED_TYPES_3(Decl, Stmt, + TypeLoc), + std::string, RegExp) { + auto &SourceManager = Finder->getASTContext().getSourceManager(); + auto ExpansionLoc = SourceManager.getExpansionLoc(Node.getLocStart()); + if (ExpansionLoc.isInvalid()) { + return false; + } + auto FileEntry = + SourceManager.getFileEntryForID(SourceManager.getFileID(ExpansionLoc)); + if (!FileEntry) { + return false; + } + + auto Filename = FileEntry->getName(); + llvm::Regex RE(RegExp); + return RE.match(Filename); } /// \brief Matches declarations. @@ -156,6 +245,17 @@ anything() { /// \endcode const internal::VariadicAllOfMatcher<Decl> decl; +/// \brief Matches a declaration of a linkage specification. +/// +/// Given +/// \code +/// extern "C" {} +/// \endcode +/// linkageSpecDecl() +/// matches "extern "C" {}" +const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> + linkageSpecDecl; + /// \brief Matches a declaration of anything that could have a name. /// /// Example matches \c X, \c S, the anonymous union type, \c i, and \c U; @@ -263,6 +363,17 @@ const internal::VariadicDynCastAllOfMatcher< /// \endcode const internal::VariadicAllOfMatcher<CXXCtorInitializer> ctorInitializer; +/// \brief Matches template arguments. +/// +/// Given +/// \code +/// template <typename T> struct C {}; +/// C<int> c; +/// \endcode +/// templateArgument() +/// matches 'int' in C<int>. +const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; + /// \brief Matches public C++ declarations. /// /// Given @@ -441,6 +552,23 @@ AST_POLYMORPHIC_MATCHER_P2( return InnerMatcher.matches(List[N], Finder, Builder); } +/// \brief Matches if the number of template arguments equals \p N. +/// +/// Given +/// \code +/// template<typename T> struct C {}; +/// C<int> c; +/// \endcode +/// classTemplateSpecializationDecl(templateArgumentCountIs(1)) +/// matches C<int>. +AST_POLYMORPHIC_MATCHER_P( + templateArgumentCountIs, + AST_POLYMORPHIC_SUPPORTED_TYPES_2(ClassTemplateSpecializationDecl, + TemplateSpecializationType), + unsigned, N) { + return internal::getTemplateSpecializationArgs(Node).size() == N; +} + /// \brief Matches a TemplateArgument that refers to a certain type. /// /// Given @@ -497,6 +625,68 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) { return false; } +/// \brief Matches a TemplateArgument that is an integral value. +/// +/// Given +/// \code +/// template<int T> struct A {}; +/// C<42> c; +/// \endcode +/// classTemplateSpecializationDecl( +/// hasAnyTemplateArgument(isIntegral())) +/// matches the implicit instantiation of C in C<42> +/// with isIntegral() matching 42. +AST_MATCHER(TemplateArgument, isIntegral) { + return Node.getKind() == TemplateArgument::Integral; +} + +/// \brief Matches a TemplateArgument that referes to an integral type. +/// +/// Given +/// \code +/// template<int T> struct A {}; +/// C<42> c; +/// \endcode +/// classTemplateSpecializationDecl( +/// hasAnyTemplateArgument(refersToIntegralType(asString("int")))) +/// matches the implicit instantiation of C in C<42>. +AST_MATCHER_P(TemplateArgument, refersToIntegralType, + internal::Matcher<QualType>, InnerMatcher) { + if (Node.getKind() != TemplateArgument::Integral) + return false; + return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder); +} + +/// \brief Matches a TemplateArgument of integral type with a given value. +/// +/// Note that 'Value' is a string as the template argument's value is +/// an arbitrary precision integer. 'Value' must be euqal to the canonical +/// representation of that integral value in base 10. +/// +/// Given +/// \code +/// template<int T> struct A {}; +/// C<42> c; +/// \endcode +/// classTemplateSpecializationDecl( +/// hasAnyTemplateArgument(equalsIntegralValue("42"))) +/// matches the implicit instantiation of C in C<42>. +AST_MATCHER_P(TemplateArgument, equalsIntegralValue, + std::string, Value) { + if (Node.getKind() != TemplateArgument::Integral) + return false; + return Node.getAsIntegral().toString(10) == Value; +} + +/// \brief Matches any value declaration. +/// +/// Example matches A, B, C and F +/// \code +/// enum X { A, B, C }; +/// void F(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; + /// \brief Matches C++ constructor declarations. /// /// Example matches Foo::Foo() and Foo::Foo(int) @@ -1414,21 +1604,21 @@ const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; /// /// Usable as: Any Matcher const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> eachOf = { - internal::EachOfVariadicOperator + internal::DynTypedMatcher::VO_EachOf }; /// \brief Matches if any of the given matchers matches. /// /// Usable as: Any Matcher const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> anyOf = { - internal::AnyOfVariadicOperator + internal::DynTypedMatcher::VO_AnyOf }; /// \brief Matches if all given matchers match. /// /// Usable as: Any Matcher const internal::VariadicOperatorMatcherFunc<2, UINT_MAX> allOf = { - internal::AllOfVariadicOperator + internal::DynTypedMatcher::VO_AllOf }; /// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) @@ -1502,16 +1692,8 @@ inline internal::Matcher<Stmt> sizeOfExpr( /// \code /// namespace a { namespace b { class X; } } /// \endcode -AST_MATCHER_P(NamedDecl, hasName, std::string, Name) { - assert(!Name.empty()); - const std::string FullNameString = "::" + Node.getQualifiedNameAsString(); - const StringRef FullName = FullNameString; - const StringRef Pattern = Name; - if (Pattern.startswith("::")) { - return FullName == Pattern; - } else { - return FullName.endswith(("::" + Pattern).str()); - } +inline internal::Matcher<NamedDecl> hasName(const std::string &Name) { + return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Name)); } /// \brief Matches NamedDecl nodes whose fully qualified names contain @@ -1558,7 +1740,7 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { inline internal::PolymorphicMatcherWithParam1< internal::HasOverloadedOperatorNameMatcher, StringRef, AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)> -hasOverloadedOperatorName(const StringRef Name) { +hasOverloadedOperatorName(StringRef Name) { return internal::PolymorphicMatcherWithParam1< internal::HasOverloadedOperatorNameMatcher, StringRef, AST_POLYMORPHIC_SUPPORTED_TYPES_2(CXXOperatorCallExpr, FunctionDecl)>( @@ -1592,7 +1774,7 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, } /// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). -AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, StringRef, BaseName, 1) { +AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) { assert(!BaseName.empty()); return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); } @@ -1607,8 +1789,8 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, /// \brief Overloaded method as shortcut for /// \c isSameOrDerivedFrom(hasName(...)). -AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, StringRef, BaseName, - 1) { +AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string, + BaseName, 1) { assert(!BaseName.empty()); return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); } @@ -1768,7 +1950,7 @@ const internal::ArgumentAdaptingMatcherFunc< /// /// Usable as: Any Matcher const internal::VariadicOperatorMatcherFunc<1, 1> unless = { - internal::NotUnaryOperator + internal::DynTypedMatcher::VO_UnaryNot }; /// \brief Matches a node if the declaration associated with that node @@ -1844,7 +2026,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, /// Example matches y.x() (matcher = callExpr(callee(methodDecl(hasName("x"))))) /// \code /// class Y { public: void x(); }; -/// void z() { Y y; y.x(); +/// void z() { Y y; y.x(); } /// \endcode AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher, 1) { @@ -1952,6 +2134,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>, /// void a(X b) { /// X &x = b; /// const X &y = b; +/// } /// }; /// \endcode AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, @@ -2280,11 +2463,10 @@ AST_MATCHER(CXXCtorInitializer, isWritten) { AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES_2( CallExpr, CXXConstructExpr), internal::Matcher<Expr>, InnerMatcher) { - for (unsigned I = 0; I < Node.getNumArgs(); ++I) { + for (const Expr *Arg : Node.arguments()) { BoundNodesTreeBuilder Result(*Builder); - if (InnerMatcher.matches(*Node.getArg(I)->IgnoreParenImpCasts(), Finder, - &Result)) { - *Builder = Result; + if (InnerMatcher.matches(*Arg->IgnoreParenImpCasts(), Finder, &Result)) { + *Builder = std::move(Result); return true; } } @@ -2372,6 +2554,19 @@ AST_MATCHER(FunctionDecl, isExternC) { return Node.isExternC(); } +/// \brief Matches deleted function declarations. +/// +/// Given: +/// \code +/// void Func(); +/// void DeletedFunc() = delete; +/// \endcode +/// functionDecl(isDeleted()) +/// matches the declaration of DeletedFunc, but not Func. +AST_MATCHER(FunctionDecl, isDeleted) { + return Node.isDeleted(); +} + /// \brief Matches the condition expression of an if statement, for loop, /// or conditional operator. /// @@ -2953,6 +3148,43 @@ AST_POLYMORPHIC_MATCHER( TSK_ExplicitInstantiationDefinition); } +/// \brief Matches declarations that are template instantiations or are inside +/// template instantiations. +/// +/// Given +/// \code +/// template<typename T> void A(T t) { T i; } +/// A(0); +/// A(0U); +/// \endcode +/// functionDecl(isInstantiated()) +/// matches 'A(int) {...};' and 'A(unsigned) {...}'. +AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) { + auto IsInstantiation = decl(anyOf(recordDecl(isTemplateInstantiation()), + functionDecl(isTemplateInstantiation()))); + return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation))); +} + +/// \brief Matches statements inside of a template instantiation. +/// +/// Given +/// \code +/// int j; +/// template<typename T> void A(T t) { T i; j += 42;} +/// A(0); +/// A(0U); +/// \endcode +/// declStmt(isInTemplateInstantiation()) +/// matches 'int i;' and 'unsigned i'. +/// unless(stmt(isInTemplateInstantiation())) +/// will NOT match j += 42; as it's shared between the template definition and +/// instantiation. +AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) { + return stmt( + hasAncestor(decl(anyOf(recordDecl(isTemplateInstantiation()), + functionDecl(isTemplateInstantiation()))))); +} + /// \brief Matches explicit template specializations of function, class, or /// static member variable template instantiations. /// @@ -2979,6 +3211,18 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc, new internal::TypeLocTypeMatcher(InnerMatcher)); } +/// \brief Matches type \c void. +/// +/// Given +/// \code +/// struct S { void func(); }; +/// \endcode +/// functionDecl(returns(voidType())) +/// matches "void func();" +AST_MATCHER(Type, voidType) { + return Node.isVoidType(); +} + /// \brief Matches builtin Types. /// /// Given @@ -3094,6 +3338,7 @@ AST_TYPE_MATCHER(IncompleteArrayType, incompleteArrayType); /// int a[] = { 2, 3 } /// int b[42]; /// int c[a[0]]; +/// } /// \endcode /// variableArrayType() /// matches "int c[a[0]]" @@ -3432,8 +3677,9 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>, /// \c recordDecl(hasDeclContext(namedDecl(hasName("M")))) matches the /// declaration of \c class \c D. AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) { - return InnerMatcher.matches(*Decl::castFromDeclContext(Node.getDeclContext()), - Finder, Builder); + const DeclContext *DC = Node.getDeclContext(); + if (!DC) return false; + return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder); } /// \brief Matches nested name specifiers. @@ -3599,7 +3845,7 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>, Result.addMatch(CaseBuilder); } } - *Builder = Result; + *Builder = std::move(Result); return Matched; } @@ -3622,7 +3868,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer, Result.addMatch(InitBuilder); } } - *Builder = Result; + *Builder = std::move(Result); return Matched; } @@ -3643,7 +3889,32 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>, return InnerMatcher.matches(*Node.getLHS(), Finder, Builder); } +/// \brief Matches declaration that has a given attribute. +/// +/// Given +/// \code +/// __attribute__((device)) void f() { ... } +/// \endcode +/// decl(hasAttr(clang::attr::CUDADevice)) matches the function declaration of +/// f. +AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) { + for (const auto *Attr : Node.attrs()) { + if (Attr->getKind() == AttrKind) + return true; + } + return false; +} + +/// \brief Matches CUDA kernel call expression. +/// +/// Example matches, +/// \code +/// kernel<<<i,j>>>(); +/// \endcode +const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> + CUDAKernelCallExpr; + } // end namespace ast_matchers } // end namespace clang -#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_H +#endif diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 94435fd274eb..ebe5cddb622a 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -32,8 +32,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H -#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H +#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H +#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSINTERNAL_H #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" @@ -44,6 +44,7 @@ #include "clang/AST/Type.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/VariadicFunction.h" +#include "llvm/Support/ManagedStatic.h" #include <map> #include <string> #include <vector> @@ -61,9 +62,8 @@ public: /// \brief Adds \c Node to the map with key \c ID. /// /// The node's base type should be in NodeBaseType or it will be unaccessible. - template <typename T> - void addNode(StringRef ID, const T* Node) { - NodeMap[ID] = ast_type_traits::DynTypedNode::create(*Node); + void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) { + NodeMap[ID] = DynNode; } /// \brief Returns the AST node bound to \c ID. @@ -103,6 +103,16 @@ public: return NodeMap; } + /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all + /// stored nodes have memoization data. + bool isComparable() const { + for (const auto &IDAndNode : NodeMap) { + if (!IDAndNode.second.getMemoizationData()) + return false; + } + return true; + } + private: IDToNodeMap NodeMap; }; @@ -126,11 +136,12 @@ public: }; /// \brief Add a binding from an id to a node. - template <typename T> void setBinding(const std::string &Id, const T *Node) { + void setBinding(const std::string &Id, + const ast_type_traits::DynTypedNode &DynNode) { if (Bindings.empty()) Bindings.push_back(BoundNodesMap()); - for (unsigned i = 0, e = Bindings.size(); i != e; ++i) - Bindings[i].addNode(Id, Node); + for (BoundNodesMap &Binding : Bindings) + Binding.addNode(Id, DynNode); } /// \brief Adds a branch in the tree. @@ -153,12 +164,38 @@ public: return Bindings < Other.Bindings; } + /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared, + /// i.e. all stored node maps have memoization data. + bool isComparable() const { + for (const BoundNodesMap &NodesMap : Bindings) { + if (!NodesMap.isComparable()) + return false; + } + return true; + } + private: SmallVector<BoundNodesMap, 16> Bindings; }; class ASTMatchFinder; +/// \brief Generic interface for all matchers. +/// +/// Used by the implementation of Matcher<T> and DynTypedMatcher. +/// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T> +/// instead. +class DynMatcherInterface : public RefCountedBaseVPTR { +public: + /// \brief Returns true if \p DynNode can be matched. + /// + /// May bind \p DynNode to an ID via \p Builder, or recurse into + /// the AST via \p Finder. + virtual bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const = 0; +}; + /// \brief Generic interface for matchers on an AST node of type T. /// /// Implement this if your matcher may need to inspect the children or @@ -167,7 +204,7 @@ class ASTMatchFinder; /// current node and doesn't care about its children or descendants, /// implement SingleNodeMatcherInterface instead. template <typename T> -class MatcherInterface : public RefCountedBaseVPTR { +class MatcherInterface : public DynMatcherInterface { public: virtual ~MatcherInterface() {} @@ -178,6 +215,12 @@ public: virtual bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const = 0; + + bool dynMatches(const ast_type_traits::DynTypedNode &DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const override { + return matches(DynNode.getUnchecked<T>(), Finder, Builder); + } }; /// \brief Interface for matchers that only evaluate properties on a single @@ -199,6 +242,145 @@ private: } }; +template <typename> class Matcher; + +/// \brief Matcher that works on a \c DynTypedNode. +/// +/// It is constructed from a \c Matcher<T> object and redirects most calls to +/// underlying matcher. +/// It checks whether the \c DynTypedNode is convertible into the type of the +/// underlying matcher and then do the actual match on the actual node, or +/// return false if it is not convertible. +class DynTypedMatcher { +public: + /// \brief Takes ownership of the provided implementation pointer. + template <typename T> + DynTypedMatcher(MatcherInterface<T> *Implementation) + : AllowBind(false), + SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()), + RestrictKind(SupportedKind), Implementation(Implementation) {} + + /// \brief Construct from a variadic function. + enum VariadicOperator { + /// \brief Matches nodes for which all provided matchers match. + VO_AllOf, + /// \brief Matches nodes for which at least one of the provided matchers + /// matches. + VO_AnyOf, + /// \brief Matches nodes for which at least one of the provided matchers + /// matches, but doesn't stop at the first match. + VO_EachOf, + /// \brief Matches nodes that do not match the provided matcher. + /// + /// Uses the variadic matcher interface, but fails if + /// InnerMatchers.size() != 1. + VO_UnaryNot + }; + static DynTypedMatcher + constructVariadic(VariadicOperator Op, + std::vector<DynTypedMatcher> InnerMatchers); + + /// \brief Get a "true" matcher for \p NodeKind. + /// + /// It only checks that the node is of the right kind. + static DynTypedMatcher trueMatcher(ast_type_traits::ASTNodeKind NodeKind); + + void setAllowBind(bool AB) { AllowBind = AB; } + + /// \brief Check whether this matcher could ever match a node of kind \p Kind. + /// \return \c false if this matcher will never match such a node. Otherwise, + /// return \c true. + bool canMatchNodesOfKind(ast_type_traits::ASTNodeKind Kind) const; + + /// \brief Return a matcher that points to the same implementation, but + /// restricts the node types for \p Kind. + DynTypedMatcher dynCastTo(const ast_type_traits::ASTNodeKind Kind) const; + + /// \brief Returns true if the matcher matches the given \c DynNode. + bool matches(const ast_type_traits::DynTypedNode &DynNode, + ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const; + + /// \brief Same as matches(), but skips the kind check. + /// + /// It is faster, but the caller must ensure the node is valid for the + /// kind of this matcher. + bool matchesNoKindCheck(const ast_type_traits::DynTypedNode &DynNode, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const; + + /// \brief Bind the specified \p ID to the matcher. + /// \return A new matcher with the \p ID bound to it if this matcher supports + /// binding. Otherwise, returns an empty \c Optional<>. + llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const; + + /// \brief Returns a unique \p ID for the matcher. + /// + /// Casting a Matcher<T> to Matcher<U> creates a matcher that has the + /// same \c Implementation pointer, but different \c RestrictKind. We need to + /// include both in the ID to make it unique. + /// + /// \c MatcherIDType supports operator< and provides strict weak ordering. + typedef std::pair<ast_type_traits::ASTNodeKind, uint64_t> MatcherIDType; + MatcherIDType getID() const { + /// FIXME: Document the requirements this imposes on matcher + /// implementations (no new() implementation_ during a Matches()). + return std::make_pair(RestrictKind, + reinterpret_cast<uint64_t>(Implementation.get())); + } + + /// \brief Returns the type this matcher works on. + /// + /// \c matches() will always return false unless the node passed is of this + /// or a derived type. + ast_type_traits::ASTNodeKind getSupportedKind() const { + return SupportedKind; + } + + /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted + /// to a \c Matcher<T>. + /// + /// This method verifies that the underlying matcher in \c Other can process + /// nodes of types T. + template <typename T> bool canConvertTo() const { + return canConvertTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + } + bool canConvertTo(ast_type_traits::ASTNodeKind To) const; + + /// \brief Construct a \c Matcher<T> interface around the dynamic matcher. + /// + /// This method asserts that \c canConvertTo() is \c true. Callers + /// should call \c canConvertTo() first to make sure that \c this is + /// compatible with T. + template <typename T> Matcher<T> convertTo() const { + assert(canConvertTo<T>()); + return unconditionalConvertTo<T>(); + } + + /// \brief Same as \c convertTo(), but does not check that the underlying + /// matcher can handle a value of T. + /// + /// If it is not compatible, then this matcher will never match anything. + template <typename T> Matcher<T> unconditionalConvertTo() const; + +private: + DynTypedMatcher(ast_type_traits::ASTNodeKind SupportedKind, + ast_type_traits::ASTNodeKind RestrictKind, + IntrusiveRefCntPtr<DynMatcherInterface> Implementation) + : AllowBind(false), + SupportedKind(SupportedKind), + RestrictKind(RestrictKind), + Implementation(std::move(Implementation)) {} + + bool AllowBind; + ast_type_traits::ASTNodeKind SupportedKind; + /// \brief A potentially stricter node kind. + /// + /// It allows to perform implicit and dynamic cast of matchers without + /// needing to change \c Implementation. + ast_type_traits::ASTNodeKind RestrictKind; + IntrusiveRefCntPtr<DynMatcherInterface> Implementation; +}; + /// \brief Wrapper of a MatcherInterface<T> *that allows copying. /// /// A Matcher<Base> can be used anywhere a Matcher<Derived> is @@ -221,7 +403,10 @@ public: Matcher(const Matcher<From> &Other, typename std::enable_if<std::is_base_of<From, T>::value && !std::is_same<From, T>::value>::type * = 0) - : Implementation(new ImplicitCastMatcher<From>(Other)) {} + : Implementation(restrictMatcher(Other.Implementation)) { + assert(Implementation.getSupportedKind().isSame( + ast_type_traits::ASTNodeKind::getFromNodeKind<T>())); + } /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. /// @@ -233,26 +418,34 @@ public: std::is_same<TypeT, Type>::value>::type* = 0) : Implementation(new TypeToQualType<TypeT>(Other)) {} + /// \brief Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the + /// argument. + /// \c To must be a base class of \c T. + template <typename To> + Matcher<To> dynCastTo() const { + static_assert(std::is_base_of<To, T>::value, "Invalid dynCast call."); + return Matcher<To>(Implementation); + } + /// \brief Forwards the call to the underlying MatcherInterface<T> pointer. bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - if (Implementation->matches(Node, Finder, Builder)) - return true; - // Delete all bindings when a matcher does not match. - // This prevents unexpected exposure of bound nodes in unmatches - // branches of the match tree. - *Builder = BoundNodesTreeBuilder(); - return false; + return Implementation.matches(ast_type_traits::DynTypedNode::create(Node), + Finder, Builder); } /// \brief Returns an ID that uniquely identifies the matcher. - uint64_t getID() const { - /// FIXME: Document the requirements this imposes on matcher - /// implementations (no new() implementation_ during a Matches()). - return reinterpret_cast<uint64_t>(Implementation.get()); + DynTypedMatcher::MatcherIDType getID() const { + return Implementation.getID(); } + /// \brief Extract the dynamic matcher. + /// + /// The returned matcher keeps the same restrictions as \c this and remembers + /// that it is meant to support nodes of type \c T. + operator DynTypedMatcher() const { return Implementation; } + /// \brief Allows the conversion of a \c Matcher<Type> to a \c /// Matcher<QualType>. /// @@ -276,24 +469,22 @@ public: }; private: - /// \brief Allows conversion from Matcher<Base> to Matcher<T> if T - /// is derived from Base. - template <typename Base> - class ImplicitCastMatcher : public MatcherInterface<T> { - public: - explicit ImplicitCastMatcher(const Matcher<Base> &From) - : From(From) {} + // For Matcher<T> <=> Matcher<U> conversions. + template <typename U> friend class Matcher; + // For DynTypedMatcher::unconditionalConvertTo<T>. + friend class DynTypedMatcher; - bool matches(const T &Node, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const override { - return From.matches(Node, Finder, Builder); - } + static DynTypedMatcher restrictMatcher(const DynTypedMatcher &Other) { + return Other.dynCastTo(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); + } - private: - const Matcher<Base> From; - }; + explicit Matcher(const DynTypedMatcher &Implementation) + : Implementation(restrictMatcher(Implementation)) { + assert(this->Implementation.getSupportedKind() + .isSame(ast_type_traits::ASTNodeKind::getFromNodeKind<T>())); + } - IntrusiveRefCntPtr< MatcherInterface<T> > Implementation; + DynTypedMatcher Implementation; }; // class Matcher /// \brief A convenient helper for creating a Matcher<T> without specifying @@ -303,153 +494,10 @@ inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { return Matcher<T>(Implementation); } -template <typename T> class BindableMatcher; - -/// \brief Matcher that works on a \c DynTypedNode. -/// -/// It is constructed from a \c Matcher<T> object and redirects most calls to -/// underlying matcher. -/// It checks whether the \c DynTypedNode is convertible into the type of the -/// underlying matcher and then do the actual match on the actual node, or -/// return false if it is not convertible. -class DynTypedMatcher { -public: - /// \brief Construct from a \c Matcher<T>. Copies the matcher. - template <typename T> inline DynTypedMatcher(const Matcher<T> &M); - - /// \brief Construct from a bindable \c Matcher<T>. Copies the matcher. - /// - /// This version enables \c tryBind() on the \c DynTypedMatcher. - template <typename T> inline DynTypedMatcher(const BindableMatcher<T> &M); - - /// \brief Returns true if the matcher matches the given \c DynNode. - bool matches(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { - return Storage->matches(DynNode, Finder, Builder); - } - - /// \brief Bind the specified \p ID to the matcher. - /// \return A new matcher with the \p ID bound to it if this matcher supports - /// binding. Otherwise, returns an empty \c Optional<>. - llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const { - return Storage->tryBind(ID); - } - - /// \brief Returns a unique \p ID for the matcher. - uint64_t getID() const { return Storage->getID(); } - - /// \brief Returns the type this matcher works on. - /// - /// \c matches() will always return false unless the node passed is of this - /// or a derived type. - ast_type_traits::ASTNodeKind getSupportedKind() const { - return Storage->getSupportedKind(); - } - - /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted - /// to a \c Matcher<T>. - /// - /// This method verifies that the underlying matcher in \c Other can process - /// nodes of types T. - template <typename T> bool canConvertTo() const { - return getSupportedKind().isBaseOf( - ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); - } - - /// \brief Construct a \c Matcher<T> interface around the dynamic matcher. - /// - /// This method asserts that \c canConvertTo() is \c true. Callers - /// should call \c canConvertTo() first to make sure that \c this is - /// compatible with T. - template <typename T> Matcher<T> convertTo() const { - assert(canConvertTo<T>()); - return unconditionalConvertTo<T>(); - } - - /// \brief Same as \c convertTo(), but does not check that the underlying - /// matcher can handle a value of T. - /// - /// If it is not compatible, then this matcher will never match anything. - template <typename T> Matcher<T> unconditionalConvertTo() const; - -private: - class MatcherStorage : public RefCountedBaseVPTR { - public: - MatcherStorage(ast_type_traits::ASTNodeKind SupportedKind, uint64_t ID) - : SupportedKind(SupportedKind), ID(ID) {} - virtual ~MatcherStorage(); - - virtual bool matches(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const = 0; - - virtual llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const = 0; - - ast_type_traits::ASTNodeKind getSupportedKind() const { - return SupportedKind; - } - - uint64_t getID() const { return ID; } - - private: - const ast_type_traits::ASTNodeKind SupportedKind; - const uint64_t ID; - }; - - /// \brief Typed implementation of \c MatcherStorage. - template <typename T> class TypedMatcherStorage; - - IntrusiveRefCntPtr<const MatcherStorage> Storage; -}; - -template <typename T> -class DynTypedMatcher::TypedMatcherStorage : public MatcherStorage { -public: - TypedMatcherStorage(const Matcher<T> &Other, bool AllowBind) - : MatcherStorage(ast_type_traits::ASTNodeKind::getFromNodeKind<T>(), - Other.getID()), - InnerMatcher(Other), AllowBind(AllowBind) {} - - bool matches(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const override { - if (const T *Node = DynNode.get<T>()) { - return InnerMatcher.matches(*Node, Finder, Builder); - } - return false; - } - - llvm::Optional<DynTypedMatcher> tryBind(StringRef ID) const override { - if (!AllowBind) - return llvm::Optional<DynTypedMatcher>(); - return DynTypedMatcher(BindableMatcher<T>(InnerMatcher).bind(ID)); - } - -private: - const Matcher<T> InnerMatcher; - const bool AllowBind; -}; - -template <typename T> -inline DynTypedMatcher::DynTypedMatcher(const Matcher<T> &M) - : Storage(new TypedMatcherStorage<T>(M, false)) {} - -template <typename T> -inline DynTypedMatcher::DynTypedMatcher(const BindableMatcher<T> &M) - : Storage(new TypedMatcherStorage<T>(M, true)) {} - /// \brief Specialization of the conversion functions for QualType. /// -/// These specializations provide the Matcher<Type>->Matcher<QualType> +/// This specialization provides the Matcher<Type>->Matcher<QualType> /// conversion that the static API does. -template <> inline bool DynTypedMatcher::canConvertTo<QualType>() const { - const ast_type_traits::ASTNodeKind SourceKind = getSupportedKind(); - return SourceKind.isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<Type>()) || - SourceKind.isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<QualType>()); -} - template <> inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const { assert(canConvertTo<QualType>()); @@ -470,7 +518,7 @@ bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start, for (IteratorT I = Start; I != End; ++I) { BoundNodesTreeBuilder Result(*Builder); if (Matcher.matches(*I, Finder, &Result)) { - *Builder = Result; + *Builder = std::move(Result); return true; } } @@ -486,7 +534,7 @@ bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, for (IteratorT I = Start; I != End; ++I) { BoundNodesTreeBuilder Result(*Builder); if (Matcher.matches(**I, Finder, &Result)) { - *Builder = Result; + *Builder = std::move(Result); return true; } } @@ -549,6 +597,33 @@ private: std::string Name; }; +/// \brief Matches named declarations with a specific name. +/// +/// See \c hasName() in ASTMatchers.h for details. +class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> { + public: + explicit HasNameMatcher(StringRef Name); + + bool matchesNode(const NamedDecl &Node) const override; + + private: + /// \brief Unqualified match routine. + /// + /// It is much faster than the full match, but it only works for unqualified + /// matches. + bool matchesNodeUnqualified(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; + + const bool UseUnqualifiedMatch; + const std::string Name; +}; + /// \brief Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but @@ -973,46 +1048,16 @@ private: /// /// This is useful when a matcher syntactically requires a child matcher, /// but the context doesn't care. See for example: anything(). -/// -/// FIXME: Alternatively we could also create a IsAMatcher or something -/// that checks that a dyn_cast is possible. This is purely needed for the -/// difference between calling for example: -/// record() -/// and -/// record(SomeMatcher) -/// In the second case we need the correct type we were dyn_cast'ed to in order -/// to get the right type for the inner matcher. In the first case we don't need -/// that, but we use the type conversion anyway and insert a TrueMatcher. -template <typename T> -class TrueMatcher : public SingleNodeMatcherInterface<T> { -public: - bool matchesNode(const T &Node) const override { - return true; - } -}; - -/// \brief Matcher<T> that wraps an inner Matcher<T> and binds the matched node -/// to an ID if the inner matcher matches on the node. -template <typename T> -class IdMatcher : public MatcherInterface<T> { -public: - /// \brief Creates an IdMatcher that binds to 'ID' if 'InnerMatcher' matches - /// the node. - IdMatcher(StringRef ID, const Matcher<T> &InnerMatcher) - : ID(ID), InnerMatcher(InnerMatcher) {} +class TrueMatcher { + public: + typedef AllNodeBaseTypes ReturnTypes; - bool matches(const T &Node, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const override { - bool Result = InnerMatcher.matches(Node, Finder, Builder); - if (Result) { - Builder->setBinding(ID, &Node); - } - return Result; + template <typename T> + operator Matcher<T>() const { + return DynTypedMatcher::trueMatcher( + ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) + .template unconditionalConvertTo<T>(); } - -private: - const std::string ID; - const Matcher<T> InnerMatcher; }; /// \brief A Matcher that allows binding the node it matches to an id. @@ -1031,7 +1076,17 @@ public: /// The returned matcher is equivalent to this matcher, but will /// bind the matched node on a match. Matcher<T> bind(StringRef ID) const { - return Matcher<T>(new IdMatcher<T>(ID, *this)); + return DynTypedMatcher(*this) + .tryBind(ID) + ->template unconditionalConvertTo<T>(); + } + + /// \brief Same as Matcher<T>'s conversion operator, but enables binding on + /// the returned matcher. + operator DynTypedMatcher() const { + DynTypedMatcher Result = static_cast<const Matcher<T>&>(*this); + Result.setAllowBind(true); + return Result; } }; @@ -1089,36 +1144,11 @@ private: /// \brief VariadicOperatorMatcher related types. /// @{ -/// \brief Function signature for any variadic operator. It takes the inner -/// matchers as an array of DynTypedMatcher. -typedef bool (*VariadicOperatorFunction)( - const ast_type_traits::DynTypedNode DynNode, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder, ArrayRef<DynTypedMatcher> InnerMatchers); - -/// \brief \c MatcherInterface<T> implementation for an variadic operator. -template <typename T> -class VariadicOperatorMatcherInterface : public MatcherInterface<T> { -public: - VariadicOperatorMatcherInterface(VariadicOperatorFunction Func, - std::vector<DynTypedMatcher> InnerMatchers) - : Func(Func), InnerMatchers(std::move(InnerMatchers)) {} - - bool matches(const T &Node, ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder) const override { - return Func(ast_type_traits::DynTypedNode::create(Node), Finder, Builder, - InnerMatchers); - } - -private: - const VariadicOperatorFunction Func; - const std::vector<DynTypedMatcher> InnerMatchers; -}; - /// \brief "No argument" placeholder to use as template paratemers. struct VariadicOperatorNoArg {}; -/// \brief Polymorphic matcher object that uses a \c VariadicOperatorFunction -/// operator. +/// \brief Polymorphic matcher object that uses a \c +/// DynTypedMatcher::VariadicOperator operator. /// /// Input matchers can have any type (including other polymorphic matcher /// types), and the actual Matcher<T> is generated on demand with an implicit @@ -1133,7 +1163,8 @@ template <typename P1, typename P2 = VariadicOperatorNoArg, typename P9 = VariadicOperatorNoArg> class VariadicOperatorMatcher { public: - VariadicOperatorMatcher(VariadicOperatorFunction Func, const P1 &Param1, + VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, + const P1 &Param1, const P2 &Param2 = VariadicOperatorNoArg(), const P3 &Param3 = VariadicOperatorNoArg(), const P4 &Param4 = VariadicOperatorNoArg(), @@ -1142,7 +1173,7 @@ public: const P7 &Param7 = VariadicOperatorNoArg(), const P8 &Param8 = VariadicOperatorNoArg(), const P9 &Param9 = VariadicOperatorNoArg()) - : Func(Func), Param1(Param1), Param2(Param2), Param3(Param3), + : Op(Op), Param1(Param1), Param2(Param2), Param3(Param3), Param4(Param4), Param5(Param5), Param6(Param6), Param7(Param7), Param8(Param8), Param9(Param9) {} @@ -1157,8 +1188,8 @@ public: addMatcher<T>(Param7, Matchers); addMatcher<T>(Param8, Matchers); addMatcher<T>(Param9, Matchers); - return Matcher<T>( - new VariadicOperatorMatcherInterface<T>(Func, std::move(Matchers))); + return DynTypedMatcher::constructVariadic(Op, std::move(Matchers)) + .template unconditionalConvertTo<T>(); } private: @@ -1173,7 +1204,7 @@ private: static void addMatcher(VariadicOperatorNoArg, std::vector<DynTypedMatcher> &Matchers) {} - const VariadicOperatorFunction Func; + const DynTypedMatcher::VariadicOperator Op; const P1 Param1; const P2 Param2; const P3 Param3; @@ -1191,7 +1222,7 @@ private: /// It supports 1-9 argument overloaded operator(). More can be added if needed. template <unsigned MinCount, unsigned MaxCount> struct VariadicOperatorMatcherFunc { - VariadicOperatorFunction Func; + DynTypedMatcher::VariadicOperator Op; template <unsigned Count, typename T> struct EnableIfValidArity @@ -1200,30 +1231,29 @@ struct VariadicOperatorMatcherFunc { template <typename M1> typename EnableIfValidArity<1, VariadicOperatorMatcher<M1> >::type operator()(const M1 &P1) const { - return VariadicOperatorMatcher<M1>(Func, P1); + return VariadicOperatorMatcher<M1>(Op, P1); } template <typename M1, typename M2> typename EnableIfValidArity<2, VariadicOperatorMatcher<M1, M2> >::type operator()(const M1 &P1, const M2 &P2) const { - return VariadicOperatorMatcher<M1, M2>(Func, P1, P2); + return VariadicOperatorMatcher<M1, M2>(Op, P1, P2); } template <typename M1, typename M2, typename M3> typename EnableIfValidArity<3, VariadicOperatorMatcher<M1, M2, M3> >::type operator()(const M1 &P1, const M2 &P2, const M3 &P3) const { - return VariadicOperatorMatcher<M1, M2, M3>(Func, P1, P2, P3); + return VariadicOperatorMatcher<M1, M2, M3>(Op, P1, P2, P3); } template <typename M1, typename M2, typename M3, typename M4> typename EnableIfValidArity<4, VariadicOperatorMatcher<M1, M2, M3, M4> >::type operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4) const { - return VariadicOperatorMatcher<M1, M2, M3, M4>(Func, P1, P2, P3, P4); + return VariadicOperatorMatcher<M1, M2, M3, M4>(Op, P1, P2, P3, P4); } template <typename M1, typename M2, typename M3, typename M4, typename M5> typename EnableIfValidArity< 5, VariadicOperatorMatcher<M1, M2, M3, M4, M5> >::type operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5) const { - return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Func, P1, P2, P3, P4, - P5); + return VariadicOperatorMatcher<M1, M2, M3, M4, M5>(Op, P1, P2, P3, P4, P5); } template <typename M1, typename M2, typename M3, typename M4, typename M5, typename M6> @@ -1232,7 +1262,7 @@ struct VariadicOperatorMatcherFunc { operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5, const M6 &P6) const { return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6>( - Func, P1, P2, P3, P4, P5, P6); + Op, P1, P2, P3, P4, P5, P6); } template <typename M1, typename M2, typename M3, typename M4, typename M5, typename M6, typename M7> @@ -1241,7 +1271,7 @@ struct VariadicOperatorMatcherFunc { operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5, const M6 &P6, const M7 &P7) const { return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7>( - Func, P1, P2, P3, P4, P5, P6, P7); + Op, P1, P2, P3, P4, P5, P6, P7); } template <typename M1, typename M2, typename M3, typename M4, typename M5, typename M6, typename M7, typename M8> @@ -1250,7 +1280,7 @@ struct VariadicOperatorMatcherFunc { operator()(const M1 &P1, const M2 &P2, const M3 &P3, const M4 &P4, const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8) const { return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8>( - Func, P1, P2, P3, P4, P5, P6, P7, P8); + Op, P1, P2, P3, P4, P5, P6, P7, P8); } template <typename M1, typename M2, typename M3, typename M4, typename M5, typename M6, typename M7, typename M8, typename M9> @@ -1260,55 +1290,40 @@ struct VariadicOperatorMatcherFunc { const M5 &P5, const M6 &P6, const M7 &P7, const M8 &P8, const M9 &P9) const { return VariadicOperatorMatcher<M1, M2, M3, M4, M5, M6, M7, M8, M9>( - Func, P1, P2, P3, P4, P5, P6, P7, P8, P9); + Op, P1, P2, P3, P4, P5, P6, P7, P8, P9); } }; /// @} -/// \brief Matches nodes that do not match the provided matcher. -/// -/// Uses the variadic matcher interface, but fails if InnerMatchers.size()!=1. -bool NotUnaryOperator(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder, - ArrayRef<DynTypedMatcher> InnerMatchers); - -/// \brief Matches nodes for which all provided matchers match. -bool AllOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder, - ArrayRef<DynTypedMatcher> InnerMatchers); - -/// \brief Matches nodes for which at least one of the provided matchers -/// matches, but doesn't stop at the first match. -bool EachOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder, - ArrayRef<DynTypedMatcher> InnerMatchers); - -/// \brief Matches nodes for which at least one of the provided matchers -/// matches. -bool AnyOfVariadicOperator(const ast_type_traits::DynTypedNode DynNode, - ASTMatchFinder *Finder, - BoundNodesTreeBuilder *Builder, - ArrayRef<DynTypedMatcher> InnerMatchers); - template <typename T> inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const { - return Matcher<T>(new VariadicOperatorMatcherInterface<T>( - AllOfVariadicOperator, llvm::makeArrayRef(*this))); + return Matcher<T>(*this); } /// \brief Creates a Matcher<T> that matches if all inner matchers match. template<typename T> BindableMatcher<T> makeAllOfComposite( ArrayRef<const Matcher<T> *> InnerMatchers) { - std::vector<DynTypedMatcher> DynMatchers; - for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { - DynMatchers.push_back(*InnerMatchers[i]); + // For the size() == 0 case, we return a "true" matcher. + if (InnerMatchers.size() == 0) { + return BindableMatcher<T>(TrueMatcher()); + } + // For the size() == 1 case, we simply return that one matcher. + // No need to wrap it in a variadic operation. + if (InnerMatchers.size() == 1) { + return BindableMatcher<T>(*InnerMatchers[0]); } - return BindableMatcher<T>(new VariadicOperatorMatcherInterface<T>( - AllOfVariadicOperator, std::move(DynMatchers))); + + std::vector<DynTypedMatcher> DynMatchers; + DynMatchers.reserve(InnerMatchers.size()); + for (const auto *InnerMatcher : InnerMatchers) { + DynMatchers.push_back(*InnerMatcher); + } + return BindableMatcher<T>( + DynTypedMatcher::constructVariadic(DynTypedMatcher::VO_AllOf, + std::move(DynMatchers)) + .template unconditionalConvertTo<T>()); } /// \brief Creates a Matcher<T> that matches if @@ -1320,8 +1335,8 @@ BindableMatcher<T> makeAllOfComposite( template<typename T, typename InnerT> BindableMatcher<T> makeDynCastAllOfComposite( ArrayRef<const Matcher<InnerT> *> InnerMatchers) { - return BindableMatcher<T>(DynTypedMatcher(makeAllOfComposite(InnerMatchers)) - .unconditionalConvertTo<T>()); + return BindableMatcher<T>( + makeAllOfComposite(InnerMatchers).template dynCastTo<T>()); } /// \brief Matches nodes of type T that have at least one descendant node of @@ -1606,6 +1621,23 @@ private: const Matcher<InnerTBase> InnerMatcher; }; +/// \brief A simple memoizer of T(*)() functions. +/// +/// It will call the passed 'Func' template parameter at most once. +/// Used to support AST_MATCHER_FUNCTION() macro. +template <typename Matcher, Matcher (*Func)()> class MemoizedMatcher { + struct Wrapper { + Wrapper() : M(Func()) {} + Matcher M; + }; + +public: + static const Matcher &getInstance() { + static llvm::ManagedStatic<Wrapper> Instance; + return Instance->M; + } +}; + // Define the create() method out of line to silence a GCC warning about // the struct "Func" having greater visibility than its base, which comes from // using the flag -fvisibility-inlines-hidden. @@ -1627,7 +1659,7 @@ getTemplateSpecializationArgs(const ClassTemplateSpecializationDecl &D) { inline ArrayRef<TemplateArgument> getTemplateSpecializationArgs(const TemplateSpecializationType &T) { - return ArrayRef<TemplateArgument>(T.getArgs(), T.getNumArgs()); + return llvm::makeArrayRef(T.getArgs(), T.getNumArgs()); } struct NotEqualsBoundNodePredicate { @@ -1642,4 +1674,4 @@ struct NotEqualsBoundNodePredicate { } // end namespace ast_matchers } // end namespace clang -#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_INTERNAL_H +#endif diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index 563372a50609..b7888be7c176 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -34,8 +34,19 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H -#define LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H +#ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H +#define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H + +/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { +/// defines a zero parameter function named DefineMatcher() that returns a +/// ReturnType object. +#define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \ + inline ReturnType DefineMatcher##_getInstance(); \ + inline ReturnType DefineMatcher() { \ + return internal::MemoizedMatcher< \ + ReturnType, DefineMatcher##_getInstance>::getInstance(); \ + } \ + inline ReturnType DefineMatcher##_getInstance() /// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { /// defines a single-parameter function named DefineMatcher() that returns a @@ -352,4 +363,4 @@ internal::TypeLocTraverseMatcher, ReturnTypesF>::Func MatcherName##Loc; \ AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName##Type, ReturnTypesF) -#endif // LLVM_CLANG_AST_MATCHERS_AST_MATCHERS_MACROS_H +#endif diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h index 82a14f1929be..ef93ac54508d 100644 --- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_DIAGNOSTICS_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_DIAGNOSTICS_H #include "clang/ASTMatchers/Dynamic/VariantValue.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h index 4045f57d1b36..bd006b6e1290 100644 --- a/include/clang/ASTMatchers/Dynamic/Parser.h +++ b/include/clang/ASTMatchers/Dynamic/Parser.h @@ -31,8 +31,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_PARSER_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_PARSER_H #include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/Registry.h" @@ -63,17 +63,6 @@ public: public: virtual ~Sema(); - /// \brief Lookup a value by name. - /// - /// This can be used in the Sema layer to declare known constants or to - /// allow to split an expression in pieces. - /// - /// \param Name The name of the value to lookup. - /// - /// \return The named value. It could be any type that VariantValue - /// supports. An empty value means that the name is not recognized. - virtual VariantValue getNamedValue(StringRef Name); - /// \brief Process a matcher expression. /// /// All the arguments passed here have already been processed. @@ -105,6 +94,29 @@ public: /// found. virtual llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) = 0; + + /// \brief Compute the list of completion types for \p Context. + /// + /// Each element of \p Context represents a matcher invocation, going from + /// outermost to innermost. Elements are pairs consisting of a reference to + /// the matcher constructor and the index of the next element in the + /// argument list of that matcher (or for the last element, the index of + /// the completion point in the argument list). An empty list requests + /// completion for the root matcher. + virtual std::vector<ArgKind> getAcceptedCompletionTypes( + llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); + + /// \brief Compute the list of completions that match any of + /// \p AcceptedTypes. + /// + /// \param AcceptedTypes All types accepted for this completion. + /// + /// \return All completions for the specified types. + /// Completions should be valid when used in \c lookupMatcherCtor(). + /// The matcher constructed from the return of \c lookupMatcherCtor() + /// should be convertible to some type in \p AcceptedTypes. + virtual std::vector<MatcherCompletion> + getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes); }; /// \brief Sema implementation that uses the matcher registry to process the @@ -121,58 +133,91 @@ public: StringRef BindID, ArrayRef<ParserValue> Args, Diagnostics *Error) override; + + std::vector<ArgKind> getAcceptedCompletionTypes( + llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context) override; + + std::vector<MatcherCompletion> + getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes) override; }; - /// \brief Parse a matcher expression, creating matchers from the registry. - /// - /// This overload creates matchers calling directly into the registry. If the - /// caller needs more control over how the matchers are created, then it can - /// use the overload below that takes a Sema. - /// - /// \param MatcherCode The matcher expression to parse. - /// - /// \return The matcher object constructed, or an empty Optional if an error - /// occurred. - /// In that case, \c Error will contain a description of the error. - /// The caller takes ownership of the DynTypedMatcher object returned. - static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error); + typedef llvm::StringMap<VariantValue> NamedValueMap; /// \brief Parse a matcher expression. /// /// \param MatcherCode The matcher expression to parse. /// /// \param S The Sema instance that will help the parser - /// construct the matchers. + /// construct the matchers. If null, it uses the default registry. + /// + /// \param NamedValues A map of precomputed named values. This provides + /// the dictionary for the <NamedValue> rule of the grammar. + /// If null, it is ignored. + /// /// \return The matcher object constructed by the processor, or an empty /// Optional if an error occurred. In that case, \c Error will contain a /// description of the error. /// The caller takes ownership of the DynTypedMatcher object returned. static llvm::Optional<DynTypedMatcher> - parseMatcherExpression(StringRef MatcherCode, Sema *S, Diagnostics *Error); - - /// \brief Parse an expression, creating matchers from the registry. - /// - /// Parses any expression supported by this parser. In general, the - /// \c parseMatcherExpression function is a better approach to get a matcher - /// object. - static bool parseExpression(StringRef Code, VariantValue *Value, - Diagnostics *Error); + parseMatcherExpression(StringRef MatcherCode, Sema *S, + const NamedValueMap *NamedValues, + Diagnostics *Error); + static llvm::Optional<DynTypedMatcher> + parseMatcherExpression(StringRef MatcherCode, Sema *S, + Diagnostics *Error) { + return parseMatcherExpression(MatcherCode, S, nullptr, Error); + } + static llvm::Optional<DynTypedMatcher> + parseMatcherExpression(StringRef MatcherCode, Diagnostics *Error) { + return parseMatcherExpression(MatcherCode, nullptr, Error); + } /// \brief Parse an expression. /// /// Parses any expression supported by this parser. In general, the /// \c parseMatcherExpression function is a better approach to get a matcher /// object. + /// + /// \param S The Sema instance that will help the parser + /// construct the matchers. If null, it uses the default registry. + /// + /// \param NamedValues A map of precomputed named values. This provides + /// the dictionary for the <NamedValue> rule of the grammar. + /// If null, it is ignored. static bool parseExpression(StringRef Code, Sema *S, + const NamedValueMap *NamedValues, VariantValue *Value, Diagnostics *Error); + static bool parseExpression(StringRef Code, Sema *S, + VariantValue *Value, Diagnostics *Error) { + return parseExpression(Code, S, nullptr, Value, Error); + } + static bool parseExpression(StringRef Code, VariantValue *Value, + Diagnostics *Error) { + return parseExpression(Code, nullptr, Value, Error); + } /// \brief Complete an expression at the given offset. /// + /// \param S The Sema instance that will help the parser + /// construct the matchers. If null, it uses the default registry. + /// + /// \param NamedValues A map of precomputed named values. This provides + /// the dictionary for the <NamedValue> rule of the grammar. + /// If null, it is ignored. + /// /// \return The list of completions, which may be empty if there are no /// available completions or if an error occurred. static std::vector<MatcherCompletion> - completeExpression(StringRef Code, unsigned CompletionOffset); + completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S, + const NamedValueMap *NamedValues); + static std::vector<MatcherCompletion> + completeExpression(StringRef Code, unsigned CompletionOffset, Sema *S) { + return completeExpression(Code, CompletionOffset, S, nullptr); + } + static std::vector<MatcherCompletion> + completeExpression(StringRef Code, unsigned CompletionOffset) { + return completeExpression(Code, CompletionOffset, nullptr); + } private: class CodeTokenizer; @@ -180,6 +225,7 @@ private: struct TokenInfo; Parser(CodeTokenizer *Tokenizer, Sema *S, + const NamedValueMap *NamedValues, Diagnostics *Error); bool parseExpressionImpl(VariantValue *Value); @@ -187,12 +233,16 @@ private: VariantValue *Value); bool parseIdentifierPrefixImpl(VariantValue *Value); - void addCompletion(const TokenInfo &CompToken, StringRef TypedText, - StringRef Decl); + void addCompletion(const TokenInfo &CompToken, + const MatcherCompletion &Completion); void addExpressionCompletions(); + std::vector<MatcherCompletion> + getNamedValueCompletions(ArrayRef<ArgKind> AcceptedTypes); + CodeTokenizer *const Tokenizer; Sema *const S; + const NamedValueMap *const NamedValues; Diagnostics *const Error; typedef std::vector<std::pair<MatcherCtor, unsigned> > ContextStackTy; diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h index faa9254bc2e7..ad24a8d1b794 100644 --- a/include/clang/ASTMatchers/Dynamic/Registry.h +++ b/include/clang/ASTMatchers/Dynamic/Registry.h @@ -14,8 +14,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_REGISTRY_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_REGISTRY_H #include "clang/ASTMatchers/Dynamic/Diagnostics.h" #include "clang/ASTMatchers/Dynamic/VariantValue.h" @@ -36,8 +36,10 @@ typedef const internal::MatcherDescriptor *MatcherCtor; struct MatcherCompletion { MatcherCompletion() {} - MatcherCompletion(StringRef TypedText, StringRef MatcherDecl) - : TypedText(TypedText), MatcherDecl(MatcherDecl) {} + MatcherCompletion(StringRef TypedText, StringRef MatcherDecl, + unsigned Specificity) + : TypedText(TypedText), MatcherDecl(MatcherDecl), + Specificity(Specificity) {} /// \brief The text to type to select this matcher. std::string TypedText; @@ -45,6 +47,13 @@ struct MatcherCompletion { /// \brief The "declaration" of the matcher, with type information. std::string MatcherDecl; + /// \brief Value corresponding to the "specificity" of the converted matcher. + /// + /// Zero specificity indicates that this conversion would produce a trivial + /// matcher that will either always or never match. + /// Such matchers are excluded from code completion results. + unsigned Specificity; + bool operator==(const MatcherCompletion &Other) const { return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl; } @@ -58,28 +67,28 @@ public: /// constructor, or Optional<MatcherCtor>() if not found. static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName); - /// \brief Compute the list of completions for \p Context. + /// \brief Compute the list of completion types for \p Context. /// /// Each element of \p Context represents a matcher invocation, going from - /// outermost to innermost. Elements are pairs consisting of a reference to the - /// matcher constructor and the index of the next element in the argument list - /// of that matcher (or for the last element, the index of the completion - /// point in the argument list). An empty list requests completion for the - /// root matcher. + /// outermost to innermost. Elements are pairs consisting of a reference to + /// the matcher constructor and the index of the next element in the + /// argument list of that matcher (or for the last element, the index of + /// the completion point in the argument list). An empty list requests + /// completion for the root matcher. + static std::vector<ArgKind> getAcceptedCompletionTypes( + llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); + + /// \brief Compute the list of completions that match any of + /// \p AcceptedTypes. /// - /// The completions are ordered first by decreasing relevance, then - /// alphabetically. Relevance is determined by how closely the matcher's - /// type matches that of the context. For example, if the innermost matcher - /// takes a FunctionDecl matcher, the FunctionDecl matchers are returned - /// first, followed by the ValueDecl matchers, then NamedDecl, then Decl, then - /// polymorphic matchers. + /// \param AcceptedTypes All types accepted for this completion. /// - /// Matchers which are technically convertible to the innermost context but - /// which would match either all or no nodes are excluded. For example, - /// namedDecl and varDecl are excluded in a FunctionDecl context, because - /// those matchers would match respectively all or no nodes in such a context. + /// \return All completions for the specified types. + /// Completions should be valid when used in \c lookupMatcherCtor(). + /// The matcher constructed from the return of \c lookupMatcherCtor() + /// should be convertible to some type in \p AcceptedTypes. static std::vector<MatcherCompletion> - getCompletions(ArrayRef<std::pair<MatcherCtor, unsigned> > Context); + getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes); /// \brief Construct a matcher from the registry. /// diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h index b25267b1c54b..a9bd3d50115a 100644 --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -14,8 +14,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H -#define LLVM_CLANG_AST_MATCHERS_DYNAMIC_VARIANT_VALUE_H +#ifndef LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H +#define LLVM_CLANG_ASTMATCHERS_DYNAMIC_VARIANTVALUE_H #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchersInternal.h" @@ -29,6 +29,51 @@ namespace clang { namespace ast_matchers { namespace dynamic { +/// \brief Kind identifier. +/// +/// It supports all types that VariantValue can contain. +class ArgKind { + public: + enum Kind { + AK_Matcher, + AK_Unsigned, + AK_String + }; + /// \brief Constructor for non-matcher types. + ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } + + /// \brief Constructor for matcher types. + ArgKind(ast_type_traits::ASTNodeKind MatcherKind) + : K(AK_Matcher), MatcherKind(MatcherKind) {} + + Kind getArgKind() const { return K; } + ast_type_traits::ASTNodeKind getMatcherKind() const { + assert(K == AK_Matcher); + return MatcherKind; + } + + /// \brief Determines if this type can be converted to \p To. + /// + /// \param To the requested destination type. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. + bool isConvertibleTo(ArgKind To, unsigned *Specificity) const; + + bool operator<(const ArgKind &Other) const { + if (K == AK_Matcher && Other.K == AK_Matcher) + return MatcherKind < Other.MatcherKind; + return K < Other.K; + } + + /// \brief String representation of the type. + std::string asString() const; + +private: + Kind K; + ast_type_traits::ASTNodeKind MatcherKind; +}; + using ast_matchers::internal::DynTypedMatcher; /// \brief A variant matcher object. @@ -48,13 +93,28 @@ class VariantMatcher { /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. class MatcherOps { public: - virtual ~MatcherOps(); - virtual bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const = 0; - virtual void constructFrom(const DynTypedMatcher &Matcher) = 0; - virtual void constructVariadicOperator( - ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> InnerMatchers) = 0; + MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} + + bool canConstructFrom(const DynTypedMatcher &Matcher, + bool &IsExactMatch) const; + + /// \brief Convert \p Matcher the destination type and return it as a new + /// DynTypedMatcher. + virtual DynTypedMatcher + convertMatcher(const DynTypedMatcher &Matcher) const = 0; + + /// \brief Constructs a variadic typed matcher from \p InnerMatchers. + /// Will try to convert each inner matcher to the destination type and + /// return llvm::None if it fails to do so. + llvm::Optional<DynTypedMatcher> + constructVariadicOperator(DynTypedMatcher::VariadicOperator Op, + ArrayRef<VariantMatcher> InnerMatchers) const; + + protected: + ~MatcherOps() {} + + private: + ast_type_traits::ASTNodeKind NodeKind; }; /// \brief Payload interface to be specialized by each matcher type. @@ -65,7 +125,10 @@ class VariantMatcher { virtual ~Payload(); virtual llvm::Optional<DynTypedMatcher> getSingleMatcher() const = 0; virtual std::string getTypeAsString() const = 0; - virtual void makeTypedMatcher(MatcherOps &Ops) const = 0; + virtual llvm::Optional<DynTypedMatcher> + getTypedMatcher(const MatcherOps &Ops) const = 0; + virtual bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, + unsigned *Specificity) const = 0; }; public: @@ -84,9 +147,9 @@ public: /// \brief Creates a 'variadic' operator matcher. /// /// It will bind to the appropriate type on getTypedMatcher<T>(). - static VariantMatcher VariadicOperatorMatcher( - ast_matchers::internal::VariadicOperatorFunction Func, - std::vector<VariantMatcher> Args); + static VariantMatcher + VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, + std::vector<VariantMatcher> Args); /// \brief Makes the matcher the "null" matcher. void reset(); @@ -111,9 +174,21 @@ public: /// that can, the result would be ambiguous and false is returned. template <class T> bool hasTypedMatcher() const { - TypedMatcherOps<T> Ops; - if (Value) Value->makeTypedMatcher(Ops); - return Ops.hasMatcher(); + if (!Value) return false; + return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); + } + + /// \brief Determines if the contained matcher can be converted to \p Kind. + /// + /// \param Kind the requested destination type. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. + bool isConvertibleTo(ast_type_traits::ASTNodeKind Kind, + unsigned *Specificity) const { + if (Value) + return Value->isConvertibleTo(Kind, Specificity); + return false; } /// \brief Return this matcher as a \c Matcher<T>. @@ -122,10 +197,9 @@ public: /// Asserts that \c hasTypedMatcher<T>() is true. template <class T> ast_matchers::internal::Matcher<T> getTypedMatcher() const { - TypedMatcherOps<T> Ops; - Value->makeTypedMatcher(Ops); - assert(Ops.hasMatcher() && "hasTypedMatcher<T>() == false"); - return Ops.matcher(); + assert(hasTypedMatcher<T>() && "hasTypedMatcher<T>() == false"); + return Value->getTypedMatcher(TypedMatcherOps<T>()) + ->template convertTo<T>(); } /// \brief String representation of the type of the value. @@ -137,51 +211,25 @@ public: private: explicit VariantMatcher(Payload *Value) : Value(Value) {} + template <typename T> struct TypedMatcherOps; + class SinglePayload; class PolymorphicPayload; class VariadicOpPayload; - template <typename T> - class TypedMatcherOps : public MatcherOps { - public: - typedef ast_matchers::internal::Matcher<T> MatcherT; - - virtual bool canConstructFrom(const DynTypedMatcher &Matcher, - bool &IsExactMatch) const { - IsExactMatch = Matcher.getSupportedKind().isSame( - ast_type_traits::ASTNodeKind::getFromNodeKind<T>()); - return Matcher.canConvertTo<T>(); - } - - virtual void constructFrom(const DynTypedMatcher& Matcher) { - Out.reset(new MatcherT(Matcher.convertTo<T>())); - } - - virtual void constructVariadicOperator( - ast_matchers::internal::VariadicOperatorFunction Func, - ArrayRef<VariantMatcher> InnerMatchers) { - std::vector<DynTypedMatcher> DynMatchers; - for (size_t i = 0, e = InnerMatchers.size(); i != e; ++i) { - // Abort if any of the inner matchers can't be converted to - // Matcher<T>. - if (!InnerMatchers[i].hasTypedMatcher<T>()) { - return; - } - DynMatchers.push_back(InnerMatchers[i].getTypedMatcher<T>()); - } - Out.reset(new MatcherT( - new ast_matchers::internal::VariadicOperatorMatcherInterface<T>( - Func, DynMatchers))); - } - - bool hasMatcher() const { return Out.get() != nullptr; } - const MatcherT &matcher() const { return *Out; } + IntrusiveRefCntPtr<const Payload> Value; +}; - private: - std::unique_ptr<MatcherT> Out; - }; +template <typename T> +struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { + TypedMatcherOps() + : MatcherOps(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()) {} + typedef ast_matchers::internal::Matcher<T> MatcherT; - IntrusiveRefCntPtr<const Payload> Value; + DynTypedMatcher + convertMatcher(const DynTypedMatcher &Matcher) const override { + return DynTypedMatcher(Matcher.convertTo<T>()); + } }; /// \brief Variant value class. @@ -228,6 +276,24 @@ public: const VariantMatcher &getMatcher() const; void setMatcher(const VariantMatcher &Matcher); + /// \brief Determines if the contained value can be converted to \p Kind. + /// + /// \param Kind the requested destination type. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. + bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; + + /// \brief Determines if the contained value can be converted to any kind + /// in \p Kinds. + /// + /// \param Kinds the requested destination types. + /// + /// \param Specificity value corresponding to the "specificity" of the + /// convertion. It is the maximum specificity of all the possible + /// conversions. + bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; + /// \brief String representation of the type of the value. std::string getTypeAsString() const; diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h index a61d9e47881d..cc14c7bd33db 100644 --- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h +++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_ANALYSIS_CFG_REACHABILITY -#define CLANG_ANALYSIS_CFG_REACHABILITY +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H #include "llvm/ADT/BitVector.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h index 36e07c21907b..a7109233987c 100644 --- a/include/clang/Analysis/Analyses/Consumed.h +++ b/include/clang/Analysis/Analyses/Consumed.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CONSUMED_H -#define LLVM_CLANG_CONSUMED_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h index 6c6d9238e5a9..fcef0fc10ac8 100644 --- a/include/clang/Analysis/Analyses/Dominators.h +++ b/include/clang/Analysis/Analyses/Dominators.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DOMINATORS_H -#define LLVM_CLANG_DOMINATORS_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 76fe9ddca6f8..174cce4f363c 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FORMAT_H -#define LLVM_CLANG_FORMAT_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_FORMATSTRING_H #include "clang/AST/CanonicalType.h" @@ -79,6 +79,7 @@ public: AsLongDouble, // 'L' AsAllocate, // for '%as', GNU extension to C90 scanf AsMAllocate, // for '%ms', GNU extension to scanf + AsWide, // 'w' (MSVCRT, like l but only for c, C, s, S, or Z AsWideChar = AsLong // for '%ls', only makes sense for printf }; @@ -154,6 +155,8 @@ public: // ** Printf-specific ** + ZArg, // MS extension + // Objective-C specific specifiers. ObjCObjArg, // '@' ObjCBeg = ObjCObjArg, ObjCEnd = ObjCObjArg, @@ -644,6 +647,9 @@ public: bool ParsePrintfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, const TargetInfo &Target); + +bool ParseFormatStringHasSArg(const char *beg, const char *end, const LangOptions &LO, + const TargetInfo &Target); bool ParseScanfString(FormatStringHandler &H, const char *beg, const char *end, const LangOptions &LO, diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 784227108ead..c29dd409e56c 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LIVEVARIABLES_H -#define LLVM_CLANG_LIVEVARIABLES_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_LIVEVARIABLES_H #include "clang/AST/Decl.h" #include "clang/Analysis/AnalysisContext.h" diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h index 91bf51cd613f..a1c650427588 100644 --- a/include/clang/Analysis/Analyses/PostOrderCFGView.h +++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_POSTORDER_CFGVIEW -#define LLVM_CLANG_POSTORDER_CFGVIEW +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H #include <vector> //#include <algorithm> @@ -47,17 +47,17 @@ public: /// \brief Set the bit associated with a particular CFGBlock. /// This is the important method for the SetType template parameter. - bool insert(const CFGBlock *Block) { + std::pair<llvm::NoneType, bool> insert(const CFGBlock *Block) { // Note that insert() is called by po_iterator, which doesn't check to // make sure that Block is non-null. Moreover, the CFGBlock iterator will // occasionally hand out null pointers for pruned edges, so we catch those // here. if (!Block) - return false; // if an edge is trivially false. + return std::make_pair(None, false); // if an edge is trivially false. if (VisitedBlockIDs.test(Block->getBlockID())) - return false; + return std::make_pair(None, false); VisitedBlockIDs.set(Block->getBlockID()); - return true; + return std::make_pair(None, true); } /// \brief Check if the bit for a CFGBlock has been already set. diff --git a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h index cb73850b08c7..c4ec2f22eca0 100644 --- a/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h +++ b/include/clang/Analysis/Analyses/PseudoConstantAnalysis.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS -#define LLVM_CLANG_ANALYSIS_PSEUDOCONSTANTANALYSIS +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_PSEUDOCONSTANTANALYSIS_H #include "clang/AST/Stmt.h" diff --git a/include/clang/Analysis/Analyses/ReachableCode.h b/include/clang/Analysis/Analyses/ReachableCode.h index 90a6d014f58d..4c523bfc8b56 100644 --- a/include/clang/Analysis/Analyses/ReachableCode.h +++ b/include/clang/Analysis/Analyses/ReachableCode.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REACHABLECODE_H -#define LLVM_CLANG_REACHABLECODE_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_REACHABLECODE_H #include "clang/Basic/SourceLocation.h" diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index b533c1db492e..458bb576f459 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -16,31 +16,33 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREADSAFETY_H -#define LLVM_CLANG_THREADSAFETY_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H #include "clang/Analysis/AnalysisContext.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/StringRef.h" namespace clang { -namespace thread_safety { +namespace threadSafety { /// This enum distinguishes between different kinds of operations that may /// need to be protected by locks. We use this enum in error handling. enum ProtectedOperationKind { POK_VarDereference, ///< Dereferencing a variable (e.g. p in *p = 5;) POK_VarAccess, ///< Reading or writing a variable (e.g. x in x = 5;) - POK_FunctionCall ///< Making a function call (e.g. fool()) + POK_FunctionCall, ///< Making a function call (e.g. fool()) + POK_PassByRef, ///< Passing a guarded variable by reference. + POK_PtPassByRef, ///< Passing a pt-guarded variable by reference. }; /// This enum distinguishes between different kinds of lock actions. For /// example, it is an error to write a variable protected by shared version of a /// mutex. enum LockKind { - LK_Shared, ///< Shared/reader lock of a mutex. + LK_Shared, ///< Shared/reader lock of a mutex. LK_Exclusive, ///< Exclusive/writer lock of a mutex. - LK_Generic ///< Can be either Shared or Exclusive + LK_Generic ///< Can be either Shared or Exclusive }; /// This enum distinguishes between different ways to access (read or write) a @@ -161,6 +163,16 @@ public: LockKind LK, SourceLocation Loc, Name *PossibleMatch = nullptr) {} + /// Warn when acquiring a lock that the negative capability is not held. + /// \param Kind -- the capability's name parameter (role, mutex, etc). + /// \param LockName -- The name for the lock expression, to be printed in the + /// diagnostic. + /// \param Neg -- The name of the negative capability to be printed in the + /// diagnostic. + /// \param Loc -- The location of the protected operation. + virtual void handleNegativeNotHeld(StringRef Kind, Name LockName, Name Neg, + SourceLocation Loc) {} + /// Warn when a function is called while an excluded mutex is locked. For /// example, the mutex may be locked inside the function. /// \param Kind -- the capability's name parameter (role, mutex, etc). @@ -171,6 +183,13 @@ public: virtual void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, SourceLocation Loc) {} + /// Called by the analysis when starting analysis of a function. + /// Used to issue suggestions for changes to annotations. + virtual void enterFunction(const FunctionDecl *FD) {} + + /// Called by the analysis when finishing analysis of a function. + virtual void leaveFunction(const FunctionDecl *FD) {} + bool issueBetaWarnings() { return IssueBetaWarnings; } void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; } @@ -190,5 +209,5 @@ void runThreadSafetyAnalysis(AnalysisDeclContext &AC, /// of access. LockKind getLockKindFromAccessKind(AccessKind AK); -}} // end namespace clang::thread_safety +}} // end namespace clang::threadSafety #endif diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 09c614ca3e36..be81121c102b 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -19,21 +19,63 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREAD_SAFETY_COMMON_H -#define LLVM_CLANG_THREAD_SAFETY_COMMON_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" +#include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" #include "clang/Analysis/AnalysisContext.h" #include "clang/Basic/OperatorKinds.h" - #include <memory> +#include <ostream> +#include <sstream> #include <vector> namespace clang { namespace threadSafety { + +// Various helper functions on til::SExpr +namespace sx { + +inline bool equals(const til::SExpr *E1, const til::SExpr *E2) { + return til::EqualsComparator::compareExprs(E1, E2); +} + +inline bool matches(const til::SExpr *E1, const til::SExpr *E2) { + // We treat a top-level wildcard as the "univsersal" lock. + // It matches everything for the purpose of checking locks, but not + // for unlocking them. + if (isa<til::Wildcard>(E1)) + return isa<til::Wildcard>(E2); + if (isa<til::Wildcard>(E2)) + return isa<til::Wildcard>(E1); + + return til::MatchComparator::compareExprs(E1, E2); +} + +inline bool partiallyMatches(const til::SExpr *E1, const til::SExpr *E2) { + const auto *PE1 = dyn_cast_or_null<til::Project>(E1); + if (!PE1) + return false; + const auto *PE2 = dyn_cast_or_null<til::Project>(E2); + if (!PE2) + return false; + return PE1->clangDecl() == PE2->clangDecl(); +} + +inline std::string toString(const til::SExpr *E) { + std::stringstream ss; + til::StdPrinter::print(E, ss); + return ss.str(); +} + +} // end namespace sx + + + // This class defines the interface of a clang CFG Visitor. // CFGWalker will invoke the following methods. // Note that methods are not virtual; the visitor is templatized. @@ -206,6 +248,59 @@ private: }; + + +class CapabilityExpr { + // TODO: move this back into ThreadSafety.cpp + // This is specific to thread safety. It is here because + // translateAttrExpr needs it, but that should be moved too. + +private: + const til::SExpr* CapExpr; ///< The capability expression. + bool Negated; ///< True if this is a negative capability + +public: + CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {} + + const til::SExpr* sexpr() const { return CapExpr; } + bool negative() const { return Negated; } + + CapabilityExpr operator!() const { + return CapabilityExpr(CapExpr, !Negated); + } + + bool equals(const CapabilityExpr &other) const { + return (Negated == other.Negated) && sx::equals(CapExpr, other.CapExpr); + } + + bool matches(const CapabilityExpr &other) const { + return (Negated == other.Negated) && sx::matches(CapExpr, other.CapExpr); + } + + bool matchesUniv(const CapabilityExpr &CapE) const { + return isUniversal() || matches(CapE); + } + + bool partiallyMatches(const CapabilityExpr &other) const { + return (Negated == other.Negated) && + sx::partiallyMatches(CapExpr, other.CapExpr); + } + + std::string toString() const { + if (Negated) + return "!" + sx::toString(CapExpr); + return sx::toString(CapExpr); + } + + bool shouldIgnore() const { return CapExpr == nullptr; } + + bool isInvalid() const { return sexpr() && isa<til::Undefined>(sexpr()); } + + bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); } +}; + + + // Translate clang::Expr to til::SExpr. class SExprBuilder { public: @@ -219,18 +314,16 @@ public: /// should be evaluated; multiple calling contexts can be chained together /// by the lock_returned attribute. struct CallingContext { + CallingContext *Prev; // The previous context; or 0 if none. const NamedDecl *AttrDecl; // The decl to which the attr is attached. const Expr *SelfArg; // Implicit object argument -- e.g. 'this' unsigned NumArgs; // Number of funArgs const Expr *const *FunArgs; // Function arguments - CallingContext *Prev; // The previous context; or 0 if none. bool SelfArrow; // is Self referred to with -> or .? - CallingContext(const NamedDecl *D = nullptr, const Expr *S = nullptr, - unsigned N = 0, const Expr *const *A = nullptr, - CallingContext *P = nullptr) - : AttrDecl(D), SelfArg(S), NumArgs(N), FunArgs(A), Prev(P), - SelfArrow(false) + CallingContext(CallingContext *P, const NamedDecl *D = nullptr) + : Prev(P), AttrDecl(D), SelfArg(nullptr), + NumArgs(0), FunArgs(nullptr), SelfArrow(false) {} }; @@ -242,6 +335,13 @@ public: SelfVar->setKind(til::Variable::VK_SFun); } + // Translate a clang expression in an attribute to a til::SExpr. + // Constructs the context from D, DeclExp, and SelfDecl. + CapabilityExpr translateAttrExpr(const Expr *AttrExp, const NamedDecl *D, + const Expr *DeclExp, VarDecl *SelfD=nullptr); + + CapabilityExpr translateAttrExpr(const Expr *AttrExp, CallingContext *Ctx); + // Translate a clang statement or expression to a TIL expression. // Also performs substitution of variables; Ctx provides the context. // Dispatches on the type of S. @@ -262,7 +362,8 @@ private: CallingContext *Ctx) ; til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx); til::SExpr *translateMemberExpr(const MemberExpr *ME, CallingContext *Ctx); - til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx); + til::SExpr *translateCallExpr(const CallExpr *CE, CallingContext *Ctx, + const Expr *SelfE = nullptr); til::SExpr *translateCXXMemberCallExpr(const CXXMemberCallExpr *ME, CallingContext *Ctx); til::SExpr *translateCXXOperatorCallExpr(const CXXOperatorCallExpr *OCE, @@ -280,10 +381,8 @@ private: til::SExpr *translateCastExpr(const CastExpr *CE, CallingContext *Ctx); til::SExpr *translateArraySubscriptExpr(const ArraySubscriptExpr *E, CallingContext *Ctx); - til::SExpr *translateConditionalOperator(const ConditionalOperator *C, - CallingContext *Ctx); - til::SExpr *translateBinaryConditionalOperator( - const BinaryConditionalOperator *C, CallingContext *Ctx); + til::SExpr *translateAbstractConditionalOperator( + const AbstractConditionalOperator *C, CallingContext *Ctx); til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx); @@ -362,21 +461,24 @@ private: void mergePhiNodesBackEdge(const CFGBlock *Blk); private: + // Set to true when parsing capability expressions, which get translated + // inaccurately in order to hack around smart pointers etc. + static const bool CapabilityExprMode = true; + til::MemRegionRef Arena; til::Variable *SelfVar; // Variable to use for 'this'. May be null. - til::SCFG *Scfg; + til::SCFG *Scfg; StatementMap SMap; // Map from Stmt to TIL Variables LVarIndexMap LVarIdxMap; // Indices of clang local vars. std::vector<til::BasicBlock *> BlockMap; // Map from clang to til BBs. std::vector<BlockInfo> BBInfo; // Extra information per BB. // Indexed by clang BlockID. - std::unique_ptr<SExprBuilder::CallingContext> CallCtx; // Root calling context LVarDefinitionMap CurrentLVarMap; - std::vector<til::Variable*> CurrentArguments; - std::vector<til::Variable*> CurrentInstructions; - std::vector<til::Variable*> IncompleteArgs; + std::vector<til::Phi*> CurrentArguments; + std::vector<til::SExpr*> CurrentInstructions; + std::vector<til::Phi*> IncompleteArgs; til::BasicBlock *CurrentBB; BlockInfo *CurrentBlockInfo; }; diff --git a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h index c4f4b21aab12..bc78021343a4 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h @@ -10,8 +10,8 @@ // that are used as part of fact-checking capability expressions. //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREAD_SAFETY_LOGICAL_H -#define LLVM_CLANG_THREAD_SAFETY_LOGICAL_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYLOGICAL_H #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" @@ -41,13 +41,13 @@ private: }; class Terminal : public LExpr { - til::SExprRef Expr; + til::SExpr *Expr; public: Terminal(til::SExpr *Expr) : LExpr(LExpr::Terminal), Expr(Expr) {} - const til::SExpr *expr() const { return Expr.get(); } - til::SExpr *expr() { return Expr.get(); } + const til::SExpr *expr() const { return Expr; } + til::SExpr *expr() { return Expr; } static bool classof(const LExpr *E) { return E->kind() == LExpr::Terminal; } }; @@ -104,5 +104,5 @@ bool LExpr::implies(const LExpr *RHS) const { } } -#endif // LLVM_CLANG_THREAD_SAFETY_LOGICAL_H +#endif diff --git a/include/clang/Analysis/Analyses/ThreadSafetyOps.def b/include/clang/Analysis/Analyses/ThreadSafetyOps.def index 6ebc95dbe9a7..0d2458b0c893 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyOps.def +++ b/include/clang/Analysis/Analyses/ThreadSafetyOps.def @@ -44,8 +44,11 @@ TIL_OPCODE_DEF(Cast) TIL_OPCODE_DEF(SCFG) TIL_OPCODE_DEF(BasicBlock) TIL_OPCODE_DEF(Phi) + +// Terminator instructions TIL_OPCODE_DEF(Goto) TIL_OPCODE_DEF(Branch) +TIL_OPCODE_DEF(Return) // pseudo-terms TIL_OPCODE_DEF(Identifier) diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index 8e4299ea70e8..2cd8c6d6d2d6 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -44,17 +44,16 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREAD_SAFETY_TIL_H -#define LLVM_CLANG_THREAD_SAFETY_TIL_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H // All clang include dependencies for this file must be put in // ThreadSafetyUtil.h. #include "ThreadSafetyUtil.h" - -#include <stdint.h> #include <algorithm> #include <cassert> #include <cstddef> +#include <stdint.h> #include <utility> @@ -63,24 +62,27 @@ namespace threadSafety { namespace til { +/// Enum for the different distinct classes of SExpr enum TIL_Opcode { #define TIL_OPCODE_DEF(X) COP_##X, #include "ThreadSafetyOps.def" #undef TIL_OPCODE_DEF }; +/// Opcode for unary arithmetic operations. enum TIL_UnaryOpcode : unsigned char { UOP_Minus, // - UOP_BitNot, // ~ UOP_LogicNot // ! }; +/// Opcode for binary arithmetic operations. enum TIL_BinaryOpcode : unsigned char { + BOP_Add, // + + BOP_Sub, // - BOP_Mul, // * BOP_Div, // / BOP_Rem, // % - BOP_Add, // + - BOP_Sub, // - BOP_Shl, // << BOP_Shr, // >> BOP_BitAnd, // & @@ -90,37 +92,42 @@ enum TIL_BinaryOpcode : unsigned char { BOP_Neq, // != BOP_Lt, // < BOP_Leq, // <= - BOP_LogicAnd, // && - BOP_LogicOr // || + BOP_LogicAnd, // && (no short-circuit) + BOP_LogicOr // || (no short-circuit) }; +/// Opcode for cast operations. enum TIL_CastOpcode : unsigned char { CAST_none = 0, CAST_extendNum, // extend precision of numeric type CAST_truncNum, // truncate precision of numeric type CAST_toFloat, // convert to floating point type CAST_toInt, // convert to integer type + CAST_objToPtr // convert smart pointer to pointer (C++ only) }; const TIL_Opcode COP_Min = COP_Future; const TIL_Opcode COP_Max = COP_Branch; const TIL_UnaryOpcode UOP_Min = UOP_Minus; const TIL_UnaryOpcode UOP_Max = UOP_LogicNot; -const TIL_BinaryOpcode BOP_Min = BOP_Mul; +const TIL_BinaryOpcode BOP_Min = BOP_Add; const TIL_BinaryOpcode BOP_Max = BOP_LogicOr; const TIL_CastOpcode CAST_Min = CAST_none; const TIL_CastOpcode CAST_Max = CAST_toInt; +/// Return the name of a unary opcode. StringRef getUnaryOpcodeString(TIL_UnaryOpcode Op); + +/// Return the name of a binary opcode. StringRef getBinaryOpcodeString(TIL_BinaryOpcode Op); -// ValueTypes are data types that can actually be held in registers. -// All variables and expressions must have a vBNF_Nonealue type. -// Pointer types are further subdivided into the various heap-allocated -// types, such as functions, records, etc. -// Structured types that are passed by value (e.g. complex numbers) -// require special handling; they use BT_ValueRef, and size ST_0. +/// ValueTypes are data types that can actually be held in registers. +/// All variables and expressions must have a value type. +/// Pointer types are further subdivided into the various heap-allocated +/// types, such as functions, records, etc. +/// Structured types that are passed by value (e.g. complex numbers) +/// require special handling; they use BT_ValueRef, and size ST_0. struct ValueType { enum BaseType : unsigned char { BT_Void = 0, @@ -246,8 +253,10 @@ inline ValueType ValueType::getValueType<void*>() { } +class BasicBlock; + -// Base class for AST nodes in the typed intermediate language. +/// Base class for AST nodes in the typed intermediate language. class SExpr { public: TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); } @@ -266,71 +275,47 @@ public: // template <class C> typename C::CType compare(CType* E, C& Cmp) { // compare all subexpressions, following the comparator interface // } - void *operator new(size_t S, MemRegionRef &R) { return ::operator new(S, R); } - // SExpr objects cannot be deleted. + /// SExpr objects cannot be deleted. // This declaration is public to workaround a gcc bug that breaks building // with REQUIRES_EH=1. void operator delete(void *) LLVM_DELETED_FUNCTION; + /// Returns the instruction ID for this expression. + /// All basic block instructions have a unique ID (i.e. virtual register). + unsigned id() const { return SExprID; } + + /// Returns the block, if this is an instruction in a basic block, + /// otherwise returns null. + BasicBlock* block() const { return Block; } + + /// Set the basic block and instruction ID for this expression. + void setID(BasicBlock *B, unsigned id) { Block = B; SExprID = id; } + protected: - SExpr(TIL_Opcode Op) : Opcode(Op), Reserved(0), Flags(0) {} - SExpr(const SExpr &E) : Opcode(E.Opcode), Reserved(0), Flags(E.Flags) {} + SExpr(TIL_Opcode Op) + : Opcode(Op), Reserved(0), Flags(0), SExprID(0), Block(nullptr) {} + SExpr(const SExpr &E) + : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0), + Block(nullptr) {} const unsigned char Opcode; unsigned char Reserved; unsigned short Flags; + unsigned SExprID; + BasicBlock* Block; private: SExpr() LLVM_DELETED_FUNCTION; - // SExpr objects must be created in an arena. + /// SExpr objects must be created in an arena. void *operator new(size_t) LLVM_DELETED_FUNCTION; }; -// Class for owning references to SExprs. -// Includes attach/detach logic for counting variable references and lazy -// rewriting strategies. -class SExprRef { -public: - SExprRef() : Ptr(nullptr) { } - SExprRef(std::nullptr_t P) : Ptr(nullptr) { } - SExprRef(SExprRef &&R) : Ptr(R.Ptr) { R.Ptr = nullptr; } - - // Defined after Variable and Future, below. - inline SExprRef(SExpr *P); - inline ~SExprRef(); - - SExpr *get() { return Ptr; } - const SExpr *get() const { return Ptr; } - - SExpr *operator->() { return get(); } - const SExpr *operator->() const { return get(); } - - SExpr &operator*() { return *Ptr; } - const SExpr &operator*() const { return *Ptr; } - - bool operator==(const SExprRef &R) const { return Ptr == R.Ptr; } - bool operator!=(const SExprRef &R) const { return !operator==(R); } - bool operator==(const SExpr *P) const { return Ptr == P; } - bool operator!=(const SExpr *P) const { return !operator==(P); } - bool operator==(std::nullptr_t) const { return Ptr == nullptr; } - bool operator!=(std::nullptr_t) const { return Ptr != nullptr; } - - inline void reset(SExpr *E); - -private: - inline void attach(); - inline void detach(); - - SExpr *Ptr; -}; - - // Contains various helper functions for SExprs. namespace ThreadSafetyTIL { inline bool isTrivial(const SExpr *E) { @@ -342,62 +327,64 @@ namespace ThreadSafetyTIL { // Nodes which declare variables class Function; class SFunction; -class BasicBlock; class Let; -// A named variable, e.g. "x". -// -// There are two distinct places in which a Variable can appear in the AST. -// A variable declaration introduces a new variable, and can occur in 3 places: -// Let-expressions: (Let (x = t) u) -// Functions: (Function (x : t) u) -// Self-applicable functions (SFunction (x) t) -// -// If a variable occurs in any other location, it is a reference to an existing -// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't -// allocate a separate AST node for variable references; a reference is just a -// pointer to the original declaration. +/// A named variable, e.g. "x". +/// +/// There are two distinct places in which a Variable can appear in the AST. +/// A variable declaration introduces a new variable, and can occur in 3 places: +/// Let-expressions: (Let (x = t) u) +/// Functions: (Function (x : t) u) +/// Self-applicable functions (SFunction (x) t) +/// +/// If a variable occurs in any other location, it is a reference to an existing +/// variable declaration -- e.g. 'x' in (x * y + z). To save space, we don't +/// allocate a separate AST node for variable references; a reference is just a +/// pointer to the original declaration. class Variable : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; } - // Let-variable, function parameter, or self-variable enum VariableKind { - VK_Let, - VK_LetBB, - VK_Fun, - VK_SFun + VK_Let, ///< Let-variable + VK_Fun, ///< Function parameter + VK_SFun ///< SFunction (self) parameter }; - // These are defined after SExprRef contructor, below - inline Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr); - inline Variable(StringRef s, SExpr *D = nullptr); - inline Variable(const Variable &Vd, SExpr *D); + Variable(StringRef s, SExpr *D = nullptr) + : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) { + Flags = VK_Let; + } + Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr) + : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"), + Definition(D), Cvdecl(Cvd) { + Flags = VK_Let; + } + Variable(const Variable &Vd, SExpr *D) // rewrite constructor + : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl) { + Flags = Vd.kind(); + } + /// Return the kind of variable (let, function param, or self) VariableKind kind() const { return static_cast<VariableKind>(Flags); } - const StringRef name() const { return Name; } - const clang::ValueDecl *clangDecl() const { return Cvdecl; } - - // Returns the definition (for let vars) or type (for parameter & self vars) - SExpr *definition() { return Definition.get(); } - const SExpr *definition() const { return Definition.get(); } + /// Return the name of the variable, if any. + StringRef name() const { return Name; } - void attachVar() const { ++NumUses; } - void detachVar() const { assert(NumUses > 0); --NumUses; } + /// Return the clang declaration for this variable, if any. + const clang::ValueDecl *clangDecl() const { return Cvdecl; } - unsigned getID() const { return Id; } - unsigned getBlockID() const { return BlockID; } + /// Return the definition of the variable. + /// For let-vars, this is the setting expression. + /// For function and self parameters, it is the type of the variable. + SExpr *definition() { return Definition; } + const SExpr *definition() const { return Definition; } - void setName(StringRef S) { Name = S; } - void setID(unsigned Bid, unsigned I) { - BlockID = static_cast<unsigned short>(Bid); - Id = static_cast<unsigned short>(I); - } - void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; } - void setDefinition(SExpr *E); + void setName(StringRef S) { Name = S; } void setKind(VariableKind K) { Flags = K; } + void setDefinition(SExpr *E) { Definition = E; } + void setClangDecl(const clang::ValueDecl *VD) { Cvdecl = VD; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -405,7 +392,8 @@ public: return Vs.reduceVariableRef(this); } - template <class C> typename C::CType compare(Variable* E, C& Cmp) { + template <class C> + typename C::CType compare(const Variable* E, C& Cmp) const { return Cmp.compareVariableRefs(this, E); } @@ -416,17 +404,13 @@ private: friend class Let; StringRef Name; // The name of the variable. - SExprRef Definition; // The TIL type or definition + SExpr* Definition; // The TIL type or definition const clang::ValueDecl *Cvdecl; // The clang declaration for this variable. - - unsigned short BlockID; - unsigned short Id; - mutable unsigned NumUses; }; -// Placeholder for an expression that has not yet been created. -// Used to implement lazy copy and rewriting strategies. +/// Placeholder for an expression that has not yet been created. +/// Used to implement lazy copy and rewriting strategies. class Future : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Future; } @@ -437,25 +421,17 @@ public: FS_done }; - Future() : - SExpr(COP_Future), Status(FS_pending), Result(nullptr), Location(nullptr) - {} + Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {} + private: virtual ~Future() LLVM_DELETED_FUNCTION; -public: - - // Registers the location in the AST where this future is stored. - // Forcing the future will automatically update the AST. - static inline void registerLocation(SExprRef *Member) { - if (Future *F = dyn_cast_or_null<Future>(Member->get())) - F->Location = Member; - } +public: // A lazy rewriting strategy should subclass Future and override this method. - virtual SExpr *create() { return nullptr; } + virtual SExpr *compute() { return nullptr; } // Return the result of this future if it exists, otherwise return null. - SExpr *maybeGetResult() { + SExpr *maybeGetResult() const { return Result; } @@ -463,8 +439,7 @@ public: SExpr *result() { switch (Status) { case FS_pending: - force(); - return Result; + return force(); case FS_evaluating: return nullptr; // infinite loop; illegal recursion. case FS_done: @@ -478,88 +453,22 @@ public: return Vs.traverse(Result, Ctx); } - template <class C> typename C::CType compare(Future* E, C& Cmp) { + template <class C> + typename C::CType compare(const Future* E, C& Cmp) const { if (!Result || !E->Result) return Cmp.comparePointers(this, E); return Cmp.compare(Result, E->Result); } private: - // Force the future. - inline void force(); + SExpr* force(); FutureStatus Status; SExpr *Result; - SExprRef *Location; }; -inline void SExprRef::attach() { - if (!Ptr) - return; - - TIL_Opcode Op = Ptr->opcode(); - if (Op == COP_Variable) { - cast<Variable>(Ptr)->attachVar(); - } else if (Op == COP_Future) { - cast<Future>(Ptr)->registerLocation(this); - } -} - -inline void SExprRef::detach() { - if (Ptr && Ptr->opcode() == COP_Variable) { - cast<Variable>(Ptr)->detachVar(); - } -} - -inline SExprRef::SExprRef(SExpr *P) : Ptr(P) { - attach(); -} - -inline SExprRef::~SExprRef() { - detach(); -} - -inline void SExprRef::reset(SExpr *P) { - detach(); - Ptr = P; - attach(); -} - - -inline Variable::Variable(StringRef s, SExpr *D) - : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr), - BlockID(0), Id(0), NumUses(0) { - Flags = VK_Let; -} - -inline Variable::Variable(SExpr *D, const clang::ValueDecl *Cvd) - : SExpr(COP_Variable), Name(Cvd ? Cvd->getName() : "_x"), - Definition(D), Cvdecl(Cvd), BlockID(0), Id(0), NumUses(0) { - Flags = VK_Let; -} - -inline Variable::Variable(const Variable &Vd, SExpr *D) // rewrite constructor - : SExpr(Vd), Name(Vd.Name), Definition(D), Cvdecl(Vd.Cvdecl), - BlockID(0), Id(0), NumUses(0) { - Flags = Vd.kind(); -} - -inline void Variable::setDefinition(SExpr *E) { - Definition.reset(E); -} - -void Future::force() { - Status = FS_evaluating; - SExpr *R = create(); - Result = R; - if (Location) - Location->reset(R); - Status = FS_done; -} - - -// Placeholder for C++ expressions that cannot be represented in the TIL. +/// Placeholder for expressions that cannot be represented in the TIL. class Undefined : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; } @@ -572,8 +481,9 @@ public: return Vs.reduceUndefined(*this); } - template <class C> typename C::CType compare(Undefined* E, C& Cmp) { - return Cmp.comparePointers(Cstmt, E->Cstmt); + template <class C> + typename C::CType compare(const Undefined* E, C& Cmp) const { + return Cmp.trueResult(); } private: @@ -581,7 +491,7 @@ private: }; -// Placeholder for a wildcard that matches any other expression. +/// Placeholder for a wildcard that matches any other expression. class Wildcard : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; } @@ -593,7 +503,8 @@ public: return Vs.reduceWildcard(*this); } - template <class C> typename C::CType compare(Wildcard* E, C& Cmp) { + template <class C> + typename C::CType compare(const Wildcard* E, C& Cmp) const { return Cmp.trueResult(); } }; @@ -626,9 +537,10 @@ public: template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx); - template <class C> typename C::CType compare(Literal* E, C& Cmp) { - // TODO -- use value, not pointer equality - return Cmp.comparePointers(Cexpr, E->Cexpr); + template <class C> + typename C::CType compare(const Literal* E, C& Cmp) const { + // TODO: defer actual comparison to LiteralT + return Cmp.trueResult(); } private: @@ -710,8 +622,8 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) { } -// Literal pointer to an object allocated in memory. -// At compile time, pointer literals are represented by symbolic names. +/// A Literal pointer to an object allocated in memory. +/// At compile time, pointer literals are represented by symbolic names. class LiteralPtr : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; } @@ -727,7 +639,8 @@ public: return Vs.reduceLiteralPtr(*this); } - template <class C> typename C::CType compare(LiteralPtr* E, C& Cmp) { + template <class C> + typename C::CType compare(const LiteralPtr* E, C& Cmp) const { return Cmp.comparePointers(Cvdecl, E->Cvdecl); } @@ -736,9 +649,9 @@ private: }; -// A function -- a.k.a. lambda abstraction. -// Functions with multiple arguments are created by currying, -// e.g. (function (x: Int) (function (y: Int) (add x y))) +/// A function -- a.k.a. lambda abstraction. +/// Functions with multiple arguments are created by currying, +/// e.g. (Function (x: Int) (Function (y: Int) (Code { return x + y }))) class Function : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Function; } @@ -755,8 +668,8 @@ public: Variable *variableDecl() { return VarDecl; } const Variable *variableDecl() const { return VarDecl; } - SExpr *body() { return Body.get(); } - const SExpr *body() const { return Body.get(); } + SExpr *body() { return Body; } + const SExpr *body() const { return Body; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -769,7 +682,8 @@ public: return Vs.reduceFunction(*this, Nvd, E1); } - template <class C> typename C::CType compare(Function* E, C& Cmp) { + template <class C> + typename C::CType compare(const Function* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(VarDecl->definition(), E->VarDecl->definition()); if (Cmp.notTrue(Ct)) @@ -782,13 +696,13 @@ public: private: Variable *VarDecl; - SExprRef Body; + SExpr* Body; }; -// A self-applicable function. -// A self-applicable function can be applied to itself. It's useful for -// implementing objects and late binding +/// A self-applicable function. +/// A self-applicable function can be applied to itself. It's useful for +/// implementing objects and late binding. class SFunction : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; } @@ -797,20 +711,20 @@ public: : SExpr(COP_SFunction), VarDecl(Vd), Body(B) { assert(Vd->Definition == nullptr); Vd->setKind(Variable::VK_SFun); - Vd->Definition.reset(this); + Vd->Definition = this; } SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor : SExpr(F), VarDecl(Vd), Body(B) { assert(Vd->Definition == nullptr); Vd->setKind(Variable::VK_SFun); - Vd->Definition.reset(this); + Vd->Definition = this; } Variable *variableDecl() { return VarDecl; } const Variable *variableDecl() const { return VarDecl; } - SExpr *body() { return Body.get(); } - const SExpr *body() const { return Body.get(); } + SExpr *body() { return Body; } + const SExpr *body() const { return Body; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -824,7 +738,8 @@ public: return Vs.reduceSFunction(*this, Nvd, E1); } - template <class C> typename C::CType compare(SFunction* E, C& Cmp) { + template <class C> + typename C::CType compare(const SFunction* E, C& Cmp) const { Cmp.enterScope(variableDecl(), E->variableDecl()); typename C::CType Ct = Cmp.compare(body(), E->body()); Cmp.leaveScope(); @@ -833,11 +748,11 @@ public: private: Variable *VarDecl; - SExprRef Body; + SExpr* Body; }; -// A block of code -- e.g. the body of a function. +/// A block of code -- e.g. the body of a function. class Code : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Code; } @@ -846,11 +761,11 @@ public: Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor : SExpr(C), ReturnType(T), Body(B) {} - SExpr *returnType() { return ReturnType.get(); } - const SExpr *returnType() const { return ReturnType.get(); } + SExpr *returnType() { return ReturnType; } + const SExpr *returnType() const { return ReturnType; } - SExpr *body() { return Body.get(); } - const SExpr *body() const { return Body.get(); } + SExpr *body() { return Body; } + const SExpr *body() const { return Body; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -859,7 +774,8 @@ public: return Vs.reduceCode(*this, Nt, Nb); } - template <class C> typename C::CType compare(Code* E, C& Cmp) { + template <class C> + typename C::CType compare(const Code* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(returnType(), E->returnType()); if (Cmp.notTrue(Ct)) return Ct; @@ -867,12 +783,12 @@ public: } private: - SExprRef ReturnType; - SExprRef Body; + SExpr* ReturnType; + SExpr* Body; }; -// A typed, writable location in memory +/// A typed, writable location in memory class Field : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Field; } @@ -881,11 +797,11 @@ public: Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor : SExpr(C), Range(R), Body(B) {} - SExpr *range() { return Range.get(); } - const SExpr *range() const { return Range.get(); } + SExpr *range() { return Range; } + const SExpr *range() const { return Range; } - SExpr *body() { return Body.get(); } - const SExpr *body() const { return Body.get(); } + SExpr *body() { return Body; } + const SExpr *body() const { return Body; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -894,7 +810,8 @@ public: return Vs.reduceField(*this, Nr, Nb); } - template <class C> typename C::CType compare(Field* E, C& Cmp) { + template <class C> + typename C::CType compare(const Field* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(range(), E->range()); if (Cmp.notTrue(Ct)) return Ct; @@ -902,12 +819,16 @@ public: } private: - SExprRef Range; - SExprRef Body; + SExpr* Range; + SExpr* Body; }; -// Apply an argument to a function +/// Apply an argument to a function. +/// Note that this does not actually call the function. Functions are curried, +/// so this returns a closure in which the first parameter has been applied. +/// Once all parameters have been applied, Call can be used to invoke the +/// function. class Apply : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; } @@ -917,11 +838,11 @@ public: : SExpr(A), Fun(F), Arg(Ar) {} - SExpr *fun() { return Fun.get(); } - const SExpr *fun() const { return Fun.get(); } + SExpr *fun() { return Fun; } + const SExpr *fun() const { return Fun; } - SExpr *arg() { return Arg.get(); } - const SExpr *arg() const { return Arg.get(); } + SExpr *arg() { return Arg; } + const SExpr *arg() const { return Arg; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -930,7 +851,8 @@ public: return Vs.reduceApply(*this, Nf, Na); } - template <class C> typename C::CType compare(Apply* E, C& Cmp) { + template <class C> + typename C::CType compare(const Apply* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(fun(), E->fun()); if (Cmp.notTrue(Ct)) return Ct; @@ -938,12 +860,12 @@ public: } private: - SExprRef Fun; - SExprRef Arg; + SExpr* Fun; + SExpr* Arg; }; -// Apply a self-argument to a self-applicable function +/// Apply a self-argument to a self-applicable function. class SApply : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; } @@ -952,23 +874,24 @@ public: SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor : SExpr(A), Sfun(Sf), Arg(Ar) {} - SExpr *sfun() { return Sfun.get(); } - const SExpr *sfun() const { return Sfun.get(); } + SExpr *sfun() { return Sfun; } + const SExpr *sfun() const { return Sfun; } - SExpr *arg() { return Arg.get() ? Arg.get() : Sfun.get(); } - const SExpr *arg() const { return Arg.get() ? Arg.get() : Sfun.get(); } + SExpr *arg() { return Arg ? Arg : Sfun; } + const SExpr *arg() const { return Arg ? Arg : Sfun; } - bool isDelegation() const { return Arg == nullptr; } + bool isDelegation() const { return Arg != nullptr; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { auto Nf = Vs.traverse(Sfun, Vs.subExprCtx(Ctx)); - typename V::R_SExpr Na = Arg.get() ? Vs.traverse(Arg, Vs.subExprCtx(Ctx)) + typename V::R_SExpr Na = Arg ? Vs.traverse(Arg, Vs.subExprCtx(Ctx)) : nullptr; return Vs.reduceSApply(*this, Nf, Na); } - template <class C> typename C::CType compare(SApply* E, C& Cmp) { + template <class C> + typename C::CType compare(const SApply* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(sfun(), E->sfun()); if (Cmp.notTrue(Ct) || (!arg() && !E->arg())) return Ct; @@ -976,12 +899,12 @@ public: } private: - SExprRef Sfun; - SExprRef Arg; + SExpr* Sfun; + SExpr* Arg; }; -// Project a named slot from a C++ struct or class. +/// Project a named slot from a C++ struct or class. class Project : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } @@ -989,17 +912,23 @@ public: Project(SExpr *R, StringRef SName) : SExpr(COP_Project), Rec(R), SlotName(SName), Cvdecl(nullptr) { } - Project(SExpr *R, clang::ValueDecl *Cvd) + Project(SExpr *R, const clang::ValueDecl *Cvd) : SExpr(COP_Project), Rec(R), SlotName(Cvd->getName()), Cvdecl(Cvd) { } Project(const Project &P, SExpr *R) : SExpr(P), Rec(R), SlotName(P.SlotName), Cvdecl(P.Cvdecl) { } - SExpr *record() { return Rec.get(); } - const SExpr *record() const { return Rec.get(); } + SExpr *record() { return Rec; } + const SExpr *record() const { return Rec; } + + const clang::ValueDecl *clangDecl() const { return Cvdecl; } - const clang::ValueDecl *clangValueDecl() const { return Cvdecl; } + bool isArrow() const { return (Flags & 0x01) != 0; } + void setArrow(bool b) { + if (b) Flags |= 0x01; + else Flags &= 0xFFFE; + } StringRef slotName() const { if (Cvdecl) @@ -1014,7 +943,8 @@ public: return Vs.reduceProject(*this, Nr); } - template <class C> typename C::CType compare(Project* E, C& Cmp) { + template <class C> + typename C::CType compare(const Project* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(record(), E->record()); if (Cmp.notTrue(Ct)) return Ct; @@ -1022,13 +952,13 @@ public: } private: - SExprRef Rec; + SExpr* Rec; StringRef SlotName; - clang::ValueDecl *Cvdecl; + const clang::ValueDecl *Cvdecl; }; -// Call a function (after all arguments have been applied). +/// Call a function (after all arguments have been applied). class Call : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Call; } @@ -1037,8 +967,8 @@ public: : SExpr(COP_Call), Target(T), Cexpr(Ce) {} Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {} - SExpr *target() { return Target.get(); } - const SExpr *target() const { return Target.get(); } + SExpr *target() { return Target; } + const SExpr *target() const { return Target; } const clang::CallExpr *clangCallExpr() const { return Cexpr; } @@ -1048,17 +978,18 @@ public: return Vs.reduceCall(*this, Nt); } - template <class C> typename C::CType compare(Call* E, C& Cmp) { + template <class C> + typename C::CType compare(const Call* E, C& Cmp) const { return Cmp.compare(target(), E->target()); } private: - SExprRef Target; + SExpr* Target; const clang::CallExpr *Cexpr; }; -// Allocate memory for a new value on the heap or stack. +/// Allocate memory for a new value on the heap or stack. class Alloc : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Call; } @@ -1073,8 +1004,8 @@ public: AllocKind kind() const { return static_cast<AllocKind>(Flags); } - SExpr *dataType() { return Dtype.get(); } - const SExpr *dataType() const { return Dtype.get(); } + SExpr *dataType() { return Dtype; } + const SExpr *dataType() const { return Dtype; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1082,7 +1013,8 @@ public: return Vs.reduceAlloc(*this, Nd); } - template <class C> typename C::CType compare(Alloc* E, C& Cmp) { + template <class C> + typename C::CType compare(const Alloc* E, C& Cmp) const { typename C::CType Ct = Cmp.compareIntegers(kind(), E->kind()); if (Cmp.notTrue(Ct)) return Ct; @@ -1090,11 +1022,11 @@ public: } private: - SExprRef Dtype; + SExpr* Dtype; }; -// Load a value from memory. +/// Load a value from memory. class Load : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Load; } @@ -1102,8 +1034,8 @@ public: Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {} Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {} - SExpr *pointer() { return Ptr.get(); } - const SExpr *pointer() const { return Ptr.get(); } + SExpr *pointer() { return Ptr; } + const SExpr *pointer() const { return Ptr; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1111,17 +1043,18 @@ public: return Vs.reduceLoad(*this, Np); } - template <class C> typename C::CType compare(Load* E, C& Cmp) { + template <class C> + typename C::CType compare(const Load* E, C& Cmp) const { return Cmp.compare(pointer(), E->pointer()); } private: - SExprRef Ptr; + SExpr* Ptr; }; -// Store a value to memory. -// Source is a pointer, destination is the value to store. +/// Store a value to memory. +/// The destination is a pointer to a field, the source is the value to store. class Store : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Store; } @@ -1129,11 +1062,11 @@ public: Store(SExpr *P, SExpr *V) : SExpr(COP_Store), Dest(P), Source(V) {} Store(const Store &S, SExpr *P, SExpr *V) : SExpr(S), Dest(P), Source(V) {} - SExpr *destination() { return Dest.get(); } // Address to store to - const SExpr *destination() const { return Dest.get(); } + SExpr *destination() { return Dest; } // Address to store to + const SExpr *destination() const { return Dest; } - SExpr *source() { return Source.get(); } // Value to store - const SExpr *source() const { return Source.get(); } + SExpr *source() { return Source; } // Value to store + const SExpr *source() const { return Source; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1142,7 +1075,8 @@ public: return Vs.reduceStore(*this, Np, Nv); } - template <class C> typename C::CType compare(Store* E, C& Cmp) { + template <class C> + typename C::CType compare(const Store* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(destination(), E->destination()); if (Cmp.notTrue(Ct)) return Ct; @@ -1150,13 +1084,13 @@ public: } private: - SExprRef Dest; - SExprRef Source; + SExpr* Dest; + SExpr* Source; }; -// If p is a reference to an array, then first(p) is a reference to the first -// element. The usual array notation p[i] becomes first(p + i). +/// If p is a reference to an array, then p[i] is a reference to the i'th +/// element of the array. class ArrayIndex : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; } @@ -1165,11 +1099,11 @@ public: ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N) : SExpr(E), Array(A), Index(N) {} - SExpr *array() { return Array.get(); } - const SExpr *array() const { return Array.get(); } + SExpr *array() { return Array; } + const SExpr *array() const { return Array; } - SExpr *index() { return Index.get(); } - const SExpr *index() const { return Index.get(); } + SExpr *index() { return Index; } + const SExpr *index() const { return Index; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1178,7 +1112,8 @@ public: return Vs.reduceArrayIndex(*this, Na, Ni); } - template <class C> typename C::CType compare(ArrayIndex* E, C& Cmp) { + template <class C> + typename C::CType compare(const ArrayIndex* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(array(), E->array()); if (Cmp.notTrue(Ct)) return Ct; @@ -1186,14 +1121,14 @@ public: } private: - SExprRef Array; - SExprRef Index; + SExpr* Array; + SExpr* Index; }; -// Pointer arithmetic, restricted to arrays only. -// If p is a reference to an array, then p + n, where n is an integer, is -// a reference to a subarray. +/// Pointer arithmetic, restricted to arrays only. +/// If p is a reference to an array, then p + n, where n is an integer, is +/// a reference to a subarray. class ArrayAdd : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; } @@ -1202,11 +1137,11 @@ public: ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N) : SExpr(E), Array(A), Index(N) {} - SExpr *array() { return Array.get(); } - const SExpr *array() const { return Array.get(); } + SExpr *array() { return Array; } + const SExpr *array() const { return Array; } - SExpr *index() { return Index.get(); } - const SExpr *index() const { return Index.get(); } + SExpr *index() { return Index; } + const SExpr *index() const { return Index; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1215,7 +1150,8 @@ public: return Vs.reduceArrayAdd(*this, Na, Ni); } - template <class C> typename C::CType compare(ArrayAdd* E, C& Cmp) { + template <class C> + typename C::CType compare(const ArrayAdd* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(array(), E->array()); if (Cmp.notTrue(Ct)) return Ct; @@ -1223,12 +1159,13 @@ public: } private: - SExprRef Array; - SExprRef Index; + SExpr* Array; + SExpr* Index; }; -// Simple unary operation -- e.g. !, ~, etc. +/// Simple arithmetic unary operations, e.g. negate and not. +/// These operations have no side-effects. class UnaryOp : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; } @@ -1242,8 +1179,8 @@ public: return static_cast<TIL_UnaryOpcode>(Flags); } - SExpr *expr() { return Expr0.get(); } - const SExpr *expr() const { return Expr0.get(); } + SExpr *expr() { return Expr0; } + const SExpr *expr() const { return Expr0; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1251,7 +1188,8 @@ public: return Vs.reduceUnaryOp(*this, Ne); } - template <class C> typename C::CType compare(UnaryOp* E, C& Cmp) { + template <class C> + typename C::CType compare(const UnaryOp* E, C& Cmp) const { typename C::CType Ct = Cmp.compareIntegers(unaryOpcode(), E->unaryOpcode()); if (Cmp.notTrue(Ct)) @@ -1260,11 +1198,12 @@ public: } private: - SExprRef Expr0; + SExpr* Expr0; }; -// Simple binary operation -- e.g. +, -, etc. +/// Simple arithmetic binary operations, e.g. +, -, etc. +/// These operations have no side effects. class BinaryOp : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; } @@ -1282,11 +1221,11 @@ public: return static_cast<TIL_BinaryOpcode>(Flags); } - SExpr *expr0() { return Expr0.get(); } - const SExpr *expr0() const { return Expr0.get(); } + SExpr *expr0() { return Expr0; } + const SExpr *expr0() const { return Expr0; } - SExpr *expr1() { return Expr1.get(); } - const SExpr *expr1() const { return Expr1.get(); } + SExpr *expr1() { return Expr1; } + const SExpr *expr1() const { return Expr1; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1295,7 +1234,8 @@ public: return Vs.reduceBinaryOp(*this, Ne0, Ne1); } - template <class C> typename C::CType compare(BinaryOp* E, C& Cmp) { + template <class C> + typename C::CType compare(const BinaryOp* E, C& Cmp) const { typename C::CType Ct = Cmp.compareIntegers(binaryOpcode(), E->binaryOpcode()); if (Cmp.notTrue(Ct)) @@ -1307,12 +1247,14 @@ public: } private: - SExprRef Expr0; - SExprRef Expr1; + SExpr* Expr0; + SExpr* Expr1; }; -// Cast expression +/// Cast expressions. +/// Cast expressions are essentially unary operations, but we treat them +/// as a distinct AST node because they only change the type of the result. class Cast : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; } @@ -1324,8 +1266,8 @@ public: return static_cast<TIL_CastOpcode>(Flags); } - SExpr *expr() { return Expr0.get(); } - const SExpr *expr() const { return Expr0.get(); } + SExpr *expr() { return Expr0; } + const SExpr *expr() const { return Expr0; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1333,7 +1275,8 @@ public: return Vs.reduceCast(*this, Ne); } - template <class C> typename C::CType compare(Cast* E, C& Cmp) { + template <class C> + typename C::CType compare(const Cast* E, C& Cmp) const { typename C::CType Ct = Cmp.compareIntegers(castOpcode(), E->castOpcode()); if (Cmp.notTrue(Ct)) @@ -1342,16 +1285,18 @@ public: } private: - SExprRef Expr0; + SExpr* Expr0; }; class SCFG; +/// Phi Node, for code in SSA form. +/// Each Phi node has an array of possible values that it can take, +/// depending on where control flow comes from. class Phi : public SExpr { public: - // TODO: change to SExprRef typedef SimpleArray<SExpr *> ValArray; // In minimal SSA form, all Phi nodes are MultiVal. @@ -1365,9 +1310,12 @@ public: static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; } - Phi() : SExpr(COP_Phi) {} - Phi(MemRegionRef A, unsigned Nvals) : SExpr(COP_Phi), Values(A, Nvals) {} - Phi(const Phi &P, ValArray &&Vs) : SExpr(P), Values(std::move(Vs)) {} + Phi() + : SExpr(COP_Phi), Cvdecl(nullptr) {} + Phi(MemRegionRef A, unsigned Nvals) + : SExpr(COP_Phi), Values(A, Nvals), Cvdecl(nullptr) {} + Phi(const Phi &P, ValArray &&Vs) + : SExpr(P), Values(std::move(Vs)), Cvdecl(nullptr) {} const ValArray &values() const { return Values; } ValArray &values() { return Values; } @@ -1375,6 +1323,12 @@ public: Status status() const { return static_cast<Status>(Flags); } void setStatus(Status s) { Flags = s; } + /// Return the clang declaration of the variable for this Phi node, if any. + const clang::ValueDecl *clangDecl() const { return Cvdecl; } + + /// Set the clang variable associated with this Phi node. + void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; } + template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { typename V::template Container<typename V::R_SExpr> @@ -1386,72 +1340,268 @@ public: return Vs.reducePhi(*this, Nvs); } - template <class C> typename C::CType compare(Phi *E, C &Cmp) { + template <class C> + typename C::CType compare(const Phi *E, C &Cmp) const { // TODO: implement CFG comparisons return Cmp.comparePointers(this, E); } private: ValArray Values; + const clang::ValueDecl* Cvdecl; +}; + + +/// Base class for basic block terminators: Branch, Goto, and Return. +class Terminator : public SExpr { +public: + static bool classof(const SExpr *E) { + return E->opcode() >= COP_Goto && E->opcode() <= COP_Return; + } + +protected: + Terminator(TIL_Opcode Op) : SExpr(Op) {} + Terminator(const SExpr &E) : SExpr(E) {} + +public: + /// Return the list of basic blocks that this terminator can branch to. + ArrayRef<BasicBlock*> successors(); + + ArrayRef<BasicBlock*> successors() const { + return const_cast<Terminator*>(this)->successors(); + } }; -// A basic block is part of an SCFG, and can be treated as a function in -// continuation passing style. It consists of a sequence of phi nodes, which -// are "arguments" to the function, followed by a sequence of instructions. -// Both arguments and instructions define new variables. It ends with a -// branch or goto to another basic block in the same SCFG. +/// Jump to another basic block. +/// A goto instruction is essentially a tail-recursive call into another +/// block. In addition to the block pointer, it specifies an index into the +/// phi nodes of that block. The index can be used to retrieve the "arguments" +/// of the call. +class Goto : public Terminator { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; } + + Goto(BasicBlock *B, unsigned I) + : Terminator(COP_Goto), TargetBlock(B), Index(I) {} + Goto(const Goto &G, BasicBlock *B, unsigned I) + : Terminator(COP_Goto), TargetBlock(B), Index(I) {} + + const BasicBlock *targetBlock() const { return TargetBlock; } + BasicBlock *targetBlock() { return TargetBlock; } + + /// Returns the index into the + unsigned index() const { return Index; } + + /// Return the list of basic blocks that this terminator can branch to. + ArrayRef<BasicBlock*> successors() { + return ArrayRef<BasicBlock*>(&TargetBlock, 1); + } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock); + return Vs.reduceGoto(*this, Ntb); + } + + template <class C> + typename C::CType compare(const Goto *E, C &Cmp) const { + // TODO: implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + BasicBlock *TargetBlock; + unsigned Index; +}; + + +/// A conditional branch to two other blocks. +/// Note that unlike Goto, Branch does not have an index. The target blocks +/// must be child-blocks, and cannot have Phi nodes. +class Branch : public Terminator { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; } + + Branch(SExpr *C, BasicBlock *T, BasicBlock *E) + : Terminator(COP_Branch), Condition(C) { + Branches[0] = T; + Branches[1] = E; + } + Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E) + : Terminator(Br), Condition(C) { + Branches[0] = T; + Branches[1] = E; + } + + const SExpr *condition() const { return Condition; } + SExpr *condition() { return Condition; } + + const BasicBlock *thenBlock() const { return Branches[0]; } + BasicBlock *thenBlock() { return Branches[0]; } + + const BasicBlock *elseBlock() const { return Branches[1]; } + BasicBlock *elseBlock() { return Branches[1]; } + + /// Return the list of basic blocks that this terminator can branch to. + ArrayRef<BasicBlock*> successors() { + return ArrayRef<BasicBlock*>(Branches, 2); + } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx)); + BasicBlock *Ntb = Vs.reduceBasicBlockRef(Branches[0]); + BasicBlock *Nte = Vs.reduceBasicBlockRef(Branches[1]); + return Vs.reduceBranch(*this, Nc, Ntb, Nte); + } + + template <class C> + typename C::CType compare(const Branch *E, C &Cmp) const { + // TODO: implement CFG comparisons + return Cmp.comparePointers(this, E); + } + +private: + SExpr* Condition; + BasicBlock *Branches[2]; +}; + + +/// Return from the enclosing function, passing the return value to the caller. +/// Only the exit block should end with a return statement. +class Return : public Terminator { +public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Return; } + + Return(SExpr* Rval) : Terminator(COP_Return), Retval(Rval) {} + Return(const Return &R, SExpr* Rval) : Terminator(R), Retval(Rval) {} + + /// Return an empty list. + ArrayRef<BasicBlock*> successors() { + return ArrayRef<BasicBlock*>(); + } + + SExpr *returnValue() { return Retval; } + const SExpr *returnValue() const { return Retval; } + + template <class V> + typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { + auto Ne = Vs.traverse(Retval, Vs.subExprCtx(Ctx)); + return Vs.reduceReturn(*this, Ne); + } + + template <class C> + typename C::CType compare(const Return *E, C &Cmp) const { + return Cmp.compare(Retval, E->Retval); + } + +private: + SExpr* Retval; +}; + + +inline ArrayRef<BasicBlock*> Terminator::successors() { + switch (opcode()) { + case COP_Goto: return cast<Goto>(this)->successors(); + case COP_Branch: return cast<Branch>(this)->successors(); + case COP_Return: return cast<Return>(this)->successors(); + default: + return ArrayRef<BasicBlock*>(); + } +} + + +/// A basic block is part of an SCFG. It can be treated as a function in +/// continuation passing style. A block consists of a sequence of phi nodes, +/// which are "arguments" to the function, followed by a sequence of +/// instructions. It ends with a Terminator, which is a Branch or Goto to +/// another basic block in the same SCFG. class BasicBlock : public SExpr { public: - typedef SimpleArray<Variable*> VarArray; + typedef SimpleArray<SExpr*> InstrArray; typedef SimpleArray<BasicBlock*> BlockArray; + // TopologyNodes are used to overlay tree structures on top of the CFG, + // such as dominator and postdominator trees. Each block is assigned an + // ID in the tree according to a depth-first search. Tree traversals are + // always up, towards the parents. + struct TopologyNode { + TopologyNode() : NodeID(0), SizeOfSubTree(0), Parent(nullptr) {} + + bool isParentOf(const TopologyNode& OtherNode) { + return OtherNode.NodeID > NodeID && + OtherNode.NodeID < NodeID + SizeOfSubTree; + } + + bool isParentOfOrEqual(const TopologyNode& OtherNode) { + return OtherNode.NodeID >= NodeID && + OtherNode.NodeID < NodeID + SizeOfSubTree; + } + + int NodeID; + int SizeOfSubTree; // Includes this node, so must be > 1. + BasicBlock *Parent; // Pointer to parent. + }; + static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; } - explicit BasicBlock(MemRegionRef A, BasicBlock* P = nullptr) + explicit BasicBlock(MemRegionRef A) : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0), - Parent(P), Terminator(nullptr) - { } - BasicBlock(BasicBlock &B, VarArray &&As, VarArray &&Is, SExpr *T) - : SExpr(COP_BasicBlock), Arena(B.Arena), CFGPtr(nullptr), BlockID(0), - Parent(nullptr), Args(std::move(As)), Instrs(std::move(Is)), - Terminator(T) - { } + Visited(0), TermInstr(nullptr) {} + BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is, + Terminator *T) + : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0), + Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {} + + /// Returns the block ID. Every block has a unique ID in the CFG. + int blockID() const { return BlockID; } - unsigned blockID() const { return BlockID; } - unsigned numPredecessors() const { return Predecessors.size(); } + /// Returns the number of predecessors. + size_t numPredecessors() const { return Predecessors.size(); } + size_t numSuccessors() const { return successors().size(); } const SCFG* cfg() const { return CFGPtr; } SCFG* cfg() { return CFGPtr; } - const BasicBlock *parent() const { return Parent; } - BasicBlock *parent() { return Parent; } + const BasicBlock *parent() const { return DominatorNode.Parent; } + BasicBlock *parent() { return DominatorNode.Parent; } - const VarArray &arguments() const { return Args; } - VarArray &arguments() { return Args; } + const InstrArray &arguments() const { return Args; } + InstrArray &arguments() { return Args; } - const VarArray &instructions() const { return Instrs; } - VarArray &instructions() { return Instrs; } + InstrArray &instructions() { return Instrs; } + const InstrArray &instructions() const { return Instrs; } - const BlockArray &predecessors() const { return Predecessors; } + /// Returns a list of predecessors. + /// The order of predecessors in the list is important; each phi node has + /// exactly one argument for each precessor, in the same order. BlockArray &predecessors() { return Predecessors; } + const BlockArray &predecessors() const { return Predecessors; } + + ArrayRef<BasicBlock*> successors() { return TermInstr->successors(); } + ArrayRef<BasicBlock*> successors() const { return TermInstr->successors(); } + + const Terminator *terminator() const { return TermInstr; } + Terminator *terminator() { return TermInstr; } - const SExpr *terminator() const { return Terminator.get(); } - SExpr *terminator() { return Terminator.get(); } + void setTerminator(Terminator *E) { TermInstr = E; } - void setBlockID(unsigned i) { BlockID = i; } - void setParent(BasicBlock *P) { Parent = P; } - void setTerminator(SExpr *E) { Terminator.reset(E); } + bool Dominates(const BasicBlock &Other) { + return DominatorNode.isParentOfOrEqual(Other.DominatorNode); + } + + bool PostDominates(const BasicBlock &Other) { + return PostDominatorNode.isParentOfOrEqual(Other.PostDominatorNode); + } - // Add a new argument. V must define a phi-node. - void addArgument(Variable *V) { - V->setKind(Variable::VK_LetBB); + /// Add a new argument. + void addArgument(Phi *V) { Args.reserveCheck(1, Arena); Args.push_back(V); } - // Add a new instruction. - void addInstruction(Variable *V) { - V->setKind(Variable::VK_LetBB); + /// Add a new instruction. + void addInstruction(SExpr *V) { Instrs.reserveCheck(1, Arena); Instrs.push_back(V); } @@ -1468,34 +1618,29 @@ public: // Reserve space for NumPreds predecessors, including space in phi nodes. void reservePredecessors(unsigned NumPreds); - // Return the index of BB, or Predecessors.size if BB is not a predecessor. + /// Return the index of BB, or Predecessors.size if BB is not a predecessor. unsigned findPredecessorIndex(const BasicBlock *BB) const { auto I = std::find(Predecessors.cbegin(), Predecessors.cend(), BB); return std::distance(Predecessors.cbegin(), I); } - // Set id numbers for variables. - void renumberVars(); - template <class V> typename V::R_BasicBlock traverse(V &Vs, typename V::R_Ctx Ctx) { - typename V::template Container<Variable*> Nas(Vs, Args.size()); - typename V::template Container<Variable*> Nis(Vs, Instrs.size()); + typename V::template Container<SExpr*> Nas(Vs, Args.size()); + typename V::template Container<SExpr*> Nis(Vs, Instrs.size()); // Entering the basic block should do any scope initialization. Vs.enterBasicBlock(*this); - for (auto *A : Args) { - auto Ne = Vs.traverse(A->Definition, Vs.subExprCtx(Ctx)); - Variable *Nvd = Vs.enterScope(*A, Ne); - Nas.push_back(Nvd); + for (auto *E : Args) { + auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx)); + Nas.push_back(Ne); } - for (auto *I : Instrs) { - auto Ne = Vs.traverse(I->Definition, Vs.subExprCtx(Ctx)); - Variable *Nvd = Vs.enterScope(*I, Ne); - Nis.push_back(Nvd); + for (auto *E : Instrs) { + auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx)); + Nis.push_back(Ne); } - auto Nt = Vs.traverse(Terminator, Ctx); + auto Nt = Vs.traverse(TermInstr, Ctx); // Exiting the basic block should handle any scope cleanup. Vs.exitBasicBlock(*this); @@ -1503,7 +1648,8 @@ public: return Vs.reduceBasicBlock(*this, Nas, Nis, Nt); } - template <class C> typename C::CType compare(BasicBlock *E, C &Cmp) { + template <class C> + typename C::CType compare(const BasicBlock *E, C &Cmp) const { // TODO: implement CFG comparisons return Cmp.comparePointers(this, E); } @@ -1511,22 +1657,32 @@ public: private: friend class SCFG; - MemRegionRef Arena; + int renumberInstrs(int id); // assign unique ids to all instructions + int topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID); + int topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID); + void computeDominator(); + void computePostDominator(); - SCFG *CFGPtr; // The CFG that contains this block. - unsigned BlockID; // unique id for this BB in the containing CFG - BasicBlock *Parent; // The parent block is the enclosing lexical scope. - // The parent dominates this block. - BlockArray Predecessors; // Predecessor blocks in the CFG. - VarArray Args; // Phi nodes. One argument per predecessor. - VarArray Instrs; // Instructions. - SExprRef Terminator; // Branch or Goto +private: + MemRegionRef Arena; // The arena used to allocate this block. + SCFG *CFGPtr; // The CFG that contains this block. + int BlockID : 31; // unique id for this BB in the containing CFG. + // IDs are in topological order. + bool Visited : 1; // Bit to determine if a block has been visited + // during a traversal. + BlockArray Predecessors; // Predecessor blocks in the CFG. + InstrArray Args; // Phi nodes. One argument per predecessor. + InstrArray Instrs; // Instructions. + Terminator* TermInstr; // Terminating instruction + + TopologyNode DominatorNode; // The dominator tree + TopologyNode PostDominatorNode; // The post-dominator tree }; -// An SCFG is a control-flow graph. It consists of a set of basic blocks, each -// of which terminates in a branch to another basic block. There is one -// entry point, and one exit point. +/// An SCFG is a control-flow graph. It consists of a set of basic blocks, +/// each of which terminates in a branch to another basic block. There is one +/// entry point, and one exit point. class SCFG : public SExpr { public: typedef SimpleArray<BasicBlock *> BlockArray; @@ -1537,20 +1693,29 @@ public: SCFG(MemRegionRef A, unsigned Nblocks) : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks), - Entry(nullptr), Exit(nullptr) { - Entry = new (A) BasicBlock(A, nullptr); - Exit = new (A) BasicBlock(A, Entry); - auto *V = new (A) Variable(new (A) Phi()); + Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) { + Entry = new (A) BasicBlock(A); + Exit = new (A) BasicBlock(A); + auto *V = new (A) Phi(); Exit->addArgument(V); + Exit->setTerminator(new (A) Return(V)); add(Entry); add(Exit); } SCFG(const SCFG &Cfg, BlockArray &&Ba) // steals memory from Ba : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)), - Entry(nullptr), Exit(nullptr) { + Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) { // TODO: set entry and exit! } + /// Return true if this CFG is valid. + bool valid() const { return Entry && Exit && Blocks.size() > 0; } + + /// Return true if this CFG has been normalized. + /// After normalization, blocks are in topological order, and block and + /// instruction IDs have been assigned. + bool normal() const { return Normal; } + iterator begin() { return Blocks.begin(); } iterator end() { return Blocks.end(); } @@ -1565,9 +1730,17 @@ public: const BasicBlock *exit() const { return Exit; } BasicBlock *exit() { return Exit; } + /// Return the number of blocks in the CFG. + /// Block::blockID() will return a number less than numBlocks(); + size_t numBlocks() const { return Blocks.size(); } + + /// Return the total number of instructions in the CFG. + /// This is useful for building instruction side-tables; + /// A call to SExpr::id() will return a number less than numInstructions(). + unsigned numInstructions() { return NumInstructions; } + inline void add(BasicBlock *BB) { - assert(BB->CFGPtr == nullptr || BB->CFGPtr == this); - BB->setBlockID(Blocks.size()); + assert(BB->CFGPtr == nullptr); BB->CFGPtr = this; Blocks.reserveCheck(1, Arena); Blocks.push_back(BB); @@ -1576,13 +1749,13 @@ public: void setEntry(BasicBlock *BB) { Entry = BB; } void setExit(BasicBlock *BB) { Exit = BB; } - // Set varable ids in all blocks. - void renumberVars(); + void computeNormalForm(); template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { Vs.enterCFG(*this); typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size()); + for (auto *B : Blocks) { Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) ); } @@ -1590,100 +1763,28 @@ public: return Vs.reduceSCFG(*this, Bbs); } - template <class C> typename C::CType compare(SCFG *E, C &Cmp) { - // TODO -- implement CFG comparisons + template <class C> + typename C::CType compare(const SCFG *E, C &Cmp) const { + // TODO: implement CFG comparisons return Cmp.comparePointers(this, E); } private: + void renumberInstrs(); // assign unique ids to all instructions + +private: MemRegionRef Arena; BlockArray Blocks; BasicBlock *Entry; BasicBlock *Exit; + unsigned NumInstructions; + bool Normal; }; -class Goto : public SExpr { -public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; } - - Goto(BasicBlock *B, unsigned I) - : SExpr(COP_Goto), TargetBlock(B), Index(I) {} - Goto(const Goto &G, BasicBlock *B, unsigned I) - : SExpr(COP_Goto), TargetBlock(B), Index(I) {} - const BasicBlock *targetBlock() const { return TargetBlock; } - BasicBlock *targetBlock() { return TargetBlock; } - - unsigned index() const { return Index; } - - template <class V> - typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { - BasicBlock *Ntb = Vs.reduceBasicBlockRef(TargetBlock); - return Vs.reduceGoto(*this, Ntb); - } - - template <class C> typename C::CType compare(Goto *E, C &Cmp) { - // TODO -- implement CFG comparisons - return Cmp.comparePointers(this, E); - } - -private: - BasicBlock *TargetBlock; - unsigned Index; // Index into Phi nodes of target block. -}; - - -class Branch : public SExpr { -public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; } - - Branch(SExpr *C, BasicBlock *T, BasicBlock *E, unsigned TI, unsigned EI) - : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E), - ThenIndex(TI), ElseIndex(EI) - {} - Branch(const Branch &Br, SExpr *C, BasicBlock *T, BasicBlock *E, - unsigned TI, unsigned EI) - : SExpr(COP_Branch), Condition(C), ThenBlock(T), ElseBlock(E), - ThenIndex(TI), ElseIndex(EI) - {} - - const SExpr *condition() const { return Condition; } - SExpr *condition() { return Condition; } - - const BasicBlock *thenBlock() const { return ThenBlock; } - BasicBlock *thenBlock() { return ThenBlock; } - - const BasicBlock *elseBlock() const { return ElseBlock; } - BasicBlock *elseBlock() { return ElseBlock; } - - unsigned thenIndex() const { return ThenIndex; } - unsigned elseIndex() const { return ElseIndex; } - - template <class V> - typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { - auto Nc = Vs.traverse(Condition, Vs.subExprCtx(Ctx)); - BasicBlock *Ntb = Vs.reduceBasicBlockRef(ThenBlock); - BasicBlock *Nte = Vs.reduceBasicBlockRef(ElseBlock); - return Vs.reduceBranch(*this, Nc, Ntb, Nte); - } - - template <class C> typename C::CType compare(Branch *E, C &Cmp) { - // TODO -- implement CFG comparisons - return Cmp.comparePointers(this, E); - } - -private: - SExpr *Condition; - BasicBlock *ThenBlock; - BasicBlock *ElseBlock; - unsigned ThenIndex; - unsigned ElseIndex; -}; - - -// An identifier, e.g. 'foo' or 'x'. -// This is a pseduo-term; it will be lowered to a variable or projection. +/// An identifier, e.g. 'foo' or 'x'. +/// This is a pseduo-term; it will be lowered to a variable or projection. class Identifier : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; } @@ -1698,7 +1799,8 @@ public: return Vs.reduceIdentifier(*this); } - template <class C> typename C::CType compare(Identifier* E, C& Cmp) { + template <class C> + typename C::CType compare(const Identifier* E, C& Cmp) const { return Cmp.compareStrings(name(), E->name()); } @@ -1707,8 +1809,8 @@ private: }; -// An if-then-else expression. -// This is a pseduo-term; it will be lowered to a branch in a CFG. +/// An if-then-else expression. +/// This is a pseduo-term; it will be lowered to a branch in a CFG. class IfThenElse : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; } @@ -1720,14 +1822,14 @@ public: : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) { } - SExpr *condition() { return Condition.get(); } // Address to store to - const SExpr *condition() const { return Condition.get(); } + SExpr *condition() { return Condition; } // Address to store to + const SExpr *condition() const { return Condition; } - SExpr *thenExpr() { return ThenExpr.get(); } // Value to store - const SExpr *thenExpr() const { return ThenExpr.get(); } + SExpr *thenExpr() { return ThenExpr; } // Value to store + const SExpr *thenExpr() const { return ThenExpr; } - SExpr *elseExpr() { return ElseExpr.get(); } // Value to store - const SExpr *elseExpr() const { return ElseExpr.get(); } + SExpr *elseExpr() { return ElseExpr; } // Value to store + const SExpr *elseExpr() const { return ElseExpr; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1737,7 +1839,8 @@ public: return Vs.reduceIfThenElse(*this, Nc, Nt, Ne); } - template <class C> typename C::CType compare(IfThenElse* E, C& Cmp) { + template <class C> + typename C::CType compare(const IfThenElse* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(condition(), E->condition()); if (Cmp.notTrue(Ct)) return Ct; @@ -1748,14 +1851,14 @@ public: } private: - SExprRef Condition; - SExprRef ThenExpr; - SExprRef ElseExpr; + SExpr* Condition; + SExpr* ThenExpr; + SExpr* ElseExpr; }; -// A let-expression, e.g. let x=t; u. -// This is a pseduo-term; it will be lowered to instructions in a CFG. +/// A let-expression, e.g. let x=t; u. +/// This is a pseduo-term; it will be lowered to instructions in a CFG. class Let : public SExpr { public: static bool classof(const SExpr *E) { return E->opcode() == COP_Let; } @@ -1770,8 +1873,8 @@ public: Variable *variableDecl() { return VarDecl; } const Variable *variableDecl() const { return VarDecl; } - SExpr *body() { return Body.get(); } - const SExpr *body() const { return Body.get(); } + SExpr *body() { return Body; } + const SExpr *body() const { return Body; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1784,7 +1887,8 @@ public: return Vs.reduceLet(*this, Nvd, E1); } - template <class C> typename C::CType compare(Let* E, C& Cmp) { + template <class C> + typename C::CType compare(const Let* E, C& Cmp) const { typename C::CType Ct = Cmp.compare(VarDecl->definition(), E->VarDecl->definition()); if (Cmp.notTrue(Ct)) @@ -1797,17 +1901,18 @@ public: private: Variable *VarDecl; - SExprRef Body; + SExpr* Body; }; -SExpr *getCanonicalVal(SExpr *E); -void simplifyIncompleteArg(Variable *V, til::Phi *Ph); +const SExpr *getCanonicalVal(const SExpr *E); +SExpr* simplifyToCanonicalVal(SExpr *E); +void simplifyIncompleteArg(til::Phi *Ph); } // end namespace til } // end namespace threadSafety } // end namespace clang -#endif // LLVM_CLANG_THREAD_SAFETY_TIL_H +#endif diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h index bc1490b4a448..705fe910d092 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h @@ -14,10 +14,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H -#define LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H #include "ThreadSafetyTIL.h" +#include <ostream> namespace clang { namespace threadSafety { @@ -56,11 +57,16 @@ public: // Traverse an expression -- returning a result of type R_SExpr. // Override this method to do something for every expression, regardless // of which kind it is. - typename R::R_SExpr traverse(SExprRef &E, typename R::R_Ctx Ctx) { - return traverse(E.get(), Ctx); + // E is a reference, so this can be use for in-place updates. + // The type T must be a subclass of SExpr. + template <class T> + typename R::R_SExpr traverse(T* &E, typename R::R_Ctx Ctx) { + return traverseSExpr(E, Ctx); } - typename R::R_SExpr traverse(SExpr *E, typename R::R_Ctx Ctx) { + // Override this method to do something for every expression. + // Does not allow in-place updates. + typename R::R_SExpr traverseSExpr(SExpr *E, typename R::R_Ctx Ctx) { return traverseByCase(E, Ctx); } @@ -73,6 +79,7 @@ public: #include "ThreadSafetyOps.def" #undef TIL_OPCODE_DEF } + return self()->reduceNull(); } // Traverse e, by static dispatch on the type "X" of e. @@ -90,10 +97,10 @@ public: class SimpleReducerBase { public: enum TraversalKind { - TRV_Normal, - TRV_Decl, - TRV_Lazy, - TRV_Type + TRV_Normal, // ordinary subexpressions + TRV_Decl, // declarations (e.g. function bodies) + TRV_Lazy, // expressions that require lazy evaluation + TRV_Type // type expressions }; // R_Ctx defines a "context" for the traversal, which encodes information @@ -145,153 +152,6 @@ protected: }; -// Implements a traversal that makes a deep copy of an SExpr. -// The default behavior of reduce##X(...) is to create a copy of the original. -// Subclasses can override reduce##X to implement non-destructive rewriting -// passes. -template<class Self> -class CopyReducer : public Traversal<Self, CopyReducerBase>, - public CopyReducerBase { -public: - CopyReducer(MemRegionRef A) : CopyReducerBase(A) {} - -public: - R_SExpr reduceNull() { - return nullptr; - } - // R_SExpr reduceFuture(...) is never used. - - R_SExpr reduceUndefined(Undefined &Orig) { - return new (Arena) Undefined(Orig); - } - R_SExpr reduceWildcard(Wildcard &Orig) { - return new (Arena) Wildcard(Orig); - } - - R_SExpr reduceLiteral(Literal &Orig) { - return new (Arena) Literal(Orig); - } - template<class T> - R_SExpr reduceLiteralT(LiteralT<T> &Orig) { - return new (Arena) LiteralT<T>(Orig); - } - R_SExpr reduceLiteralPtr(LiteralPtr &Orig) { - return new (Arena) LiteralPtr(Orig); - } - - R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { - return new (Arena) Function(Orig, Nvd, E0); - } - R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { - return new (Arena) SFunction(Orig, Nvd, E0); - } - R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Code(Orig, E0, E1); - } - R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Field(Orig, E0, E1); - } - - R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Apply(Orig, E0, E1); - } - R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) SApply(Orig, E0, E1); - } - R_SExpr reduceProject(Project &Orig, R_SExpr E0) { - return new (Arena) Project(Orig, E0); - } - R_SExpr reduceCall(Call &Orig, R_SExpr E0) { - return new (Arena) Call(Orig, E0); - } - - R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { - return new (Arena) Alloc(Orig, E0); - } - R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { - return new (Arena) Load(Orig, E0); - } - R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) Store(Orig, E0, E1); - } - R_SExpr reduceArrayIndex(ArrayIndex &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) ArrayIndex(Orig, E0, E1); - } - R_SExpr reduceArrayAdd(ArrayAdd &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) ArrayAdd(Orig, E0, E1); - } - R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { - return new (Arena) UnaryOp(Orig, E0); - } - R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { - return new (Arena) BinaryOp(Orig, E0, E1); - } - R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { - return new (Arena) Cast(Orig, E0); - } - - R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> &Bbs) { - return nullptr; // FIXME: implement CFG rewriting - } - R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, - Container<Variable *> &Is, R_SExpr T) { - return nullptr; // FIXME: implement CFG rewriting - } - R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { - return new (Arena) Phi(Orig, std::move(As.Elems)); - } - R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { - return new (Arena) Goto(Orig, B, 0); // FIXME: set index - } - R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { - return new (Arena) Branch(O, C, B0, B1, 0, 0); // FIXME: set indices - } - - R_SExpr reduceIdentifier(Identifier &Orig) { - return new (Arena) Identifier(Orig); - } - R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { - return new (Arena) IfThenElse(Orig, C, T, E); - } - R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { - return new (Arena) Let(Orig, Nvd, B); - } - - // Create a new variable from orig, and push it onto the lexical scope. - Variable *enterScope(Variable &Orig, R_SExpr E0) { - return new (Arena) Variable(Orig, E0); - } - // Exit the lexical scope of orig. - void exitScope(const Variable &Orig) {} - - void enterCFG(SCFG &Cfg) {} - void exitCFG(SCFG &Cfg) {} - void enterBasicBlock(BasicBlock &BB) {} - void exitBasicBlock(BasicBlock &BB) {} - - // Map Variable references to their rewritten definitions. - Variable *reduceVariableRef(Variable *Ovd) { return Ovd; } - - // Map BasicBlock references to their rewritten definitions. - BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } -}; - - -class SExprCopier : public CopyReducer<SExprCopier> { -public: - typedef SExpr *R_SExpr; - - SExprCopier(MemRegionRef A) : CopyReducer(A) { } - - // Create a copy of e in region a. - static SExpr *copy(SExpr *E, MemRegionRef A) { - SExprCopier Copier(A); - return Copier.traverse(E, TRV_Normal); - } -}; - - - // Base class for visit traversals. class VisitReducerBase : public SimpleReducerBase { public: @@ -366,8 +226,8 @@ public: R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) { return Bbs.Success; } - R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<Variable *> &As, - Container<Variable *> &Is, R_SExpr T) { + R_BasicBlock reduceBasicBlock(BasicBlock &Orig, Container<R_SExpr> &As, + Container<R_SExpr> &Is, R_SExpr T) { return (As.Success && Is.Success && T); } R_SExpr reducePhi(Phi &Orig, Container<R_SExpr> &As) { @@ -379,6 +239,9 @@ public: R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { return C; } + R_SExpr reduceReturn(Return &O, R_SExpr E) { + return E; + } R_SExpr reduceIdentifier(Identifier &Orig) { return true; @@ -423,7 +286,7 @@ protected: Self *self() { return reinterpret_cast<Self *>(this); } public: - bool compareByCase(SExpr *E1, SExpr* E2) { + bool compareByCase(const SExpr *E1, const SExpr* E2) { switch (E1->opcode()) { #define TIL_OPCODE_DEF(X) \ case COP_##X: \ @@ -431,6 +294,7 @@ public: #include "ThreadSafetyOps.def" #undef TIL_OPCODE_DEF } + return false; } }; @@ -449,38 +313,86 @@ public: bool compareStrings (StringRef s, StringRef r) { return s == r; } bool comparePointers(const void* P, const void* Q) { return P == Q; } - bool compare(SExpr *E1, SExpr* E2) { + bool compare(const SExpr *E1, const SExpr* E2) { if (E1->opcode() != E2->opcode()) return false; return compareByCase(E1, E2); } // TODO -- handle alpha-renaming of variables - void enterScope(Variable* V1, Variable* V2) { } + void enterScope(const Variable* V1, const Variable* V2) { } void leaveScope() { } - bool compareVariableRefs(Variable* V1, Variable* V2) { + bool compareVariableRefs(const Variable* V1, const Variable* V2) { return V1 == V2; } - static bool compareExprs(SExpr *E1, SExpr* E2) { + static bool compareExprs(const SExpr *E1, const SExpr* E2) { EqualsComparator Eq; return Eq.compare(E1, E2); } }; + +class MatchComparator : public Comparator<MatchComparator> { +public: + // Result type for the comparison, e.g. bool for simple equality, + // or int for lexigraphic comparison (-1, 0, 1). Must have one value which + // denotes "true". + typedef bool CType; + + CType trueResult() { return true; } + bool notTrue(CType ct) { return !ct; } + + bool compareIntegers(unsigned i, unsigned j) { return i == j; } + bool compareStrings (StringRef s, StringRef r) { return s == r; } + bool comparePointers(const void* P, const void* Q) { return P == Q; } + + bool compare(const SExpr *E1, const SExpr* E2) { + // Wildcards match anything. + if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard) + return true; + // otherwise normal equality. + if (E1->opcode() != E2->opcode()) + return false; + return compareByCase(E1, E2); + } + + // TODO -- handle alpha-renaming of variables + void enterScope(const Variable* V1, const Variable* V2) { } + void leaveScope() { } + + bool compareVariableRefs(const Variable* V1, const Variable* V2) { + return V1 == V2; + } + + static bool compareExprs(const SExpr *E1, const SExpr* E2) { + MatchComparator Matcher; + return Matcher.compare(E1, E2); + } +}; + + + +// inline std::ostream& operator<<(std::ostream& SS, StringRef R) { +// return SS.write(R.data(), R.size()); +// } + // Pretty printer for TIL expressions template <typename Self, typename StreamType> class PrettyPrinter { private: bool Verbose; // Print out additional information bool Cleanup; // Omit redundant decls. + bool CStyle; // Print exprs in C-like syntax. public: - PrettyPrinter(bool V = false, bool C = true) : Verbose(V), Cleanup(C) { } + PrettyPrinter(bool V = false, bool C = true, bool CS = true) + : Verbose(V), Cleanup(C), CStyle(CS) + {} - static void print(SExpr *E, StreamType &SS) { + static void print(const SExpr *E, StreamType &SS) { Self printer; printer.printSExpr(E, SS, Prec_MAX); } @@ -502,7 +414,7 @@ protected: static const unsigned Prec_MAX = 6; // Return the precedence of a given node, for use in pretty printing. - unsigned precedence(SExpr *E) { + unsigned precedence(const SExpr *E) { switch (E->opcode()) { case COP_Future: return Prec_Atom; case COP_Undefined: return Prec_Atom; @@ -529,13 +441,14 @@ protected: case COP_UnaryOp: return Prec_Unary; case COP_BinaryOp: return Prec_Binary; - case COP_Cast: return Prec_Unary; + case COP_Cast: return Prec_Atom; case COP_SCFG: return Prec_Decl; case COP_BasicBlock: return Prec_MAX; case COP_Phi: return Prec_Atom; case COP_Goto: return Prec_Atom; case COP_Branch: return Prec_Atom; + case COP_Return: return Prec_Other; case COP_Identifier: return Prec_Atom; case COP_IfThenElse: return Prec_Other; @@ -544,22 +457,29 @@ protected: return Prec_MAX; } - void printBlockLabel(StreamType & SS, BasicBlock *BB, unsigned index) { + void printBlockLabel(StreamType & SS, const BasicBlock *BB, int index) { if (!BB) { SS << "BB_null"; return; } SS << "BB_"; SS << BB->blockID(); - SS << ":"; - SS << index; + if (index >= 0) { + SS << ":"; + SS << index; + } } - void printSExpr(SExpr *E, StreamType &SS, unsigned P) { + + void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) { if (!E) { self()->printNull(SS); return; } + if (Sub && E->block() && E->opcode() != COP_Variable) { + SS << "_x" << E->id(); + return; + } if (self()->precedence(E) > P) { // Wrap expr in () if necessary. SS << "("; @@ -582,28 +502,28 @@ protected: SS << "#null"; } - void printFuture(Future *E, StreamType &SS) { + void printFuture(const Future *E, StreamType &SS) { self()->printSExpr(E->maybeGetResult(), SS, Prec_Atom); } - void printUndefined(Undefined *E, StreamType &SS) { + void printUndefined(const Undefined *E, StreamType &SS) { SS << "#undefined"; } - void printWildcard(Wildcard *E, StreamType &SS) { - SS << "_"; + void printWildcard(const Wildcard *E, StreamType &SS) { + SS << "*"; } template<class T> - void printLiteralT(LiteralT<T> *E, StreamType &SS) { + void printLiteralT(const LiteralT<T> *E, StreamType &SS) { SS << E->value(); } - void printLiteralT(LiteralT<uint8_t> *E, StreamType &SS) { + void printLiteralT(const LiteralT<uint8_t> *E, StreamType &SS) { SS << "'" << E->value() << "'"; } - void printLiteral(Literal *E, StreamType &SS) { + void printLiteral(const Literal *E, StreamType &SS) { if (E->clangExpr()) { SS << getSourceLiteralString(E->clangExpr()); return; @@ -685,25 +605,18 @@ protected: SS << "#lit"; } - void printLiteralPtr(LiteralPtr *E, StreamType &SS) { + void printLiteralPtr(const LiteralPtr *E, StreamType &SS) { SS << E->clangDecl()->getNameAsString(); } - void printVariable(Variable *V, StreamType &SS, bool IsVarDecl = false) { - if (!IsVarDecl && Cleanup) { - SExpr* E = getCanonicalVal(V); - if (E != V) { - printSExpr(E, SS, Prec_Atom); - return; - } - } - if (V->kind() == Variable::VK_LetBB) - SS << V->name() << V->getBlockID() << "_" << V->getID(); + void printVariable(const Variable *V, StreamType &SS, bool IsVarDecl=false) { + if (CStyle && V->kind() == Variable::VK_SFun) + SS << "this"; else - SS << V->name() << V->getID(); + SS << V->name() << V->id(); } - void printFunction(Function *E, StreamType &SS, unsigned sugared = 0) { + void printFunction(const Function *E, StreamType &SS, unsigned sugared = 0) { switch (sugared) { default: SS << "\\("; // Lambda @@ -719,7 +632,7 @@ protected: SS << ": "; self()->printSExpr(E->variableDecl()->definition(), SS, Prec_MAX); - SExpr *B = E->body(); + const SExpr *B = E->body(); if (B && B->opcode() == COP_Function) self()->printFunction(cast<Function>(B), SS, 2); else { @@ -728,29 +641,29 @@ protected: } } - void printSFunction(SFunction *E, StreamType &SS) { + void printSFunction(const SFunction *E, StreamType &SS) { SS << "@"; self()->printVariable(E->variableDecl(), SS, true); SS << " "; self()->printSExpr(E->body(), SS, Prec_Decl); } - void printCode(Code *E, StreamType &SS) { + void printCode(const Code *E, StreamType &SS) { SS << ": "; self()->printSExpr(E->returnType(), SS, Prec_Decl-1); SS << " -> "; self()->printSExpr(E->body(), SS, Prec_Decl); } - void printField(Field *E, StreamType &SS) { + void printField(const Field *E, StreamType &SS) { SS << ": "; self()->printSExpr(E->range(), SS, Prec_Decl-1); SS << " = "; self()->printSExpr(E->body(), SS, Prec_Decl); } - void printApply(Apply *E, StreamType &SS, bool sugared = false) { - SExpr *F = E->fun(); + void printApply(const Apply *E, StreamType &SS, bool sugared = false) { + const SExpr *F = E->fun(); if (F->opcode() == COP_Apply) { printApply(cast<Apply>(F), SS, true); SS << ", "; @@ -763,7 +676,7 @@ protected: SS << ")$"; } - void printSApply(SApply *E, StreamType &SS) { + void printSApply(const SApply *E, StreamType &SS) { self()->printSExpr(E->sfun(), SS, Prec_Postfix); if (E->isDelegation()) { SS << "@("; @@ -772,14 +685,36 @@ protected: } } - void printProject(Project *E, StreamType &SS) { + void printProject(const Project *E, StreamType &SS) { + if (CStyle) { + // Omit the this-> + if (const SApply *SAP = dyn_cast<SApply>(E->record())) { + if (const Variable *V = dyn_cast<Variable>(SAP->sfun())) { + if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) { + SS << E->slotName(); + return; + } + } + } + if (isa<Wildcard>(E->record())) { + // handle existentials + SS << "&"; + SS << E->clangDecl()->getQualifiedNameAsString(); + return; + } + } self()->printSExpr(E->record(), SS, Prec_Postfix); - SS << "."; + if (CStyle && E->isArrow()) { + SS << "->"; + } + else { + SS << "."; + } SS << E->slotName(); } - void printCall(Call *E, StreamType &SS) { - SExpr *T = E->target(); + void printCall(const Call *E, StreamType &SS) { + const SExpr *T = E->target(); if (T->opcode() == COP_Apply) { self()->printApply(cast<Apply>(T), SS, true); SS << ")"; @@ -790,52 +725,60 @@ protected: } } - void printAlloc(Alloc *E, StreamType &SS) { + void printAlloc(const Alloc *E, StreamType &SS) { SS << "new "; self()->printSExpr(E->dataType(), SS, Prec_Other-1); } - void printLoad(Load *E, StreamType &SS) { + void printLoad(const Load *E, StreamType &SS) { self()->printSExpr(E->pointer(), SS, Prec_Postfix); - SS << "^"; + if (!CStyle) + SS << "^"; } - void printStore(Store *E, StreamType &SS) { + void printStore(const Store *E, StreamType &SS) { self()->printSExpr(E->destination(), SS, Prec_Other-1); SS << " := "; self()->printSExpr(E->source(), SS, Prec_Other-1); } - void printArrayIndex(ArrayIndex *E, StreamType &SS) { + void printArrayIndex(const ArrayIndex *E, StreamType &SS) { self()->printSExpr(E->array(), SS, Prec_Postfix); SS << "["; self()->printSExpr(E->index(), SS, Prec_MAX); SS << "]"; } - void printArrayAdd(ArrayAdd *E, StreamType &SS) { + void printArrayAdd(const ArrayAdd *E, StreamType &SS) { self()->printSExpr(E->array(), SS, Prec_Postfix); SS << " + "; self()->printSExpr(E->index(), SS, Prec_Atom); } - void printUnaryOp(UnaryOp *E, StreamType &SS) { + void printUnaryOp(const UnaryOp *E, StreamType &SS) { SS << getUnaryOpcodeString(E->unaryOpcode()); self()->printSExpr(E->expr(), SS, Prec_Unary); } - void printBinaryOp(BinaryOp *E, StreamType &SS) { + void printBinaryOp(const BinaryOp *E, StreamType &SS) { self()->printSExpr(E->expr0(), SS, Prec_Binary-1); SS << " " << getBinaryOpcodeString(E->binaryOpcode()) << " "; self()->printSExpr(E->expr1(), SS, Prec_Binary-1); } - void printCast(Cast *E, StreamType &SS) { - SS << "%"; + void printCast(const Cast *E, StreamType &SS) { + if (!CStyle) { + SS << "cast["; + SS << E->castOpcode(); + SS << "]("; + self()->printSExpr(E->expr(), SS, Prec_Unary); + SS << ")"; + return; + } self()->printSExpr(E->expr(), SS, Prec_Unary); } - void printSCFG(SCFG *E, StreamType &SS) { + void printSCFG(const SCFG *E, StreamType &SS) { SS << "CFG {\n"; for (auto BBI : *E) { printBasicBlock(BBI, SS); @@ -844,39 +787,45 @@ protected: newline(SS); } - void printBasicBlock(BasicBlock *E, StreamType &SS) { + + void printBBInstr(const SExpr *E, StreamType &SS) { + bool Sub = false; + if (E->opcode() == COP_Variable) { + auto *V = cast<Variable>(E); + SS << "let " << V->name() << V->id() << " = "; + E = V->definition(); + Sub = true; + } + else if (E->opcode() != COP_Store) { + SS << "let _x" << E->id() << " = "; + } + self()->printSExpr(E, SS, Prec_MAX, Sub); + SS << ";"; + newline(SS); + } + + void printBasicBlock(const BasicBlock *E, StreamType &SS) { SS << "BB_" << E->blockID() << ":"; if (E->parent()) SS << " BB_" << E->parent()->blockID(); newline(SS); - for (auto *A : E->arguments()) { - SS << "let "; - self()->printVariable(A, SS, true); - SS << " = "; - self()->printSExpr(A->definition(), SS, Prec_MAX); - SS << ";"; - newline(SS); - } - for (auto *I : E->instructions()) { - if (I->definition()->opcode() != COP_Store) { - SS << "let "; - self()->printVariable(I, SS, true); - SS << " = "; - } - self()->printSExpr(I->definition(), SS, Prec_MAX); - SS << ";"; - newline(SS); - } - SExpr *T = E->terminator(); + + for (auto *A : E->arguments()) + printBBInstr(A, SS); + + for (auto *I : E->instructions()) + printBBInstr(I, SS); + + const SExpr *T = E->terminator(); if (T) { - self()->printSExpr(T, SS, Prec_MAX); + self()->printSExpr(T, SS, Prec_MAX, false); SS << ";"; newline(SS); } newline(SS); } - void printPhi(Phi *E, StreamType &SS) { + void printPhi(const Phi *E, StreamType &SS) { SS << "phi("; if (E->status() == Phi::PH_SingleVal) self()->printSExpr(E->values()[0], SS, Prec_MAX); @@ -891,25 +840,38 @@ protected: SS << ")"; } - void printGoto(Goto *E, StreamType &SS) { + void printGoto(const Goto *E, StreamType &SS) { SS << "goto "; printBlockLabel(SS, E->targetBlock(), E->index()); } - void printBranch(Branch *E, StreamType &SS) { + void printBranch(const Branch *E, StreamType &SS) { SS << "branch ("; self()->printSExpr(E->condition(), SS, Prec_MAX); SS << ") "; - printBlockLabel(SS, E->thenBlock(), E->thenIndex()); + printBlockLabel(SS, E->thenBlock(), -1); SS << " "; - printBlockLabel(SS, E->elseBlock(), E->elseIndex()); + printBlockLabel(SS, E->elseBlock(), -1); } - void printIdentifier(Identifier *E, StreamType &SS) { + void printReturn(const Return *E, StreamType &SS) { + SS << "return "; + self()->printSExpr(E->returnValue(), SS, Prec_Other); + } + + void printIdentifier(const Identifier *E, StreamType &SS) { SS << E->name(); } - void printIfThenElse(IfThenElse *E, StreamType &SS) { + void printIfThenElse(const IfThenElse *E, StreamType &SS) { + if (CStyle) { + printSExpr(E->condition(), SS, Prec_Unary); + SS << " ? "; + printSExpr(E->thenExpr(), SS, Prec_Unary); + SS << " : "; + printSExpr(E->elseExpr(), SS, Prec_Unary); + return; + } SS << "if ("; printSExpr(E->condition(), SS, Prec_MAX); SS << ") then "; @@ -918,7 +880,7 @@ protected: printSExpr(E->elseExpr(), SS, Prec_Other); } - void printLet(Let *E, StreamType &SS) { + void printLet(const Let *E, StreamType &SS) { SS << "let "; printVariable(E->variableDecl(), SS, true); SS << " = "; @@ -929,6 +891,10 @@ protected: }; +class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { }; + + + } // end namespace til } // end namespace threadSafety } // end namespace clang diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h index 31200a3a7253..ba3e0e519b09 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h @@ -11,19 +11,19 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_THREAD_SAFETY_UTIL_H -#define LLVM_CLANG_THREAD_SAFETY_UTIL_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H +#include "clang/AST/ExprCXX.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" #include "llvm/Support/Compiler.h" -#include "clang/AST/ExprCXX.h" - #include <cassert> #include <cstddef> -#include <vector> +#include <ostream> #include <utility> +#include <vector> namespace clang { namespace threadSafety { @@ -142,18 +142,35 @@ public: assert(i < Size && "Array index out of bounds."); return Data[i]; } + T &back() { + assert(Size && "No elements in the array."); + return Data[Size - 1]; + } + const T &back() const { + assert(Size && "No elements in the array."); + return Data[Size - 1]; + } iterator begin() { return Data; } - iterator end() { return Data + Size; } + iterator end() { return Data + Size; } + + const_iterator begin() const { return Data; } + const_iterator end() const { return Data + Size; } const_iterator cbegin() const { return Data; } - const_iterator cend() const { return Data + Size; } + const_iterator cend() const { return Data + Size; } void push_back(const T &Elem) { assert(Size < Capacity); Data[Size++] = Elem; } + // drop last n elements from array + void drop(unsigned n = 0) { + assert(Size > n); + Size -= n; + } + void setValues(unsigned Sz, const T& C) { assert(Sz <= Capacity); Size = Sz; @@ -171,6 +188,37 @@ public: return J - Osz; } + // An adaptor to reverse a simple array + class ReverseAdaptor { + public: + ReverseAdaptor(SimpleArray &Array) : Array(Array) {} + // A reverse iterator used by the reverse adaptor + class Iterator { + public: + Iterator(T *Data) : Data(Data) {} + T &operator*() { return *Data; } + const T &operator*() const { return *Data; } + Iterator &operator++() { + --Data; + return *this; + } + bool operator!=(Iterator Other) { return Data != Other.Data; } + + private: + T *Data; + }; + Iterator begin() { return Array.end() - 1; } + Iterator end() { return Array.begin() - 1; } + const Iterator begin() const { return Array.end() - 1; } + const Iterator end() const { return Array.begin() - 1; } + + private: + SimpleArray &Array; + }; + + const ReverseAdaptor reverse() const { return ReverseAdaptor(*this); } + ReverseAdaptor reverse() { return ReverseAdaptor(*this); } + private: // std::max is annoying here, because it requires a reference, // thus forcing InitialCapacity to be initialized outside the .h file. @@ -185,6 +233,7 @@ private: size_t Capacity; }; + } // end namespace til @@ -310,6 +359,11 @@ private: }; +inline std::ostream& operator<<(std::ostream& ss, const StringRef str) { + return ss.write(str.data(), str.size()); +} + + } // end namespace threadSafety } // end namespace clang diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 188722d94b3a..53ff20c23560 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_UNINIT_VALS_H -#define LLVM_CLANG_UNINIT_VALS_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H +#define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H #include "clang/AST/Stmt.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/clang/Analysis/AnalysisContext.h b/include/clang/Analysis/AnalysisContext.h index 08e335418ab7..0ebdf15f2c4e 100644 --- a/include/clang/Analysis/AnalysisContext.h +++ b/include/clang/Analysis/AnalysisContext.h @@ -17,6 +17,7 @@ #include "clang/AST/Decl.h" #include "clang/Analysis/CFG.h" +#include "clang/Analysis/CodeInjector.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Allocator.h" @@ -143,6 +144,14 @@ public: /// \sa getBody bool isBodyAutosynthesized() const; + /// \brief Checks if the body of the Decl is generated by the BodyFarm from a + /// model file. + /// + /// Note, the lookup is not free. We are going to call getBody behind + /// the scenes. + /// \sa getBody + bool isBodyAutosynthesizedFromModelFile() const; + CFG *getCFG(); CFGStmtMap *getCFGStmtMap(); @@ -398,6 +407,10 @@ class AnalysisDeclContextManager { ContextMap Contexts; LocationContextManager LocContexts; CFG::BuildOptions cfgBuildOptions; + + /// Pointer to an interface that can provide function bodies for + /// declarations from external source. + std::unique_ptr<CodeInjector> Injector; /// Flag to indicate whether or not bodies should be synthesized /// for well-known functions. @@ -410,7 +423,8 @@ public: bool addTemporaryDtors = false, bool synthesizeBodies = false, bool addStaticInitBranches = false, - bool addCXXNewAllocator = true); + bool addCXXNewAllocator = true, + CodeInjector* injector = nullptr); ~AnalysisDeclContextManager(); diff --git a/include/clang/Analysis/AnalysisDiagnostic.h b/include/clang/Analysis/AnalysisDiagnostic.h index 33c940e7bbf0..8d28971cfe5c 100644 --- a/include/clang/Analysis/AnalysisDiagnostic.h +++ b/include/clang/Analysis/AnalysisDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICANALYSIS_H -#define LLVM_CLANG_DIAGNOSTICANALYSIS_H +#ifndef LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H +#define LLVM_CLANG_ANALYSIS_ANALYSISDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index 891fb90691f3..beea867228d6 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CFG_H -#define LLVM_CLANG_CFG_H +#ifndef LLVM_CLANG_ANALYSIS_CFG_H +#define LLVM_CLANG_ANALYSIS_CFG_H #include "clang/AST/Stmt.h" #include "clang/Analysis/Support/BumpVector.h" @@ -811,10 +811,9 @@ public: ImplTy I; }; - /// buildCFG - Builds a CFG from an AST. The responsibility to free the - /// constructed CFG belongs to the caller. - static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C, - const BuildOptions &BO); + /// buildCFG - Builds a CFG from an AST. + static std::unique_ptr<CFG> buildCFG(const Decl *D, Stmt *AST, ASTContext *C, + const BuildOptions &BO); /// createBlock - Create a new block in the CFG. The CFG owns the block; /// the caller should not directly free it. diff --git a/include/clang/Analysis/CFGStmtMap.h b/include/clang/Analysis/CFGStmtMap.h index 6e8e140afb23..4dfa91df0f42 100644 --- a/include/clang/Analysis/CFGStmtMap.h +++ b/include/clang/Analysis/CFGStmtMap.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CFGSTMTMAP_H -#define LLVM_CLANG_CFGSTMTMAP_H +#ifndef LLVM_CLANG_ANALYSIS_CFGSTMTMAP_H +#define LLVM_CLANG_ANALYSIS_CFGSTMTMAP_H #include "clang/Analysis/CFG.h" diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index 593ba575c78e..eda22a57e8a5 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -14,8 +14,8 @@ // edges to all externally available functions. //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH -#define LLVM_CLANG_ANALYSIS_CALLGRAPH +#ifndef LLVM_CLANG_ANALYSIS_CALLGRAPH_H +#define LLVM_CLANG_ANALYSIS_CALLGRAPH_H #include "clang/AST/DeclBase.h" #include "clang/AST/RecursiveASTVisitor.h" diff --git a/include/clang/Analysis/CodeInjector.h b/include/clang/Analysis/CodeInjector.h new file mode 100644 index 000000000000..413a55b05b07 --- /dev/null +++ b/include/clang/Analysis/CodeInjector.h @@ -0,0 +1,46 @@ +//===-- CodeInjector.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the clang::CodeInjector interface which is responsible for +/// injecting AST of function definitions that may not be available in the +/// original source. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CODEINJECTOR_H +#define LLVM_CLANG_ANALYSIS_CODEINJECTOR_H + +namespace clang { + +class Stmt; +class FunctionDecl; +class ObjCMethodDecl; + +/// \brief CodeInjector is an interface which is responsible for injecting AST +/// of function definitions that may not be available in the original source. +/// +/// The getBody function will be called each time the static analyzer examines a +/// function call that has no definition available in the current translation +/// unit. If the returned statement is not a null pointer, it is assumed to be +/// the body of a function which will be used for the analysis. The source of +/// the body can be arbitrary, but it is advised to use memoization to avoid +/// unnecessary reparsing of the external source that provides the body of the +/// functions. +class CodeInjector { +public: + CodeInjector(); + virtual ~CodeInjector(); + + virtual Stmt *getBody(const FunctionDecl *D) = 0; + virtual Stmt *getBody(const ObjCMethodDecl *D) = 0; +}; +} + +#endif diff --git a/include/clang/Analysis/DomainSpecific/CocoaConventions.h b/include/clang/Analysis/DomainSpecific/CocoaConventions.h index e6a2f13a0b80..8b3fcff52d08 100644 --- a/include/clang/Analysis/DomainSpecific/CocoaConventions.h +++ b/include/clang/Analysis/DomainSpecific/CocoaConventions.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_DS_COCOA -#define LLVM_CLANG_ANALYSIS_DS_COCOA +#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H +#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_COCOACONVENTIONS_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" diff --git a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h index 930c2bd0925b..f9e800a4a412 100644 --- a/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h +++ b/include/clang/Analysis/DomainSpecific/ObjCNoReturn.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN -#define LLVM_CLANG_ANALYSIS_DS_OBJCNORETURN +#ifndef LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H +#define LLVM_CLANG_ANALYSIS_DOMAINSPECIFIC_OBJCNORETURN_H #include "clang/Basic/IdentifierTable.h" diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 57324d042908..f87271550c20 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_PROGRAM_POINT -#define LLVM_CLANG_ANALYSIS_PROGRAM_POINT +#ifndef LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H +#define LLVM_CLANG_ANALYSIS_PROGRAMPOINT_H #include "clang/Analysis/AnalysisContext.h" #include "clang/Analysis/CFG.h" diff --git a/include/clang/Analysis/Support/BumpVector.h b/include/clang/Analysis/Support/BumpVector.h index 6d0427ba92b5..841adf64557d 100644 --- a/include/clang/Analysis/Support/BumpVector.h +++ b/include/clang/Analysis/Support/BumpVector.h @@ -16,8 +16,8 @@ // refactor this core logic into something common that is shared between // the two. The main thing that is different is the allocation strategy. -#ifndef LLVM_CLANG_BUMP_VECTOR -#define LLVM_CLANG_BUMP_VECTOR +#ifndef LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H +#define LLVM_CLANG_ANALYSIS_SUPPORT_BUMPVECTOR_H #include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Allocator.h" @@ -241,4 +241,4 @@ void BumpVector<T>::grow(BumpVectorContext &C, size_t MinSize) { } } // end: clang namespace -#endif // end: LLVM_CLANG_BUMP_VECTOR +#endif diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h index 9e8ef2e3ee8e..bd246792fe24 100644 --- a/include/clang/Basic/ABI.h +++ b/include/clang/Basic/ABI.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef CLANG_BASIC_ABI_H -#define CLANG_BASIC_ABI_H +#ifndef LLVM_CLANG_BASIC_ABI_H +#define LLVM_CLANG_BASIC_ABI_H #include "llvm/Support/DataTypes.h" @@ -24,14 +24,15 @@ namespace clang { enum CXXCtorType { Ctor_Complete, ///< Complete object ctor Ctor_Base, ///< Base object ctor - Ctor_CompleteAllocating ///< Complete object allocating ctor + Ctor_Comdat ///< The COMDAT used for ctors }; /// \brief C++ destructor types. enum CXXDtorType { Dtor_Deleting, ///< Deleting dtor Dtor_Complete, ///< Complete object dtor - Dtor_Base ///< Base object dtor + Dtor_Base, ///< Base object dtor + Dtor_Comdat ///< The COMDAT used for dtors }; /// \brief A return adjustment. @@ -204,4 +205,4 @@ struct ThunkInfo { } // end namespace clang -#endif // CLANG_BASIC_ABI_H +#endif diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 4b1cea50f884..8dd75660c672 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -30,6 +30,7 @@ enum ID { opencl_global = Offset, opencl_local, opencl_constant, + opencl_generic, cuda_device, cuda_constant, diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h index 7304c8f673e6..18a2b8a31871 100644 --- a/include/clang/Basic/AllDiagnostics.h +++ b/include/clang/Basic/AllDiagnostics.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ALL_DIAGNOSTICS_H -#define LLVM_CLANG_ALL_DIAGNOSTICS_H +#ifndef LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H +#define LLVM_CLANG_BASIC_ALLDIAGNOSTICS_H #include "clang/AST/ASTDiagnostic.h" #include "clang/AST/CommentDiagnostic.h" diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 704a375ba291..843746111463 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -115,6 +115,10 @@ def DeclBase : AttrSubject; def FunctionLike : SubsetSubject<DeclBase, [{S->getFunctionType(false) != NULL}]>; +def OpenCLKernelFunction : SubsetSubject<Function, [{ + S->hasAttr<OpenCLKernelAttr>() +}]>; + // HasFunctionProto is a more strict version of FunctionLike, so it should // never be specified in a Subjects list along with FunctionLike (due to the // inclusive nature of subject testing). @@ -186,10 +190,11 @@ class Spelling<string name, string variety> { class GNU<string name> : Spelling<name, "GNU">; class Declspec<string name> : Spelling<name, "Declspec">; -class CXX11<string namespace, string name> : Spelling<name, "CXX11"> { +class CXX11<string namespace, string name, int version = 1> + : Spelling<name, "CXX11"> { string Namespace = namespace; -} -class Keyword<string name> : Spelling<name, "Keyword">; + int Version = version; +} class Keyword<string name> : Spelling<name, "Keyword">; class Pragma<string namespace, string name> : Spelling<name, "Pragma"> { string Namespace = namespace; } @@ -219,12 +224,14 @@ class SubjectList<list<AttrSubject> subjects, SubjectDiag diag = WarnDiag, string CustomDiag = customDiag; } -class LangOpt<string name> { +class LangOpt<string name, bit negated = 0> { string Name = name; + bit Negated = negated; } def MicrosoftExt : LangOpt<"MicrosoftExt">; def Borland : LangOpt<"Borland">; def CUDA : LangOpt<"CUDA">; +def COnly : LangOpt<"CPlusPlus", 1>; // Defines targets for target-specific attributes. The list of strings should // specify architectures for which the target applies, based off the ArchType @@ -354,6 +361,24 @@ def Aligned : InheritableAttr { let Documentation = [Undocumented]; } +def AlignValue : Attr { + let Spellings = [ + // Unfortunately, this is semantically an assertion, not a directive + // (something else must ensure the alignment), so aligned_value is a + // probably a better name. We might want to add an aligned_value spelling in + // the future (and a corresponding C++ attribute), but this can be done + // later once we decide if we also want them to have slightly-different + // semantics than Intel's align_value. + GNU<"align_value"> + // Intel's compiler on Windows also supports: + // , Declspec<"align_value"> + ]; + let Args = [ExprArgument<"Alignment">]; + let Subjects = SubjectList<[Var, TypedefName], WarnDiag, + "ExpectedVariableOrTypedef">; + let Documentation = [AlignValueDocs]; +} + def AlignMac68k : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; @@ -434,7 +459,8 @@ def Bounded : IgnoredAttr { } def CarriesDependency : InheritableParamAttr { - let Spellings = [GNU<"carries_dependency">, CXX11<"","carries_dependency">]; + let Spellings = [GNU<"carries_dependency">, + CXX11<"","carries_dependency", 200809>]; let Subjects = SubjectList<[ParmVar, ObjCMethod, Function], ErrorDiag>; let Documentation = [CarriesDependencyDocs]; } @@ -541,6 +567,13 @@ def CUDAHost : InheritableAttr { let Documentation = [Undocumented]; } +def CUDAInvalidTarget : InheritableAttr { + let Spellings = []; + let Subjects = SubjectList<[Function]>; + let LangOpts = [CUDA]; + let Documentation = [Undocumented]; +} + def CUDALaunchBounds : InheritableAttr { let Spellings = [GNU<"launch_bounds">]; let Args = [IntArgument<"MaxThreads">, DefaultIntArgument<"MinBlocks", 0>]; @@ -568,7 +601,7 @@ def C11NoReturn : InheritableAttr { } def CXX11NoReturn : InheritableAttr { - let Spellings = [CXX11<"","noreturn">]; + let Spellings = [CXX11<"","noreturn", 200809>]; let Subjects = SubjectList<[Function], ErrorDiag>; let Documentation = [CXX11NoReturnDocs]; } @@ -597,27 +630,32 @@ def OpenCLImageAccess : Attr { def OpenCLPrivateAddressSpace : TypeAttr { let Spellings = [Keyword<"__private">, Keyword<"private">]; - let Documentation = [Undocumented]; + let Documentation = [OpenCLAddressSpacePrivateDocs]; } def OpenCLGlobalAddressSpace : TypeAttr { let Spellings = [Keyword<"__global">, Keyword<"global">]; - let Documentation = [Undocumented]; + let Documentation = [OpenCLAddressSpaceGlobalDocs]; } def OpenCLLocalAddressSpace : TypeAttr { let Spellings = [Keyword<"__local">, Keyword<"local">]; - let Documentation = [Undocumented]; + let Documentation = [OpenCLAddressSpaceLocalDocs]; } def OpenCLConstantAddressSpace : TypeAttr { let Spellings = [Keyword<"__constant">, Keyword<"constant">]; - let Documentation = [Undocumented]; + let Documentation = [OpenCLAddressSpaceConstantDocs]; +} + +def OpenCLGenericAddressSpace : TypeAttr { + let Spellings = [Keyword<"__generic">, Keyword<"generic">]; + let Documentation = [OpenCLAddressSpaceGenericDocs]; } def Deprecated : InheritableAttr { let Spellings = [GCC<"deprecated">, Declspec<"deprecated">, - CXX11<"","deprecated">]; + CXX11<"","deprecated", 201309>]; let Args = [StringArgument<"Message", 1>]; let Documentation = [Undocumented]; } @@ -655,7 +693,7 @@ def FastCall : InheritableAttr { let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">, Keyword<"_fastcall">]; // let Subjects = [Function, ObjCMethod]; - let Documentation = [Undocumented]; + let Documentation = [FastCallDocs]; } def Final : InheritableAttr { @@ -671,6 +709,25 @@ def MinSize : InheritableAttr { let Documentation = [Undocumented]; } +def FlagEnum : InheritableAttr { + let Spellings = [GNU<"flag_enum">]; + let Subjects = SubjectList<[Enum]>; + let Documentation = [FlagEnumDocs]; + let LangOpts = [COnly]; + let AdditionalMembers = [{ +private: + llvm::APInt FlagBits; +public: + llvm::APInt &getFlagBits() { + return FlagBits; + } + + const llvm::APInt &getFlagBits() const { + return FlagBits; + } +}]; +} + def Flatten : InheritableAttr { let Spellings = [GCC<"flatten">]; let Subjects = SubjectList<[Function], ErrorDiag>; @@ -754,7 +811,7 @@ def MayAlias : InheritableAttr { def MSABI : InheritableAttr { let Spellings = [GCC<"ms_abi">]; // let Subjects = [Function, ObjCMethod]; - let Documentation = [Undocumented]; + let Documentation = [MSABIDocs]; } def MSP430Interrupt : InheritableAttr, TargetSpecificAttr<TargetMSP430> { @@ -810,7 +867,7 @@ def NoCommon : InheritableAttr { } def NoDebug : InheritableAttr { - let Spellings = [GNU<"nodebug">]; + let Spellings = [GCC<"nodebug">]; let Documentation = [Undocumented]; } @@ -832,6 +889,38 @@ def NoMips16 : InheritableAttr, TargetSpecificAttr<TargetMips> { let Documentation = [Undocumented]; } +// This is not a TargetSpecificAttr so that is silently accepted and +// ignored on other targets as encouraged by the OpenCL spec. +// +// See OpenCL 1.2 6.11.5: "It is our intention that a particular +// implementation of OpenCL be free to ignore all attributes and the +// resulting executable binary will produce the same result." +// +// However, only AMD GPU targets will emit the corresponding IR +// attribute. +// +// FIXME: This provides a sub-optimal error message if you attempt to +// use this in CUDA, since CUDA does not use the same terminology. +def AMDGPUNumVGPR : InheritableAttr { + let Spellings = [GNU<"amdgpu_num_vgpr">]; + let Args = [UnsignedArgument<"NumVGPR">]; + let Documentation = [AMDGPUNumVGPRDocs]; + +// FIXME: This should be for OpenCLKernelFunction, but is not to +// workaround needing to see kernel attribute before others to know if +// this should be rejected on non-kernels. + let Subjects = SubjectList<[Function], ErrorDiag, + "ExpectedKernelFunction">; +} + +def AMDGPUNumSGPR : InheritableAttr { + let Spellings = [GNU<"amdgpu_num_sgpr">]; + let Args = [UnsignedArgument<"NumSGPR">]; + let Documentation = [AMDGPUNumSGPRDocs]; + let Subjects = SubjectList<[Function], ErrorDiag, + "ExpectedKernelFunction">; +} + def NoSplitStack : InheritableAttr { let Spellings = [GCC<"no_split_stack">]; let Subjects = SubjectList<[Function], ErrorDiag>; @@ -845,11 +934,15 @@ def NonNull : InheritableAttr { let Args = [VariadicUnsignedArgument<"Args">]; let AdditionalMembers = [{bool isNonNull(unsigned idx) const { + if (!args_size()) + return true; for (const auto &V : args()) if (V == idx) return true; return false; } }]; + // FIXME: We should merge duplicates into a single nonnull attribute. + let DuplicatesAllowedWhileMerging = 1; let Documentation = [Undocumented]; } @@ -860,6 +953,13 @@ def ReturnsNonNull : InheritableAttr { let Documentation = [Undocumented]; } +def AssumeAligned : InheritableAttr { + let Spellings = [GCC<"assume_aligned">]; + let Subjects = SubjectList<[ObjCMethod, Function]>; + let Args = [ExprArgument<"Alignment">, ExprArgument<"Offset", 1>]; + let Documentation = [AssumeAlignedDocs]; +} + def NoReturn : InheritableAttr { let Spellings = [GCC<"noreturn">, Declspec<"noreturn">]; // FIXME: Does GCC allow this on the function instead? @@ -1068,7 +1168,7 @@ def Pure : InheritableAttr { def Regparm : TypeAttr { let Spellings = [GCC<"regparm">]; let Args = [UnsignedArgument<"NumParams">]; - let Documentation = [Undocumented]; + let Documentation = [RegparmDocs]; } def ReqdWorkGroupSize : InheritableAttr { @@ -1115,7 +1215,7 @@ def Sentinel : InheritableAttr { def StdCall : InheritableAttr { let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">]; // let Subjects = [Function, ObjCMethod]; - let Documentation = [Undocumented]; + let Documentation = [StdCallDocs]; } def SysVABI : InheritableAttr { @@ -1128,7 +1228,14 @@ def ThisCall : InheritableAttr { let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">, Keyword<"_thiscall">]; // let Subjects = [Function, ObjCMethod]; - let Documentation = [Undocumented]; + let Documentation = [ThisCallDocs]; +} + +def VectorCall : InheritableAttr { + let Spellings = [GNU<"vectorcall">, Keyword<"__vectorcall">, + Keyword<"_vectorcall">]; +// let Subjects = [Function, ObjCMethod]; + let Documentation = [VectorCallDocs]; } def Pascal : InheritableAttr { @@ -1784,14 +1891,21 @@ def Unaligned : IgnoredAttr { } def LoopHint : Attr { - /// vectorize: vectorizes loop operations if 'value != 0'. - /// vectorize_width: vectorize loop operations with width 'value'. - /// interleave: interleave multiple loop iterations if 'value != 0'. - /// interleave_count: interleaves 'value' loop interations. - /// unroll: unroll loop if 'value != 0'. - /// unroll_count: unrolls loop 'value' times. - - let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">]; + /// #pragma clang loop <option> directive + /// vectorize: vectorizes loop operations if State == Enable. + /// vectorize_width: vectorize loop operations with width 'Value'. + /// interleave: interleave multiple loop iterations if State == Enable. + /// interleave_count: interleaves 'Value' loop interations. + /// unroll: fully unroll loop if State == Enable. + /// unroll_count: unrolls loop 'Value' times. + + /// #pragma unroll <argument> directive + /// <no arg>: fully unrolls loop. + /// boolean: fully unrolls loop if State == Enable. + /// expression: unrolls loop 'Value' times. + + let Spellings = [Pragma<"clang", "loop">, Pragma<"", "unroll">, + Pragma<"", "nounroll">]; /// State of the loop optimization specified by the spelling. let Args = [EnumArgument<"Option", "OptionType", @@ -1799,10 +1913,13 @@ def LoopHint : Attr { "unroll", "unroll_count"], ["Vectorize", "VectorizeWidth", "Interleave", "InterleaveCount", "Unroll", "UnrollCount"]>, - DefaultIntArgument<"Value", 1>]; + EnumArgument<"State", "LoopHintState", + ["default", "enable", "disable"], + ["Default", "Enable", "Disable"]>, + ExprArgument<"Value">]; let AdditionalMembers = [{ - static StringRef getOptionName(int Option) { + static const char *getOptionName(int Option) { switch(Option) { case Vectorize: return "vectorize"; case VectorizeWidth: return "vectorize_width"; @@ -1814,59 +1931,68 @@ def LoopHint : Attr { llvm_unreachable("Unhandled LoopHint option."); } - static StringRef getValueName(int Value) { - if (Value) - return "enable"; - return "disable"; - } - void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const { unsigned SpellingIndex = getSpellingListIndex(); - if (SpellingIndex == Pragma_unroll) { - // String "unroll" of "#pragma unroll" is already emitted as the - // pragma name. - if (option == UnrollCount) - printArgument(OS); + // For "#pragma unroll" and "#pragma nounroll" the string "unroll" or + // "nounroll" is already emitted as the pragma name. + if (SpellingIndex == Pragma_nounroll) { OS << "\n"; return; } + else if (SpellingIndex == Pragma_unroll) { + OS << getValueString(Policy) << "\n"; + return; + } + assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); - OS << getOptionName(option); - printArgument(OS); - OS << "\n"; + OS << getOptionName(option) << getValueString(Policy) << "\n"; } - // Prints the loop hint argument including the enclosing parentheses to OS. - void printArgument(raw_ostream &OS) const { + // Return a string containing the loop hint argument including the + // enclosing parentheses. + std::string getValueString(const PrintingPolicy &Policy) const { + std::string ValueName; + llvm::raw_string_ostream OS(ValueName); OS << "("; if (option == VectorizeWidth || option == InterleaveCount || option == UnrollCount) - OS << value; - else if (value) - OS << "enable"; + value->printPretty(OS, nullptr, Policy); + else if (state == Default) + return ""; + else if (state == Enable) + OS << (option == Unroll ? "full" : "enable"); else OS << "disable"; OS << ")"; + return OS.str(); } // Return a string suitable for identifying this attribute in diagnostics. - std::string getDiagnosticName() const { - std::string DiagnosticName; - llvm::raw_string_ostream OS(DiagnosticName); + std::string getDiagnosticName(const PrintingPolicy &Policy) const { unsigned SpellingIndex = getSpellingListIndex(); - if (SpellingIndex == Pragma_unroll && option == Unroll) - OS << "#pragma unroll"; - else if (SpellingIndex == Pragma_unroll && option == UnrollCount) { - OS << "#pragma unroll"; - printArgument(OS); - } else { - assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); - OS << getOptionName(option); - printArgument(OS); - } - return OS.str(); + if (SpellingIndex == Pragma_nounroll) + return "#pragma nounroll"; + else if (SpellingIndex == Pragma_unroll) + return "#pragma unroll" + getValueString(Policy); + + assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); + return getOptionName(option) + getValueString(Policy); } }]; let Documentation = [LoopHintDocs, UnrollHintDocs]; } + +def CapturedRecord : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let SemaHandler = 0; + let Documentation = [Undocumented]; +} + +def OMPThreadPrivateDecl : InheritableAttr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let SemaHandler = 0; + let Documentation = [Undocumented]; +} diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index e6d6a33d3b5d..918abb6072ea 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -72,9 +72,9 @@ def ThreadDocs : Documentation { let Content = [{ The ``__declspec(thread)`` attribute declares a variable with thread local storage. It is available under the ``-fms-extensions`` flag for MSVC -compatibility. Documentation for the Visual C++ attribute is available on MSDN_. +compatibility. See the documentation for `__declspec(thread)`_ on MSDN. -.. _MSDN: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx +.. _`__declspec(thread)`: http://msdn.microsoft.com/en-us/library/9w1sdazb.aspx In Clang, ``__declspec(thread)`` is generally equivalent in functionality to the GNU ``__thread`` keyword. The variable must not have a destructor and must have @@ -154,6 +154,30 @@ def ReleaseCapabilityDocs : Documentation { Marks a function as releasing a capability. }]; } + +def AssumeAlignedDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Use ``__attribute__((assume_aligned(<alignment>[,<offset>]))`` on a function +declaration to specify that the return value of the function (which must be a +pointer type) has the specified offset, in bytes, from an address with the +specified alignment. The offset is taken to be zero if omitted. + +.. code-block:: c++ + + // The returned pointer value has 32-byte alignment. + void *a() __attribute__((assume_aligned (32))); + + // The returned pointer value is 4 bytes greater than an address having + // 32-byte alignment. + void *b() __attribute__((assume_aligned (32, 4))); + +Note that this attribute provides information to the compiler regarding a +condition that the code already ensures is true. It does not cause the compiler +to enforce the provided alignment assumption. + }]; +} + def EnableIfDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -649,15 +673,180 @@ The semantics are as follows: }]; } +def DocCatAMDGPURegisterAttributes : + DocumentationCategory<"AMD GPU Register Attributes"> { + let Content = [{ +Clang supports attributes for controlling register usage on AMD GPU +targets. These attributes may be attached to a kernel function +definition and is an optimization hint to the backend for the maximum +number of registers to use. This is useful in cases where register +limited occupancy is known to be an important factor for the +performance for the kernel. + +The semantics are as follows: + +- The backend will attempt to limit the number of used registers to + the specified value, but the exact number used is not + guaranteed. The number used may be rounded up to satisfy the + allocation requirements or ABI constraints of the subtarget. For + example, on Southern Islands VGPRs may only be allocated in + increments of 4, so requesting a limit of 39 VGPRs will really + attempt to use up to 40. Requesting more registers than the + subtarget supports will truncate to the maximum allowed. The backend + may also use fewer registers than requested whenever possible. + +- 0 implies the default no limit on register usage. + +- Ignored on older VLIW subtargets which did not have separate scalar + and vector registers, R600 through Northern Islands. + +}]; +} + + +def AMDGPUNumVGPRDocs : Documentation { + let Category = DocCatAMDGPURegisterAttributes; + let Content = [{ +Clang supports the +``__attribute__((amdgpu_num_vgpr(<num_registers>)))`` attribute on AMD +Southern Islands GPUs and later for controlling the number of vector +registers. A typical value would be between 4 and 256 in increments +of 4. +}]; +} + +def AMDGPUNumSGPRDocs : Documentation { + let Category = DocCatAMDGPURegisterAttributes; + let Content = [{ + +Clang supports the +``__attribute__((amdgpu_num_sgpr(<num_registers>)))`` attribute on AMD +Southern Islands GPUs and later for controlling the number of scalar +registers. A typical value would be between 8 and 104 in increments of +8. + +Due to common instruction constraints, an additional 2-4 SGPRs are +typically required for internal use depending on features used. This +value is a hint for the total number of SGPRs to use, and not the +number of user SGPRs, so no special consideration needs to be given +for these. +}]; +} + +def DocCatCallingConvs : DocumentationCategory<"Calling Conventions"> { + let Content = [{ +Clang supports several different calling conventions, depending on the target +platform and architecture. The calling convention used for a function determines +how parameters are passed, how results are returned to the caller, and other +low-level details of calling a function. + }]; +} + def PcsDocs : Documentation { - let Category = DocCatFunction; + let Category = DocCatCallingConvs; let Content = [{ -On ARM targets, this can attribute can be used to select calling conventions, +On ARM targets, this attribute can be used to select calling conventions similar to ``stdcall`` on x86. Valid parameter values are "aapcs" and "aapcs-vfp". }]; } +def RegparmDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On 32-bit x86 targets, the regparm attribute causes the compiler to pass +the first three integer parameters in EAX, EDX, and ECX instead of on the +stack. This attribute has no effect on variadic functions, and all parameters +are passed via the stack as normal. + }]; +} + +def SysVABIDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On Windows x86_64 targets, this attribute changes the calling convention of a +function to match the default convention used on Sys V targets such as Linux, +Mac, and BSD. This attribute has no effect on other targets. + }]; +} + +def MSABIDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On non-Windows x86_64 targets, this attribute changes the calling convention of +a function to match the default convention used on Windows x86_64. This +attribute has no effect on Windows targets or non-x86_64 targets. + }]; +} + +def StdCallDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On 32-bit x86 targets, this attribute changes the calling convention of a +function to clear parameters off of the stack on return. This convention does +not support variadic calls or unprototyped functions in C, and has no effect on +x86_64 targets. This calling convention is used widely by the Windows API and +COM applications. See the documentation for `__stdcall`_ on MSDN. + +.. _`__stdcall`: http://msdn.microsoft.com/en-us/library/zxk0tw93.aspx + }]; +} + +def FastCallDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX and EDX as register parameters and clear parameters off of +the stack on return. This convention does not support variadic calls or +unprototyped functions in C, and has no effect on x86_64 targets. This calling +convention is supported primarily for compatibility with existing code. Users +seeking register parameters should use the ``regparm`` attribute, which does +not require callee-cleanup. See the documentation for `__fastcall`_ on MSDN. + +.. _`__fastcall`: http://msdn.microsoft.com/en-us/library/6xa169sk.aspx + }]; +} + +def ThisCallDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On 32-bit x86 targets, this attribute changes the calling convention of a +function to use ECX for the first parameter (typically the implicit ``this`` +parameter of C++ methods) and clear parameters off of the stack on return. This +convention does not support variadic calls or unprototyped functions in C, and +has no effect on x86_64 targets. See the documentation for `__thiscall`_ on +MSDN. + +.. _`__thiscall`: http://msdn.microsoft.com/en-us/library/ek8tkfbw.aspx + }]; +} + +def VectorCallDocs : Documentation { + let Category = DocCatCallingConvs; + let Content = [{ +On 32-bit x86 *and* x86_64 targets, this attribute changes the calling +convention of a function to pass vector parameters in SSE registers. + +On 32-bit x86 targets, this calling convention is similar to ``__fastcall``. +The first two integer parameters are passed in ECX and EDX. Subsequent integer +parameters are passed in memory, and callee clears the stack. On x86_64 +targets, the callee does *not* clear the stack, and integer parameters are +passed in RCX, RDX, R8, and R9 as is done for the default Windows x64 calling +convention. + +On both 32-bit x86 and x86_64 targets, vector and floating point arguments are +passed in XMM0-XMM5. Homogenous vector aggregates of up to four elements are +passed in sequential SSE registers if enough are available. If AVX is enabled, +256 bit vectors are passed in YMM0-YMM5. Any vector or aggregate type that +cannot be passed in registers for any reason is passed by reference, which +allows the caller to align the parameter memory. + +See the documentation for `__vectorcall`_ on MSDN for more details. + +.. _`__vectorcall`: http://msdn.microsoft.com/en-us/library/dn375768.aspx + }]; +} + def DocCatConsumed : DocumentationCategory<"Consumed Annotation Checking"> { let Content = [{ Clang supports additional attributes for checking basic resource management @@ -987,6 +1176,36 @@ Clang implements two kinds of checks with this attribute. }]; } +def AlignValueDocs : Documentation { + let Category = DocCatType; + let Content = [{ +The align_value attribute can be added to the typedef of a pointer type or the +declaration of a variable of pointer or reference type. It specifies that the +pointer will point to, or the reference will bind to, only objects with at +least the provided alignment. This alignment value must be some positive power +of 2. + + .. code-block:: c + + typedef double * aligned_double_ptr __attribute__((align_value(64))); + void foo(double & x __attribute__((align_value(128)), + aligned_double_ptr y) { ... } + +If the pointer value does not have the specified alignment at runtime, the +behavior of the program is undefined. + }]; +} + +def FlagEnumDocs : Documentation { + let Category = DocCatType; + let Content = [{ +This attribute can be added to an enumerator to signal to the compiler that it +is intended to be used as a flag type. This will cause the compiler to assume +that the range of the type includes all of the values that you can get by +manipulating bits of the enumerator when issuing warnings. + }]; +} + def MSInheritanceDocs : Documentation { let Category = DocCatType; let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance"; @@ -1045,12 +1264,14 @@ entire application without optimization. Avoiding optimization on the specified function can improve the quality of the debugging information for that function. -This attribute is incompatible with the ``always_inline`` attribute. +This attribute is incompatible with the ``always_inline`` and ``minsize`` +attributes. }]; } def LoopHintDocs : Documentation { let Category = DocCatStmt; + let Heading = "#pragma clang loop"; let Content = [{ The ``#pragma clang loop`` directive allows loop optimization hints to be specified for the subsequent loop. The directive allows vectorization, @@ -1064,10 +1285,11 @@ for details. def UnrollHintDocs : Documentation { let Category = DocCatStmt; + let Heading = "#pragma unroll, #pragma nounroll"; let Content = [{ -Loop unrolling optimization hints can be specified with ``#pragma unroll``. The -pragma is placed immediately before a for, while, do-while, or c++11 range-based -for loop. +Loop unrolling optimization hints can be specified with ``#pragma unroll`` and +``#pragma nounroll``. The pragma is placed immediately before a for, while, +do-while, or c++11 range-based for loop. Specifying ``#pragma unroll`` without a parameter directs the loop unroller to attempt to fully unroll the loop if the trip count is known at compile time: @@ -1095,11 +1317,107 @@ enclosed in parentheses: ... } +Specifying ``#pragma nounroll`` indicates that the loop should not be unrolled: + +.. code-block:: c++ + + #pragma nounroll + for (...) { + ... + } + ``#pragma unroll`` and ``#pragma unroll _value_`` have identical semantics to -``#pragma clang loop unroll(enable)`` and ``#pragma clang loop -unroll_count(_value_)`` respectively. See `language extensions +``#pragma clang loop unroll(full)`` and +``#pragma clang loop unroll_count(_value_)`` respectively. ``#pragma nounroll`` +is equivalent to ``#pragma clang loop unroll(disable)``. See +`language extensions <http://clang.llvm.org/docs/LanguageExtensions.html#extensions-for-loop-hint-optimizations>`_ for further details including limitations of the unroll hints. }]; } +def DocOpenCLAddressSpaces : DocumentationCategory<"OpenCL Address Spaces"> { + let Content = [{ +The address space qualifier may be used to specify the region of memory that is +used to allocate the object. OpenCL supports the following address spaces: +__generic(generic), __global(global), __local(local), __private(private), +__constant(constant). + + .. code-block:: c + + __constant int c = ...; + + __generic int* foo(global int* g) { + __local int* l; + private int p; + ... + return l; + } + +More details can be found in the OpenCL C language Spec v2.0, Section 6.5. + }]; +} + +def OpenCLAddressSpaceGenericDocs : Documentation { + let Category = DocOpenCLAddressSpaces; + let Heading = "__generic(generic)"; + let Content = [{ +The generic address space attribute is only available with OpenCL v2.0 and later. +It can be used with pointer types. Variables in global and local scope and +function parameters in non-kernel functions can have the generic address space +type attribute. It is intended to be a placeholder for any other address space +except for '__constant' in OpenCL code which can be used with multiple address +spaces. + }]; +} + +def OpenCLAddressSpaceConstantDocs : Documentation { + let Category = DocOpenCLAddressSpaces; + let Heading = "__constant(constant)"; + let Content = [{ +The constant address space attribute signals that an object is located in +a constant (non-modifiable) memory region. It is available to all work items. +Any type can be annotated with the constant address space attribute. Objects +with the constant address space qualifier can be declared in any scope and must +have an initializer. + }]; +} + +def OpenCLAddressSpaceGlobalDocs : Documentation { + let Category = DocOpenCLAddressSpaces; + let Heading = "__global(global)"; + let Content = [{ +The global address space attribute specifies that an object is allocated in +global memory, which is accessible by all work items. The content stored in this +memory area persists between kernel executions. Pointer types to the global +address space are allowed as function parameters or local variables. Starting +with OpenCL v2.0, the global address space can be used with global (program +scope) variables and static local variable as well. + }]; +} + +def OpenCLAddressSpaceLocalDocs : Documentation { + let Category = DocOpenCLAddressSpaces; + let Heading = "__local(local)"; + let Content = [{ +The local address space specifies that an object is allocated in the local (work +group) memory area, which is accessible to all work items in the same work +group. The content stored in this memory region is not accessible after +the kernel execution ends. In a kernel function scope, any variable can be in +the local address space. In other scopes, only pointer types to the local address +space are allowed. Local address space variables cannot have an initializer. + }]; +} + +def OpenCLAddressSpacePrivateDocs : Documentation { + let Category = DocOpenCLAddressSpaces; + let Heading = "__private(private)"; + let Content = [{ +The private address space specifies that an object is allocated in the private +(work item) memory. Other work items cannot access the same memory area and its +content is destroyed after work item execution ends. Local variables can be +declared in the private address space. Function arguments are always in the +private address space. Kernel function arguments of a pointer or an array type +cannot point to the private address space. + }]; +} diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h index 150a30e73d3f..f0b0a6445d40 100644 --- a/include/clang/Basic/AttrKinds.h +++ b/include/clang/Basic/AttrKinds.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ATTRKINDS_H -#define LLVM_CLANG_ATTRKINDS_H +#ifndef LLVM_CLANG_BASIC_ATTRKINDS_H +#define LLVM_CLANG_BASIC_ATTRKINDS_H namespace clang { diff --git a/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h index 5783b3bff510..a64dd5666b73 100644 --- a/include/clang/Basic/Attributes.h +++ b/include/clang/Basic/Attributes.h @@ -10,16 +10,14 @@ #ifndef LLVM_CLANG_BASIC_ATTRIBUTES_H #define LLVM_CLANG_BASIC_ATTRIBUTES_H -#include "llvm/ADT/Triple.h" #include "clang/Basic/LangOptions.h" +#include "llvm/ADT/Triple.h" namespace clang { class IdentifierInfo; enum class AttrSyntax { - /// Is the attribute identifier generally known for any syntax? - Generic, /// Is the identifier known as a GNU-style attribute? GNU, /// Is the identifier known as a __declspec-style attribute? @@ -30,11 +28,11 @@ enum class AttrSyntax { Pragma }; -/// \brief Return true if we recognize and implement the attribute specified by -/// the given information. -bool hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, - const IdentifierInfo *Attr, const llvm::Triple &T, - const LangOptions &LangOpts); +/// \brief Return the version number associated with the attribute if we +/// recognize and implement the attribute specified by the given information. +int hasAttribute(AttrSyntax Syntax, const IdentifierInfo *Scope, + const IdentifierInfo *Attr, const llvm::Triple &T, + const LangOptions &LangOpts); } // end namespace clang diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index e705382e11ca..098f5dacacbd 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -412,6 +412,7 @@ BUILTIN(__builtin_va_start, "vA.", "nt") BUILTIN(__builtin_va_end, "vA", "n") BUILTIN(__builtin_va_copy, "vAA", "n") BUILTIN(__builtin_stdarg_start, "vA.", "n") +BUILTIN(__builtin_assume_aligned, "v*vC*z.", "nc") BUILTIN(__builtin_bcmp, "iv*v*z", "n") BUILTIN(__builtin_bcopy, "vv*v*z", "n") BUILTIN(__builtin_bzero, "vv*z", "nF") @@ -496,6 +497,7 @@ BUILTIN(__builtin_unreachable, "v", "nr") BUILTIN(__builtin_shufflevector, "v." , "nc") BUILTIN(__builtin_convertvector, "v." , "nct") BUILTIN(__builtin_alloca, "v*z" , "n") +BUILTIN(__builtin_call_with_static_chain, "v.", "nt") // "Overloaded" Atomic operator builtins. These are overloaded to support data // types of i8, i16, i32, i64, and i128. The front-end sees calls to the @@ -540,6 +542,12 @@ BUILTIN(__sync_fetch_and_xor_4, "iiD*i.", "tn") BUILTIN(__sync_fetch_and_xor_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_fetch_and_xor_16, "LLLiLLLiD*LLLi.", "tn") +BUILTIN(__sync_fetch_and_nand, "v.", "t") +BUILTIN(__sync_fetch_and_nand_1, "ccD*c.", "tn") +BUILTIN(__sync_fetch_and_nand_2, "ssD*s.", "tn") +BUILTIN(__sync_fetch_and_nand_4, "iiD*i.", "tn") +BUILTIN(__sync_fetch_and_nand_8, "LLiLLiD*LLi.", "tn") +BUILTIN(__sync_fetch_and_nand_16, "LLLiLLLiD*LLLi.", "tn") BUILTIN(__sync_add_and_fetch, "v.", "t") BUILTIN(__sync_add_and_fetch_1, "ccD*c.", "tn") @@ -576,6 +584,13 @@ BUILTIN(__sync_xor_and_fetch_4, "iiD*i.", "tn") BUILTIN(__sync_xor_and_fetch_8, "LLiLLiD*LLi.", "tn") BUILTIN(__sync_xor_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") +BUILTIN(__sync_nand_and_fetch, "v.", "t") +BUILTIN(__sync_nand_and_fetch_1, "ccD*c.", "tn") +BUILTIN(__sync_nand_and_fetch_2, "ssD*s.", "tn") +BUILTIN(__sync_nand_and_fetch_4, "iiD*i.", "tn") +BUILTIN(__sync_nand_and_fetch_8, "LLiLLiD*LLi.", "tn") +BUILTIN(__sync_nand_and_fetch_16, "LLLiLLLiD*LLLi.", "tn") + BUILTIN(__sync_bool_compare_and_swap, "v.", "t") BUILTIN(__sync_bool_compare_and_swap_1, "bcD*cc.", "tn") BUILTIN(__sync_bool_compare_and_swap_2, "bsD*ss.", "tn") @@ -689,6 +704,7 @@ LANGBUILTIN(_InterlockedDecrement, "LiLiD*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangeAdd, "LiLiD*Li", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchangePointer, "v*v*D*v*", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedExchange, "LiLiD*Li", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__readfsdword, "ULiULi", "n", ALL_MS_LANGUAGES) // C99 library functions // C99 stdlib.h @@ -1173,6 +1189,9 @@ LIBBUILTIN(_Block_object_dispose, "vvC*iC", "f", "Blocks.h", ALL_LANGUAGES) // Annotation function BUILTIN(__builtin_annotation, "v.", "tn") +// Invariants +BUILTIN(__builtin_assume, "vb", "n") + // Multiprecision Arithmetic Builtins. BUILTIN(__builtin_addcb, "UcUcCUcCUcCUc*", "n") BUILTIN(__builtin_addcs, "UsUsCUsCUsCUs*", "n") diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index f9d30e40560a..3ce2255c8646 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -29,7 +29,7 @@ namespace clang { class ASTContext; class QualType; class LangOptions; - + enum LanguageID { GNU_LANG = 0x1, // builtin requires GNU mode. C_LANG = 0x2, // builtin for c only. @@ -40,7 +40,7 @@ namespace clang { ALL_GNU_LANGUAGES = ALL_LANGUAGES | GNU_LANG, // builtin requires GNU mode. ALL_MS_LANGUAGES = ALL_LANGUAGES | MS_LANG // builtin requires MS mode. }; - + namespace Builtin { enum ID { NotBuiltin = 0, // This is not a builtin function. diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def index 695ecf9da5f8..9d223c3e8516 100644 --- a/include/clang/Basic/BuiltinsAArch64.def +++ b/include/clang/Basic/BuiltinsAArch64.def @@ -50,4 +50,7 @@ BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") BUILTIN(__builtin_arm_isb, "vUi", "nc") +// Prefetch +BUILTIN(__builtin_arm_prefetch, "vvC*UiUiUiUi", "nc") + #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsARM.def b/include/clang/Basic/BuiltinsARM.def index 2e5eac694fc2..9091ad4d7581 100644 --- a/include/clang/Basic/BuiltinsARM.def +++ b/include/clang/Basic/BuiltinsARM.def @@ -74,13 +74,19 @@ BUILTIN(__builtin_arm_wfe, "v", "") BUILTIN(__builtin_arm_wfi, "v", "") BUILTIN(__builtin_arm_sev, "v", "") BUILTIN(__builtin_arm_sevl, "v", "") +BUILTIN(__builtin_arm_dbg, "vUi", "") // Data barrier BUILTIN(__builtin_arm_dmb, "vUi", "nc") BUILTIN(__builtin_arm_dsb, "vUi", "nc") BUILTIN(__builtin_arm_isb, "vUi", "nc") +// Prefetch +BUILTIN(__builtin_arm_prefetch, "vvC*UiUi", "nc") + // MSVC +LANGBUILTIN(__emit, "vIUiC", "", ALL_MS_LANGUAGES) + LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) diff --git a/include/clang/Basic/BuiltinsLe64.def b/include/clang/Basic/BuiltinsLe64.def new file mode 100644 index 000000000000..532860603c29 --- /dev/null +++ b/include/clang/Basic/BuiltinsLe64.def @@ -0,0 +1,19 @@ +//==- BuiltinsLe64.def - Le64 Builtin function 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 defines the Le64-specific builtin function database. Users of this +// file must define the BUILTIN macro to make use of this information. +// +//===----------------------------------------------------------------------===// + +// The format of this database matches clang/Basic/Builtins.def. + +BUILTIN(__clear_cache, "vv*v*", "i") + +#undef BUILTIN diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index 7e9b5eea8325..9c920dce5cab 100644 --- a/include/clang/Basic/BuiltinsNVPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def @@ -139,8 +139,8 @@ BUILTIN(__nvvm_brev64, "ULLiULLi", "") // Sad -BUILTIN(__nvvm_sad_i, "iii", "") -BUILTIN(__nvvm_sad_ui, "UiUiUi", "") +BUILTIN(__nvvm_sad_i, "iiii", "") +BUILTIN(__nvvm_sad_ui, "UiUiUiUi", "") // Floor, Ceil @@ -255,19 +255,19 @@ BUILTIN(__nvvm_rsqrt_approx_d, "dd", "") // Add -BUILTIN(__nvvm_add_rn_ftz_f, "ff", "") -BUILTIN(__nvvm_add_rn_f, "ff", "") -BUILTIN(__nvvm_add_rz_ftz_f, "ff", "") -BUILTIN(__nvvm_add_rz_f, "ff", "") -BUILTIN(__nvvm_add_rm_ftz_f, "ff", "") -BUILTIN(__nvvm_add_rm_f, "ff", "") -BUILTIN(__nvvm_add_rp_ftz_f, "ff", "") -BUILTIN(__nvvm_add_rp_f, "ff", "") - -BUILTIN(__nvvm_add_rn_d, "dd", "") -BUILTIN(__nvvm_add_rz_d, "dd", "") -BUILTIN(__nvvm_add_rm_d, "dd", "") -BUILTIN(__nvvm_add_rp_d, "dd", "") +BUILTIN(__nvvm_add_rn_ftz_f, "fff", "") +BUILTIN(__nvvm_add_rn_f, "fff", "") +BUILTIN(__nvvm_add_rz_ftz_f, "fff", "") +BUILTIN(__nvvm_add_rz_f, "fff", "") +BUILTIN(__nvvm_add_rm_ftz_f, "fff", "") +BUILTIN(__nvvm_add_rm_f, "fff", "") +BUILTIN(__nvvm_add_rp_ftz_f, "fff", "") +BUILTIN(__nvvm_add_rp_f, "fff", "") + +BUILTIN(__nvvm_add_rn_d, "ddd", "") +BUILTIN(__nvvm_add_rz_d, "ddd", "") +BUILTIN(__nvvm_add_rm_d, "ddd", "") +BUILTIN(__nvvm_add_rp_d, "ddd", "") // Convert diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index 8a751e4ce846..e42af4244160 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -204,6 +204,25 @@ BUILTIN(__builtin_altivec_vcmpgtsw_p, "iiV4SiV4Si", "") BUILTIN(__builtin_altivec_vcmpgtuw_p, "iiV4UiV4Ui", "") BUILTIN(__builtin_altivec_vcmpgtfp_p, "iiV4fV4f", "") +// VSX built-ins. + +BUILTIN(__builtin_vsx_lxvd2x, "V2divC*", "") +BUILTIN(__builtin_vsx_lxvw4x, "V4iivC*", "") + +BUILTIN(__builtin_vsx_stxvd2x, "vV2div*", "") +BUILTIN(__builtin_vsx_stxvw4x, "vV4iiv*", "") + +BUILTIN(__builtin_vsx_xvmaxdp, "V2dV2dV2d", "") +BUILTIN(__builtin_vsx_xvmaxsp, "V4fV4fV4f", "") +BUILTIN(__builtin_vsx_xsmaxdp, "ddd", "") + +BUILTIN(__builtin_vsx_xvmindp, "V2dV2dV2d", "") +BUILTIN(__builtin_vsx_xvminsp, "V4fV4fV4f", "") +BUILTIN(__builtin_vsx_xsmindp, "ddd", "") + +BUILTIN(__builtin_vsx_xvdivdp, "V2dV2dV2d", "") +BUILTIN(__builtin_vsx_xvdivsp, "V4fV4fV4f", "") + // FIXME: Obviously incomplete. #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsR600.def b/include/clang/Basic/BuiltinsR600.def index 49135ccb056d..84fc4fae4eab 100644 --- a/include/clang/Basic/BuiltinsR600.def +++ b/include/clang/Basic/BuiltinsR600.def @@ -16,8 +16,8 @@ BUILTIN(__builtin_amdgpu_div_scale, "dddbb*", "n") BUILTIN(__builtin_amdgpu_div_scalef, "fffbb*", "n") -BUILTIN(__builtin_amdgpu_div_fmas, "dddd", "nc") -BUILTIN(__builtin_amdgpu_div_fmasf, "ffff", "nc") +BUILTIN(__builtin_amdgpu_div_fmas, "ddddb", "nc") +BUILTIN(__builtin_amdgpu_div_fmasf, "ffffb", "nc") BUILTIN(__builtin_amdgpu_div_fixup, "dddd", "nc") BUILTIN(__builtin_amdgpu_div_fixupf, "ffff", "nc") BUILTIN(__builtin_amdgpu_trig_preop, "ddi", "nc") @@ -28,5 +28,9 @@ BUILTIN(__builtin_amdgpu_rsq, "dd", "nc") BUILTIN(__builtin_amdgpu_rsqf, "ff", "nc") BUILTIN(__builtin_amdgpu_rsq_clamped, "dd", "nc") BUILTIN(__builtin_amdgpu_rsq_clampedf, "ff", "nc") +BUILTIN(__builtin_amdgpu_ldexp, "ddi", "nc") +BUILTIN(__builtin_amdgpu_ldexpf, "ffi", "nc") +BUILTIN(__builtin_amdgpu_class, "bdi", "nc") +BUILTIN(__builtin_amdgpu_classf, "bfi", "nc") #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 1f377a8ab1de..eb6803b141b7 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -187,13 +187,45 @@ BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "") BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "") BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "") BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "") +BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "") +BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "") +BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "") BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "") +BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "") +BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "") +BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "") BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "") @@ -303,12 +335,12 @@ BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "") BUILTIN(__builtin_ia32_mwait, "vUiUi", "") BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "") BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIc", "") -BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fi", "") +BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "") BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "") -BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "") -BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "") -BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "") +BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIc", "") +BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIc", "") +BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIc", "") BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "") BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "") @@ -339,13 +371,13 @@ BUILTIN(__builtin_ia32_roundps, "V4fV4fi", "") BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fi", "") BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2di", "") BUILTIN(__builtin_ia32_roundpd, "V2dV2di", "") -BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fi", "") -BUILTIN(__builtin_ia32_dppd, "V2dV2dV2di", "") +BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "") +BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "") BUILTIN(__builtin_ia32_movntdqa, "V2LLiV2LLi*", "") BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "") BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "") BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "") -BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16ci", "") +BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "") BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "") // SSE 4.2 @@ -404,13 +436,13 @@ BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "") BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "") BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "") BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "") -BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "") -BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "") +BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIc", "") +BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIc", "") BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "") BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "") -BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIi", "") -BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dc", "") -BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fc", "") +BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "") +BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "") +BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "") BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIc", "") BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIc", "") BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIc", "") @@ -472,7 +504,7 @@ BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4dV4d", "") BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8fV8f", "") // AVX2 -BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32ci", "") +BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "") BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "") BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "") BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "") @@ -492,7 +524,7 @@ BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIc", "") BUILTIN(__builtin_ia32_pavgb256, "V32cV32cV32c", "") BUILTIN(__builtin_ia32_pavgw256, "V16sV16sV16s", "") BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "") -BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "") +BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIc", "") BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "") BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "") BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "") @@ -559,8 +591,8 @@ BUILTIN(__builtin_ia32_vbroadcastss_ps, "V4fV4f", "") BUILTIN(__builtin_ia32_vbroadcastss_ps256, "V8fV4f", "") BUILTIN(__builtin_ia32_vbroadcastsd_pd256, "V4dV2d", "") BUILTIN(__builtin_ia32_vbroadcastsi256, "V4LLiV2LLi", "") -BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "") -BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "") +BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIc", "") +BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIc", "") BUILTIN(__builtin_ia32_pbroadcastb256, "V32cV16c", "") BUILTIN(__builtin_ia32_pbroadcastw256, "V16sV8s", "") BUILTIN(__builtin_ia32_pbroadcastd256, "V8iV4i", "") @@ -615,14 +647,34 @@ BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iV4iC*V4LLiV4iIc", "") // F16C BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "") BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "") +BUILTIN(__builtin_ia32_vcvtps2ph512, "V16sV16fIi", "") BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "") BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "") +BUILTIN(__builtin_ia32_vcvtph2ps512, "V16fV16s", "") // RDRAND BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "") BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "") BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "") +// FSGSBASE +BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "") +BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "") +BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "") +BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "") +BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "") +BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "") +BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "") +BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "") + +// ADX +BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "") +BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "") +BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "") +BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "") +BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "") +BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "") + // RDSEED BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "") BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "") @@ -653,7 +705,7 @@ BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "") BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "") BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "") -// FMA4 +// FMA BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "") BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "") BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "") @@ -686,6 +738,12 @@ BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "") BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "") BUILTIN(__builtin_ia32_vfmsubaddps256, "V8fV8fV8fV8f", "") BUILTIN(__builtin_ia32_vfmsubaddpd256, "V4dV4dV4dV4d", "") +BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUci", "") +BUILTIN(__builtin_ia32_vfmsubpd512_mask, "V8dV8dV8dV8dUci", "") +BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUci", "") +BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsi", "") +BUILTIN(__builtin_ia32_vfmsubps512_mask, "V16fV16fV16fV16fUsi", "") +BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsi", "") // XOP BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "") @@ -761,4 +819,119 @@ BUILTIN(__builtin_ia32_rdpmc, "ULLii", "") BUILTIN(__builtin_ia32_rdtsc, "ULLi", "") BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "") +// AVX-512 +BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUciC", "") +BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsiC", "") +BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "") +BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "") +BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "") +BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "") +BUILTIN(__builtin_ia32_rsqrt28sd_mask, "V2dV2dV2dV2dUciC", "") +BUILTIN(__builtin_ia32_rsqrt28ss_mask, "V4fV4fV4fV4fUciC", "") +BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUciC", "") +BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsiC", "") +BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "") +BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "") +BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "") +BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "") +BUILTIN(__builtin_ia32_rcp28sd_mask, "V2dV2dV2dV2dUciC", "") +BUILTIN(__builtin_ia32_rcp28ss_mask, "V4fV4fV4fV4fUciC", "") +BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUciC", "") +BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsiC", "") +BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsiC", "") +BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsiC", "") +BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUciC", "") +BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUciC", "") +BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fiCUsi", "") +BUILTIN(__builtin_ia32_pcmpeqb512_mask, "LLiV64cV64cLLi", "") +BUILTIN(__builtin_ia32_pcmpeqd512_mask, "sV16iV16is", "") +BUILTIN(__builtin_ia32_pcmpeqq512_mask, "cV8LLiV8LLic", "") +BUILTIN(__builtin_ia32_pcmpeqw512_mask, "iV32sV32si", "") +BUILTIN(__builtin_ia32_pcmpeqb256_mask, "iV32cV32ci", "") +BUILTIN(__builtin_ia32_pcmpeqd256_mask, "cV8iV8ic", "") +BUILTIN(__builtin_ia32_pcmpeqq256_mask, "cV4LLiV4LLic", "") +BUILTIN(__builtin_ia32_pcmpeqw256_mask, "sV16sV16ss", "") +BUILTIN(__builtin_ia32_pcmpeqb128_mask, "sV16cV16cs", "") +BUILTIN(__builtin_ia32_pcmpeqd128_mask, "cV4iV4ic", "") +BUILTIN(__builtin_ia32_pcmpeqq128_mask, "cV2LLiV2LLic", "") +BUILTIN(__builtin_ia32_pcmpeqw128_mask, "cV8sV8sc", "") +BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8diCUci", "") +BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fiCV16fUsiC", "") +BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8diCV8dUciC", "") +BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsiC", "") +BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUciC", "") +BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsiC", "") +BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUciC", "") +BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsiC", "") +BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUciC", "") +BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsiC", "") +BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUciC", "") +BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsiC", "") +BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsiC", "") +BUILTIN(__builtin_ia32_cvtdq2pd512_mask, "V8dV8iV8dUc", "") +BUILTIN(__builtin_ia32_cvtudq2pd512_mask, "V8dV8iV8dUc", "") +BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUciC", "") +BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fiCV16sUs", "") +BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsiC", "") +BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pmuldq512_mask, "V8LLiV16iV16iV8LLiUc", "") +BUILTIN(__builtin_ia32_pmuludq512_mask, "V8LLiV16iV16iV8LLiUc", "") +BUILTIN(__builtin_ia32_blendmd_512_mask, "V16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_blendmq_512_mask, "V8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_blendmps_512_mask, "V16fV16fV16fUs", "") +BUILTIN(__builtin_ia32_blendmpd_512_mask, "V8dV8dV8dUc", "") +BUILTIN(__builtin_ia32_ptestmd512, "UsV16iV16iUs", "") +BUILTIN(__builtin_ia32_ptestmq512, "UcV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pbroadcastd512_gpr_mask, "V16iiV16iUs", "") +BUILTIN(__builtin_ia32_pbroadcastq512_gpr_mask, "V8LLiLLiV8LLiUc", "") +BUILTIN(__builtin_ia32_pbroadcastq512_mem_mask, "V8LLiLLiV8LLiUc", "") +BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16ivC*V16iUs", "") +BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLivC*V8LLiUc", "") +BUILTIN(__builtin_ia32_loadups512_mask, "V16fvC*V16fUs", "") +BUILTIN(__builtin_ia32_loadupd512_mask, "V8dvC*V8dUc", "") +BUILTIN(__builtin_ia32_storedqudi512_mask, "vv*V8LLiUc", "") +BUILTIN(__builtin_ia32_storedqusi512_mask, "vv*V16iUs", "") +BUILTIN(__builtin_ia32_storeupd512_mask, "vv*V8dUc", "") +BUILTIN(__builtin_ia32_storeups512_mask, "vv*V16fUs", "") +BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "") +BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "") +BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "") +BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "") +BUILTIN(__builtin_ia32_alignq512_mask, "V8LLiV8LLiV8LLiUcV8LLiUc", "") +BUILTIN(__builtin_ia32_alignd512_mask, "V16iV16iV16iUcV16iUc", "") +BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8dvC*V8iUciC", "") +BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16fvC*UsiC", "") +BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8dvC*V8LLiUciC", "") +BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8fvC*V8LLiUciC", "") +BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLivC*V8iUciC", "") +BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16ivC*UsiC", "") +BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLivC*V8LLiUciC", "") +BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8ivC*V8LLiUciC", "") +BUILTIN(__builtin_ia32_scattersiv8df, "vv*UcV8iV8diC", "") +BUILTIN(__builtin_ia32_scattersiv16sf, "vv*UsV16iV16fiC", "") +BUILTIN(__builtin_ia32_scatterdiv8df, "vv*UcV8LLiV8diC", "") +BUILTIN(__builtin_ia32_scatterdiv16sf, "vv*UcV8LLiV8fiC", "") +BUILTIN(__builtin_ia32_scattersiv8di, "vv*UcV8iV8LLiiC", "") +BUILTIN(__builtin_ia32_scattersiv16si, "vv*UsV16iV16iiC", "") +BUILTIN(__builtin_ia32_scatterdiv8di, "vv*UcV8LLiV8LLiiC", "") +BUILTIN(__builtin_ia32_scatterdiv16si, "vv*UcV8LLiV8iiC", "") +BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8ivC*iCiC", "") +BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16ivC*iCiC", "") +BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLivC*iCiC", "") +BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLivC*iCiC", "") +BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iv*iCiC", "") +BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16iv*iCiC", "") +BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiv*iCiC", "") +BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLiv*iCiC", "") +BUILTIN(__builtin_ia32_knothi, "UsUs", "") + #undef BUILTIN diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h index d0afda43709a..dd9c55431e01 100644 --- a/include/clang/Basic/CharInfo.h +++ b/include/clang/Basic/CharInfo.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_BASIC_CHARINFO_H -#define CLANG_BASIC_CHARINFO_H +#ifndef LLVM_CLANG_BASIC_CHARINFO_H +#define LLVM_CLANG_BASIC_CHARINFO_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" diff --git a/include/clang/Basic/CommentOptions.h b/include/clang/Basic/CommentOptions.h index 7991875838a4..92419f91b741 100644 --- a/include/clang/Basic/CommentOptions.h +++ b/include/clang/Basic/CommentOptions.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_COMMENTOPTIONS_H -#define LLVM_CLANG_COMMENTOPTIONS_H +#ifndef LLVM_CLANG_BASIC_COMMENTOPTIONS_H +#define LLVM_CLANG_BASIC_COMMENTOPTIONS_H #include <string> #include <vector> diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index a7b2ba270d46..91e94db802b1 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTIC_H -#define LLVM_CLANG_DIAGNOSTIC_H +#ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H +#define LLVM_CLANG_BASIC_DIAGNOSTIC_H #include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/DiagnosticOptions.h" @@ -187,7 +187,7 @@ private: IntrusiveRefCntPtr<DiagnosticIDs> Diags; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; DiagnosticConsumer *Client; - bool OwnsDiagClient; + std::unique_ptr<DiagnosticConsumer> Owner; SourceManager *SourceMgr; /// \brief Mapping information for diagnostics. @@ -302,7 +302,6 @@ private: unsigned NumWarnings; ///< Number of warnings reported unsigned NumErrors; ///< Number of errors reported - unsigned NumErrorsSuppressed; ///< Number of errors suppressed /// \brief A function pointer that converts an opaque diagnostic /// argument to a strings. @@ -369,14 +368,11 @@ public: const DiagnosticConsumer *getClient() const { return Client; } /// \brief Determine whether this \c DiagnosticsEngine object own its client. - bool ownsClient() const { return OwnsDiagClient; } - + bool ownsClient() const { return Owner != nullptr; } + /// \brief Return the current diagnostic client along with ownership of that /// client. - DiagnosticConsumer *takeClient() { - OwnsDiagClient = false; - return Client; - } + std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); } bool hasSourceManager() const { return SourceMgr != nullptr; } SourceManager &getSourceManager() const { diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index 8d5a1c77233b..d353b451aaa7 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -141,6 +141,13 @@ def note_constexpr_calls_suppressed : Note< "(skipping %0 call%s0 in backtrace; use -fconstexpr-backtrace-limit=0 to " "see all)">; def note_constexpr_call_here : Note<"in call to '%0'">; +def note_constexpr_baa_insufficient_alignment : Note< + "%select{alignment of|offset of the aligned pointer from}0 the base pointee " + "object (%1 %plural{1:byte|:bytes}1) is %select{less than|not a multiple of}0 the " + "asserted %2 %plural{1:byte|:bytes}2">; +def note_constexpr_baa_value_insufficient_alignment : Note< + "value of the aligned pointer (%0) is not a multiple of the asserted %1 " + "%plural{1:byte|:bytes}1">; def warn_integer_constant_overflow : Warning< "overflow in expression; result is %0 with type %1">, diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index b3c77b8f5f36..ff9ed69022ec 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -81,6 +81,8 @@ def err_deleted_non_function : Error< "only functions can have deleted definitions">; def err_module_not_found : Error<"module '%0' not found">, DefaultFatal; def err_module_not_built : Error<"could not build module '%0'">, DefaultFatal; +def err_module_lock_failure : Error< + "could not acquire lock file for module '%0'">, DefaultFatal; def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, DefaultFatal; def note_pragma_entered_here : Note<"#pragma entered here">; @@ -102,10 +104,12 @@ def ext_cxx11_longlong : Extension< def warn_cxx98_compat_longlong : Warning< "'long long' is incompatible with C++98">, InGroup<CXX98CompatPedantic>, DefaultIgnore; -def err_integer_too_large : Error< - "integer constant is larger than the largest unsigned integer type">; -def ext_integer_too_large_for_signed : ExtWarn< - "integer constant is larger than the largest signed integer type">, +def err_integer_literal_too_large : Error< + "integer literal is too large to be represented in any %select{signed |}0" + "integer type">; +def ext_integer_literal_too_large_for_signed : ExtWarn< + "integer literal is too large to be represented in a signed integer type, " + "interpreting as unsigned">, InGroup<DiagGroup<"implicitly-unsigned-literal">>; // Sema && AST @@ -121,6 +125,8 @@ def err_target_unknown_abi : Error<"unknown target ABI '%0'">; def err_target_unknown_fpmath : Error<"unknown FP unit '%0'">; def err_target_unsupported_fpmath : Error< "the '%0' unit is not supported with this instruction set">; +def err_target_unsupported_unaligned : Error< + "the %0 sub-architecture does not support unaligned accesses">; // Source manager def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index cd26a6a4dd70..41c78ee669dc 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -22,6 +22,8 @@ def err_drv_unknown_stdin_type_clang_cl : Error< def err_drv_unknown_language : Error<"language not recognized: '%0'">; def err_drv_invalid_arch_name : Error< "invalid arch name '%0'">; +def err_drv_invalid_thread_model_for_target : Error< + "invalid thread model '%0' in '%1' for this target">; def err_drv_invalid_linker_name : Error< "invalid linker name in argument '%0'">; def err_drv_invalid_rtlib_name : Error< @@ -100,10 +102,6 @@ def err_drv_cc_print_options_failure : Error< "unable to open CC_PRINT_OPTIONS file: %0">; def err_drv_preamble_format : Error< "incorrect format for -preamble-bytes=N,END">; -def err_drv_conflicting_deployment_targets : Error< - "conflicting deployment targets, both '%0' and '%1' are present in environment">; -def err_drv_invalid_arch_for_deployment_target : Error< - "invalid architecture '%0' for deployment target '%1'">; def err_drv_objc_gc_arr : Error< "cannot specify both '-fobjc-arc' and '%0'">; def err_arc_unsupported_on_runtime : Error< @@ -124,7 +122,7 @@ def warn_O4_is_O3 : Warning<"-O4 is equivalent to -O3">, InGroup<Deprecated>; def warn_drv_optimization_value : Warning<"optimization level '%0' is not supported; using '%1%2' instead">, InGroup<InvalidCommandLineArgument>; def warn_ignored_gcc_optimization : Warning<"optimization flag '%0' is not supported">, - InGroup<InvalidCommandLineArgument>; + InGroup<IgnoredOptimizationArgument>; def warn_c_kext : Warning< "ignoring -fapple-kext which is valid for C++ and Objective-C++ only">; def warn_drv_input_file_unused : Warning< @@ -165,9 +163,11 @@ def warn_debug_compression_unavailable : Warning<"cannot compress debug sections def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; -def note_drv_t_option_is_global : - Note<"The last /TC or /TP option takes precedence over earlier instances">; - +def note_drv_t_option_is_global : Note< + "The last /TC or /TP option takes precedence over earlier instances">; +def note_drv_address_sanitizer_debug_runtime : Note< + "AddressSanitizer doesn't support linking with debug runtime libraries yet">; + def err_analyzer_config_no_value : Error< "analyzer-config option '%0' has a key but no value">; def err_analyzer_config_multiple_values : Error< @@ -175,7 +175,7 @@ def err_analyzer_config_multiple_values : Error< def err_drv_modules_validate_once_requires_timestamp : Error< "option '-fmodules-validate-once-per-build-session' requires " - "'-fbuild-session-timestamp=<seconds since Epoch>'">; + "'-fbuild-session-timestamp=<seconds since Epoch>' or '-fbuild-session-file=<file>'">; def warn_drv_invoking_fallback : Warning<"falling back to %0">, InGroup<Fallback>; diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index ae704c49150b..15f74b11698f 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -46,6 +46,16 @@ def warn_fe_backend_optimization_failure : Warning<"%0">, BackendInfo, def note_fe_backend_optimization_remark_invalid_loc : Note<"could " "not determine the original source location for %0:%1:%2">; +def remark_sanitize_address_insert_extra_padding_accepted : Remark< + "-fsanitize-address-field-padding applied to %0">, ShowInSystemHeader, + InGroup<SanitizeAddressRemarks>; +def remark_sanitize_address_insert_extra_padding_rejected : Remark< + "-fsanitize-address-field-padding ignored for %0 because it " + "%select{is not C++|is packed|is a union|is trivially copyable|" + "has trivial destructor|is standard layout|is in a blacklisted file|" + "is blacklisted}1">, ShowInSystemHeader, + InGroup<SanitizeAddressRemarks>; + def err_fe_invalid_code_complete_file : Error< "cannot locate code-completion file %0">, DefaultFatal; def err_fe_stdout_binary : Error<"unable to change standard output to binary">, @@ -85,9 +95,12 @@ def err_fe_no_pch_in_dir : Error< def err_fe_action_not_available : Error< "action %0 not compiled in">; +def warn_fe_serialized_diag_merge_failure : Warning< + "unable to merge a subprocess's serialized diagnostics">, + InGroup<SerializedDiagnostics>; def warn_fe_serialized_diag_failure : Warning< "unable to open file %0 for serializing diagnostics (%1)">, - InGroup<DiagGroup<"serialized-diagnostics">>; + InGroup<SerializedDiagnostics>; def err_verify_missing_line : Error< "missing or invalid line number following '@' in expected %0">; @@ -135,12 +148,15 @@ def warn_unknown_warning_specifier : Warning< def err_unknown_analyzer_checker : Error< "no analyzer checkers are associated with '%0'">; +def note_suggest_disabling_all_checkers : Note< + "use -analyzer-disable-all-checks to disable all static analyzer checkers">; + def warn_incompatible_analyzer_plugin_api : Warning< "checker plugin '%0' is not compatible with this version of the analyzer">, InGroup<DiagGroup<"analyzer-incompatible-plugin"> >; def note_incompatible_analyzer_plugin_api : Note< "current API version is '%0', but plugin was compiled with version '%1'">; - + def err_module_map_not_found : Error<"module map file '%0' not found">, DefaultFatal; def err_missing_module_name : Error< @@ -167,7 +183,19 @@ def warn_module_config_macro_undef : Warning< def note_module_def_undef_here : Note< "macro was %select{defined|#undef'd}0 here">; def remark_module_build : Remark<"building module '%0' as '%1'">, - InGroup<DiagGroup<"module-build">>; + InGroup<ModuleBuild>; +def remark_module_build_done : Remark<"finished building module '%0'">, + InGroup<ModuleBuild>; + +def err_conflicting_module_names : Error< + "conflicting module names specified: '-fmodule-name=%0' and " + "'-fmodule-implementation-of %1'">; +def err_conflicting_module_files : Error< + "module '%0' is defined in both '%1' and '%2'">; +def err_module_file_not_found : Error< + "file '%0' is not a precompiled module file">, DefaultFatal; +def err_module_file_not_module : Error< + "AST file '%0' was not built as a module">, DefaultFatal; def err_missing_vfs_overlay_file : Error< "virtual filesystem overlay file '%0' not found">, DefaultFatal; diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index 58dee482b627..75d40b17a67c 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -60,7 +60,7 @@ def ExternCCompat : DiagGroup<"extern-c-compat">; def KeywordCompat : DiagGroup<"keyword-compat">; def GNUCaseRange : DiagGroup<"gnu-case-range">; def CastAlign : DiagGroup<"cast-align">; -def : DiagGroup<"cast-qual">; +def CastQual : DiagGroup<"cast-qual">; def : DiagGroup<"char-align">; def Comment : DiagGroup<"comment">; def GNUComplexInteger : DiagGroup<"gnu-complex-integer">; @@ -71,6 +71,7 @@ def GNUDesignator : DiagGroup<"gnu-designator">; def GNUStringLiteralOperatorTemplate : DiagGroup<"gnu-string-literal-operator-template">; +def DeleteIncomplete : DiagGroup<"delete-incomplete">; def DeleteNonVirtualDtor : DiagGroup<"delete-non-virtual-dtor">; def AbstractFinalClass : DiagGroup<"abstract-final-class">; @@ -118,9 +119,9 @@ def FormatExtraArgs : DiagGroup<"format-extra-args">; def FormatZeroLength : DiagGroup<"format-zero-length">; // Warnings for C++1y code which is not compatible with prior C++ standards. -def CXXPre1yCompat : DiagGroup<"c++98-c++11-compat">; -def CXXPre1yCompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic", - [CXXPre1yCompat]>; +def CXXPre14Compat : DiagGroup<"c++98-c++11-compat">; +def CXXPre14CompatPedantic : DiagGroup<"c++98-c++11-compat-pedantic", + [CXXPre14Compat]>; def CXXPre1zCompat : DiagGroup<"c++98-c++11-c++14-compat">; def CXXPre1zCompatPedantic : DiagGroup<"c++98-c++11-c++14-compat-pedantic", [CXXPre1zCompat]>; @@ -133,19 +134,21 @@ def CXX98CompatUnnamedTypeTemplateArgs : DiagGroup<"c++98-compat-unnamed-type-template-args">; def CXX98Compat : DiagGroup<"c++98-compat", - [CXX98CompatBindToTemporaryCopy, - CXX98CompatLocalTypeTemplateArgs, + [CXX98CompatLocalTypeTemplateArgs, CXX98CompatUnnamedTypeTemplateArgs, - CXXPre1yCompat, + CXXPre14Compat, CXXPre1zCompat]>; // Warnings for C++11 features which are Extensions in C++98 mode. def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat, - CXXPre1yCompatPedantic, + CXX98CompatBindToTemporaryCopy, + CXXPre14CompatPedantic, CXXPre1zCompatPedantic]>; def CXX11Narrowing : DiagGroup<"c++11-narrowing">; +def CXX11WarnOverrideMethod : DiagGroup<"inconsistent-missing-override">; + // Original name of this warning in Clang def : DiagGroup<"c++0x-narrowing", [CXX11Narrowing]>; @@ -162,11 +165,11 @@ def CXX11Compat : DiagGroup<"c++11-compat", [CXX11Narrowing, CXX11CompatReservedUserDefinedLiteral, CXX11CompatDeprecatedWritableStr, - CXXPre1yCompat, + CXXPre14Compat, CXXPre1zCompat]>; def : DiagGroup<"c++0x-compat", [CXX11Compat]>; def CXX11CompatPedantic : DiagGroup<"c++11-compat-pedantic", - [CXXPre1yCompatPedantic, + [CXXPre14CompatPedantic, CXXPre1zCompatPedantic]>; def CXX14Compat : DiagGroup<"c++14-compat", [CXXPre1zCompat]>; @@ -187,6 +190,7 @@ def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; +def FlagEnum : DiagGroup<"flag-enum">; def InfiniteRecursion : DiagGroup<"infinite-recursion">; def GNUImaginaryConstant : DiagGroup<"gnu-imaginary-constant">; def IgnoredQualifiers : DiagGroup<"ignored-qualifiers">; @@ -198,11 +202,13 @@ def IncompatiblePointerTypes : DiagGroup<"incompatible-pointer-types", [IncompatiblePointerTypesDiscardsQualifiers]>; def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; -def IncompleteModule : DiagGroup<"incomplete-module", [IncompleteUmbrella]>; def NonModularIncludeInFrameworkModule : DiagGroup<"non-modular-include-in-framework-module">; def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module", [NonModularIncludeInFrameworkModule]>; +def IncompleteModule : DiagGroup<"incomplete-module", + [IncompleteUmbrella, NonModularIncludeInModule]>; + def InvalidNoreturn : DiagGroup<"invalid-noreturn">; def InvalidSourceEncoding : DiagGroup<"invalid-source-encoding">; def KNRPromotedParameter : DiagGroup<"knr-promoted-parameter">; @@ -231,6 +237,7 @@ def MismatchedParameterTypes : DiagGroup<"mismatched-parameter-types">; def MismatchedReturnTypes : DiagGroup<"mismatched-return-types">; def MismatchedTags : DiagGroup<"mismatched-tags">; def MissingFieldInitializers : DiagGroup<"missing-field-initializers">; +def ModuleBuild : DiagGroup<"module-build">; def ModuleConflict : DiagGroup<"module-conflict">; def NewlineEOF : DiagGroup<"newline-eof">; def NullArithmetic : DiagGroup<"null-arithmetic">; @@ -267,7 +274,9 @@ def ObjCInvalidIBOutletProperty : DiagGroup<"invalid-iboutlet">; def ObjCRootClass : DiagGroup<"objc-root-class">; def ObjCPointerIntrospectPerformSelector : DiagGroup<"deprecated-objc-pointer-introspection-performSelector">; def ObjCPointerIntrospect : DiagGroup<"deprecated-objc-pointer-introspection", [ObjCPointerIntrospectPerformSelector]>; +def ObjCMultipleMethodNames : DiagGroup<"objc-multiple-method-names">; def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; +def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; def PointerArith : DiagGroup<"pointer-arith">; @@ -285,6 +294,7 @@ def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", [CXX98CompatBindToTemporaryCopy]>; def SelfAssignmentField : DiagGroup<"self-assign-field">; def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>; +def SelfMove : DiagGroup<"self-move">; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def Sentinel : DiagGroup<"sentinel">; def MissingMethodReturnType : DiagGroup<"missing-method-return-type">; @@ -329,6 +339,8 @@ def : DiagGroup<"sequence-point", [Unsequenced]>; // Preprocessor warnings. def AmbiguousMacro : DiagGroup<"ambiguous-macro">; +def KeywordAsMacro : DiagGroup<"keyword-macro">; +def ReservedIdAsMacro : DiagGroup<"reserved-id-macro">; // Just silence warnings about -Wstrict-aliasing for now. def : DiagGroup<"strict-aliasing=0">; @@ -349,6 +361,7 @@ def InvalidOffsetof : DiagGroup<"invalid-offsetof">; def : DiagGroup<"strict-prototypes">; def StrictSelector : DiagGroup<"strict-selector-match">; def MethodDuplicate : DiagGroup<"duplicate-method-match">; +def ObjCCStringFormat : DiagGroup<"cstring-format-directive">; def CoveredSwitchDefault : DiagGroup<"covered-switch-default">; def SwitchBool : DiagGroup<"switch-bool">; def SwitchEnum : DiagGroup<"switch-enum">; @@ -383,7 +396,9 @@ def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", def UnsupportedFriend : DiagGroup<"unsupported-friend">; def UnusedArgument : DiagGroup<"unused-argument">; def UnusedCommandLineArgument : DiagGroup<"unused-command-line-argument">; -def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument">; +def IgnoredOptimizationArgument : DiagGroup<"ignored-optimization-argument">; +def InvalidCommandLineArgument : DiagGroup<"invalid-command-line-argument", + [IgnoredOptimizationArgument]>; def UnusedComparison : DiagGroup<"unused-comparison">; def UnusedExceptionParameter : DiagGroup<"unused-exception-parameter">; def UnneededInternalDecl : DiagGroup<"unneeded-internal-declaration">; @@ -395,11 +410,17 @@ def UnusedMemberFunction : DiagGroup<"unused-member-function", def UnusedLabel : DiagGroup<"unused-label">; def UnusedParameter : DiagGroup<"unused-parameter">; def UnusedResult : DiagGroup<"unused-result">; -def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult]>; +def PotentiallyEvaluatedExpression : DiagGroup<"potentially-evaluated-expression">; +def UnevaluatedExpression : DiagGroup<"unevaluated-expression", + [PotentiallyEvaluatedExpression]>; +def UnusedValue : DiagGroup<"unused-value", [UnusedComparison, UnusedResult, + UnevaluatedExpression]>; def UnusedConstVariable : DiagGroup<"unused-const-variable">; def UnusedVariable : DiagGroup<"unused-variable", [UnusedConstVariable]>; +def UnusedLocalTypedef : DiagGroup<"unused-local-typedef">; def UnusedPropertyIvar : DiagGroup<"unused-property-ivar">; +def UnusedGetterReturnValue : DiagGroup<"unused-getter-return-value">; def UsedButMarkedUnused : DiagGroup<"used-but-marked-unused">; def UserDefinedLiterals : DiagGroup<"user-defined-literals">; def Reorder : DiagGroup<"reorder">; @@ -408,8 +429,6 @@ def ImplicitAtomic : DiagGroup<"implicit-atomic-properties">; def CustomAtomic : DiagGroup<"custom-atomic-properties">; def AtomicProperties : DiagGroup<"atomic-properties", [ImplicitAtomic, CustomAtomic]>; -// FIXME: Remove arc-abi once an Xcode is released that doesn't pass this flag. -def : DiagGroup<"arc-abi">; def ARCUnsafeRetainedAssign : DiagGroup<"arc-unsafe-retained-assign">; def ARCRetainCycles : DiagGroup<"arc-retain-cycles">; def ARCNonPodMemAccess : DiagGroup<"arc-non-pod-memaccess">; @@ -426,6 +445,9 @@ def DeallocInCategory:DiagGroup<"dealloc-in-category">; def SelectorTypeMismatch : DiagGroup<"selector-type-mismatch">; def Selector : DiagGroup<"selector", [SelectorTypeMismatch]>; def Protocol : DiagGroup<"protocol">; +def AtProtocol : DiagGroup<"at-protocol">; +def PropertyAccessDotSyntax: DiagGroup<"property-access-dot-syntax">; +def PropertyAttr : DiagGroup<"property-attribute-mismatch">; def SuperSubClassMismatch : DiagGroup<"super-class-method-mismatch">; def OverridingMethodMismatch : DiagGroup<"overriding-method-mismatch">; def VariadicMacros : DiagGroup<"variadic-macros">; @@ -520,7 +542,7 @@ def Unused : DiagGroup<"unused", [UnusedArgument, UnusedFunction, UnusedLabel, // UnusedParameter, (matches GCC's behavior) // UnusedMemberFunction, (clean-up llvm before enabling) - UnusedPrivateField, + UnusedPrivateField, UnusedLocalTypedef, UnusedValue, UnusedVariable, UnusedPropertyIvar]>, DiagCategory<"Unused Entity Issue">; @@ -565,6 +587,7 @@ def Most : DiagGroup<"most", [ Reorder, ReturnType, SelfAssignment, + SelfMove, SizeofArrayArgument, SizeofArrayDecay, StringPlusInt, @@ -585,10 +608,14 @@ def Most : DiagGroup<"most", [ def ThreadSafetyAttributes : DiagGroup<"thread-safety-attributes">; def ThreadSafetyAnalysis : DiagGroup<"thread-safety-analysis">; def ThreadSafetyPrecise : DiagGroup<"thread-safety-precise">; +def ThreadSafetyReference : DiagGroup<"thread-safety-reference">; +def ThreadSafetyNegative : DiagGroup<"thread-safety-negative">; def ThreadSafety : DiagGroup<"thread-safety", [ThreadSafetyAttributes, ThreadSafetyAnalysis, - ThreadSafetyPrecise]>; + ThreadSafetyPrecise, + ThreadSafetyReference]>; +def ThreadSafetyVerbose : DiagGroup<"thread-safety-verbose">; def ThreadSafetyBeta : DiagGroup<"thread-safety-beta">; // Uniqueness Analysis warnings @@ -614,6 +641,8 @@ def : DiagGroup<"int-conversions", [IntConversion]>; // -Wint-conversions = -Wint-conversion def : DiagGroup<"vector-conversions", [VectorConversion]>; // -Wvector-conversions = -Wvector-conversion +def : DiagGroup<"unused-local-typedefs", [UnusedLocalTypedef]>; + // -Wunused-local-typedefs = -Wunused-local-typedef // A warning group for warnings that we want to have on by default in clang, // but which aren't on by default in GCC. @@ -624,15 +653,17 @@ def NonGCC : DiagGroup<"non-gcc", // earlier C++ versions. def CXX11 : DiagGroup<"c++11-extensions", [CXX11ExtraSemi, CXX11LongLong]>; -// A warning group for warnings about using C++1y features as extensions in +// A warning group for warnings about using C++14 features as extensions in // earlier C++ versions. -def CXX1y : DiagGroup<"c++1y-extensions">; +def CXX14 : DiagGroup<"c++14-extensions">; // A warning group for warnings about using C++1z features as extensions in // earlier C++ versions. def CXX1z : DiagGroup<"c++1z-extensions">; def : DiagGroup<"c++0x-extensions", [CXX11]>; +def : DiagGroup<"c++1y-extensions", [CXX14]>; + def DelegatingCtorCycles : DiagGroup<"delegating-ctor-cycles">; @@ -710,6 +741,12 @@ def BackendOptimizationFailure : DiagGroup<"pass-failed">; def ProfileInstrOutOfDate : DiagGroup<"profile-instr-out-of-date">; def ProfileInstrUnprofiled : DiagGroup<"profile-instr-unprofiled">; +// AddressSanitizer frontent instrumentation remarks. +def SanitizeAddressRemarks : DiagGroup<"sanitize-address">; + +// Issues with serialized diagnostics. +def SerializedDiagnostics : DiagGroup<"serialized-diagnostics">; + // A warning group for warnings about code that clang accepts when // compiling CUDA C/C++ but which is not compatible with the CUDA spec. def CudaCompat : DiagGroup<"cuda-compat">; diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index bfb0f0d1ee5d..99b469d70e78 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICIDS_H -#define LLVM_CLANG_DIAGNOSTICIDS_H +#ifndef LLVM_CLANG_BASIC_DIAGNOSTICIDS_H +#define LLVM_CLANG_BASIC_DIAGNOSTICIDS_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -33,7 +33,7 @@ namespace clang { DIAG_START_SERIALIZATION = DIAG_START_FRONTEND + 100, DIAG_START_LEX = DIAG_START_SERIALIZATION + 120, DIAG_START_PARSE = DIAG_START_LEX + 300, - DIAG_START_AST = DIAG_START_PARSE + 400, + DIAG_START_AST = DIAG_START_PARSE + 500, DIAG_START_COMMENT = DIAG_START_AST + 100, DIAG_START_SEMA = DIAG_START_COMMENT + 100, DIAG_START_ANALYSIS = DIAG_START_SEMA + 3000, diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index 86def878834f..93cc7c297813 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -161,8 +161,8 @@ def err_invalid_suffix_integer_constant : Error< def err_invalid_suffix_float_constant : Error< "invalid suffix '%0' on floating constant">; def warn_cxx11_compat_digit_separator : Warning< - "digit separators are incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompat>, DefaultIgnore; + "digit separators are incompatible with C++ standards before C++14">, + InGroup<CXXPre14Compat>, DefaultIgnore; def err_digit_separator_not_between_digits : Error< "digit separator cannot appear at %select{start|end}0 of digit sequence">; def warn_extraneous_char_constant : Warning< @@ -182,11 +182,11 @@ def ext_hexconstant_invalid : Extension< "hexadecimal floating constants are a C99 feature">, InGroup<C99>; def ext_binary_literal : Extension< "binary integer literals are a GNU extension">, InGroup<GNUBinaryLiteral>; -def ext_binary_literal_cxx1y : Extension< - "binary integer literals are a C++1y extension">, InGroup<CXX1y>; +def ext_binary_literal_cxx14 : Extension< + "binary integer literals are a C++14 extension">, InGroup<CXX14>; def warn_cxx11_compat_binary_literal : Warning< - "binary integer literals are incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompatPedantic>, DefaultIgnore; + "binary integer literals are incompatible with C++ standards before C++14">, + InGroup<CXXPre14CompatPedantic>, DefaultIgnore; def err_pascal_string_too_long : Error<"Pascal string is too long">; def err_octal_escape_too_large : Error<"octal escape sequence out of range">; def err_hex_escape_too_large : Error<"hex escape sequence out of range">; @@ -201,6 +201,9 @@ def warn_c99_compat_unicode_literal : Warning< def warn_cxx98_compat_unicode_literal : Warning< "unicode literals are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx14_compat_u8_character_literal : Warning< + "unicode literals are incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; def warn_cxx11_compat_user_defined_literal : Warning< "identifier after literal will be treated as a user-defined literal suffix " "in C++11">, InGroup<CXX11Compat>, DefaultIgnore; @@ -287,6 +290,11 @@ def note_pp_ambiguous_macro_chosen : Note< "expanding this definition of %0">; def note_pp_ambiguous_macro_other : Note< "other definition of %0">; +def warn_pp_macro_hides_keyword : Extension< + "keyword is hidden by macro definition">, InGroup<KeywordAsMacro>; +def warn_pp_macro_is_reserved_id : Warning< + "macro name is a reserved identifier">, DefaultIgnore, + InGroup<ReservedIdAsMacro>; def pp_invalid_string_literal : Warning< "invalid string literal, ignoring final '\\'">; @@ -324,7 +332,7 @@ def warn_cxx98_compat_variadic_macro : Warning< InGroup<CXX98CompatPedantic>, DefaultIgnore; def ext_named_variadic_macro : Extension< "named variadic macros are a GNU extension">, InGroup<VariadicMacros>; -def err_embedded_include : Error< +def err_embedded_directive : Error< "embedding a #%0 directive within macro arguments is not supported">; def ext_embedded_directive : Extension< "embedding a directive within macro arguments has undefined behavior">, @@ -615,9 +623,6 @@ def warn_auto_module_import : Warning< def warn_uncovered_module_header : Warning< "umbrella header for module '%0' does not include header '%1'">, InGroup<IncompleteUmbrella>; -def warn_forgotten_module_header : Warning< - "header '%0' is included in module '%1' but not listed in module map">, - InGroup<IncompleteModule>, DefaultIgnore; def err_expected_id_building_module : Error< "expected a module name in '__building_module' expression">; def error_use_of_private_header_outside_module : Error< diff --git a/include/clang/Basic/DiagnosticOptions.def b/include/clang/Basic/DiagnosticOptions.def index a360a5a84e98..fdd325446e27 100644 --- a/include/clang/Basic/DiagnosticOptions.def +++ b/include/clang/Basic/DiagnosticOptions.def @@ -81,6 +81,8 @@ VALUE_DIAGOPT(MacroBacktraceLimit, 32, DefaultMacroBacktraceLimit) VALUE_DIAGOPT(TemplateBacktraceLimit, 32, DefaultTemplateBacktraceLimit) /// Limit depth of constexpr backtrace. VALUE_DIAGOPT(ConstexprBacktraceLimit, 32, DefaultConstexprBacktraceLimit) +/// Limit number of times to perform spell checking. +VALUE_DIAGOPT(SpellCheckingLimit, 32, DefaultSpellCheckingLimit) VALUE_DIAGOPT(TabStop, 32, DefaultTabStop) /// The distance between tab stops. /// Column limit for formatting message diagnostics, or 0 if unused. @@ -92,4 +94,3 @@ VALUE_DIAGOPT(MessageLength, 32, 0) #undef SEMANTIC_DIAGOPT #undef SEMANTIC_ENUM_DIAGOPT #undef SEMANTIC_VALUE_DIAGOPT - diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h index 3e4d0eefbcf9..058e00f73e77 100644 --- a/include/clang/Basic/DiagnosticOptions.h +++ b/include/clang/Basic/DiagnosticOptions.h @@ -33,7 +33,8 @@ public: enum { DefaultTabStop = 8, MaxTabStop = 100, DefaultMacroBacktraceLimit = 6, DefaultTemplateBacktraceLimit = 10, - DefaultConstexprBacktraceLimit = 10 }; + DefaultConstexprBacktraceLimit = 10, + DefaultSpellCheckingLimit = 50 }; // Define simple diagnostic options (with no accessors). #define DIAGOPT(Name, Bits, Default) unsigned Name : Bits; diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index b1305e182f0b..239d4d20bb72 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -108,6 +108,9 @@ def ext_alignof_expr : ExtWarn< def warn_microsoft_dependent_exists : Warning< "dependent %select{__if_not_exists|__if_exists}0 declarations are ignored">, InGroup<DiagGroup<"microsoft-exists">>; +def warn_microsoft_qualifiers_ignored : Warning< + "qualifiers after comma in declarator list are ignored">, + InGroup<IgnoredAttributes>; def ext_c11_generic_selection : Extension< "generic selections are a C11-specific feature">, InGroup<C11>; @@ -121,11 +124,15 @@ def ext_c11_alignment : Extension< def ext_c11_noreturn : Extension< "_Noreturn functions are a C11-specific feature">, InGroup<C11>; +def err_c11_noreturn_misplaced : Error< + "'_Noreturn' keyword must precede function declarator">; def ext_gnu_indirect_goto : Extension< "use of GNU indirect-goto extension">, InGroup<GNULabelsAsValue>; def ext_gnu_address_of_label : Extension< "use of GNU address-of-label extension">, InGroup<GNULabelsAsValue>; +def err_stmtexpr_file_scope : Error< + "statement expression not allowed at file scope">; def ext_gnu_statement_expr : Extension< "use of GNU statement expression extension">, InGroup<GNUStatementExpression>; def ext_gnu_conditional_expr : Extension< @@ -167,6 +174,9 @@ def err_expected_fn_body : Error< def warn_attribute_on_function_definition : Warning< "GCC does not allow %0 attribute in this position on a function definition">, InGroup<GccCompat>; +def warn_gcc_attribute_location : Warning< + "GCC does not allow an attribute in this position on a function declaration">, + InGroup<GccCompat>; def warn_attribute_no_decl : Warning< "attribute %0 ignored, because it is not attached to a declaration">, InGroup<IgnoredAttributes>; @@ -194,11 +204,19 @@ def err_expected_semi_after_namespace_name : Error< "expected ';' after namespace name">; def err_unexpected_namespace_attributes_alias : Error< "attributes cannot be specified on namespace alias">; +def err_unexpected_nested_namespace_attribute : Error< + "attributes cannot be specified on a nested namespace definition">; def err_inline_namespace_alias : Error<"namespace alias cannot be inline">; def err_namespace_nonnamespace_scope : Error< "namespaces can only be defined in global or namespace scope">; -def err_nested_namespaces_with_double_colon : Error< - "nested namespace definition must define each namespace separately">; +def ext_nested_namespace_definition : ExtWarn< + "nested namespace definition is a C++1z extension; " + "define each namespace separately">, InGroup<CXX1z>; +def warn_cxx14_compat_nested_namespace_definition : Warning< + "nested namespace definition is incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; +def err_inline_nested_namespace_definition : Error< + "nested namespace definition cannot be 'inline'">; def err_expected_semi_after_attribute_list : Error< "expected ';' after attribute list">; def err_expected_semi_after_static_assert : Error< @@ -268,22 +286,17 @@ def ext_auto_storage_class : ExtWarn< "'auto' storage class specifier is not permitted in C++11, and will not " "be supported in future releases">, InGroup<DiagGroup<"auto-storage-class">>; def ext_decltype_auto_type_specifier : ExtWarn< - "'decltype(auto)' type specifier is a C++1y extension">, InGroup<CXX1y>; + "'decltype(auto)' type specifier is a C++14 extension">, InGroup<CXX14>; def warn_cxx11_compat_decltype_auto_type_specifier : Warning< "'decltype(auto)' type specifier is incompatible with C++ standards before " - "C++1y">, InGroup<CXXPre1yCompat>, DefaultIgnore; + "C++14">, InGroup<CXXPre14Compat>, DefaultIgnore; def ext_for_range : ExtWarn< "range-based for loop is a C++11 extension">, InGroup<CXX11>; def warn_cxx98_compat_for_range : Warning< "range-based for loop is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -def ext_for_range_identifier : ExtWarn< - "range-based for loop with implicit deduced type is a C++1z extension">, - InGroup<CXX1z>; -def warn_cxx1y_compat_for_range_identifier : Warning< - "range-based for loop with implicit deduced type is incompatible with " - "C++ standards before C++1z">, - InGroup<CXXPre1zCompat>, DefaultIgnore; +def err_for_range_identifier : Error< + "range-based for loop requires type for loop variable">; def err_for_range_expected_decl : Error< "for range declaration must declare a variable">; def err_argument_required_after_attribute : Error< @@ -303,6 +316,8 @@ def err_expected_class_name_not_template : Error<"'typename' is redundant; base classes are implicitly types">; def err_unspecified_vla_size_with_static : Error< "'static' may not be used with an unspecified variable length array size">; +def err_unspecified_size_with_static : Error< + "'static' may not be used without an array size">; def warn_deprecated_register : Warning< "'register' storage class specifier is deprecated">, InGroup<DeprecatedRegister>; @@ -332,10 +347,12 @@ def err_invalid_vector_decl_spec_combination : Error< def err_invalid_pixel_decl_spec_combination : Error< "'__pixel' must be preceded by '__vector'. " "'%0' declaration specifier not allowed here">; -def err_invalid_vector_decl_spec : Error< - "cannot use '%0' with '__vector'">; def err_invalid_vector_bool_decl_spec : Error< "cannot use '%0' with '__vector bool'">; +def err_invalid_vector_double_decl_spec : Error < + "use of 'double' with '__vector' requires VSX support to be enabled (available on the POWER7 or later)">; +def err_invalid_vector_long_double_decl_spec : Error< + "cannot use 'long double' with '__vector'">; def warn_vector_long_decl_spec_combination : Warning< "Use of 'long' with '__vector' is deprecated">, InGroup<Deprecated>; def err_friend_invalid_in_context : Error< @@ -363,6 +380,8 @@ def err_function_definition_not_allowed : Error< "function definition is not allowed here">; def err_expected_end_of_enumerator : Error< "expected '= constant-expression' or end of enumerator definition">; +def err_expected_coloncolon_after_super : Error< + "expected '::' after '__super'">; /// Objective-C parser diagnostics def err_expected_minus_or_plus : Error< @@ -477,6 +496,8 @@ def ext_ellipsis_exception_spec : Extension< InGroup<Microsoft>; def err_dynamic_and_noexcept_specification : Error< "cannot have both throw() and noexcept() clause on the same function">; +def err_except_spec_unparsed : Error< + "unexpected end of exception specification">; def warn_cxx98_compat_noexcept_decl : Warning< "noexcept specifications are incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; @@ -487,6 +508,8 @@ def err_constructor_bad_name : Error< "missing return type for function %0; did you mean the constructor name %1?">; def err_destructor_tilde_identifier : Error< "expected a class name after '~' to name a destructor">; +def err_destructor_tilde_scope : Error< + "'~' in destructor name should be after nested name specifier">; def err_destructor_template_id : Error< "destructor name %0 does not refer to a template">; def err_default_arg_unparsed : Error< @@ -498,11 +521,24 @@ def note_bracket_depth : Note< def err_misplaced_ellipsis_in_declaration : Error< "'...' must %select{immediately precede declared identifier|" "be innermost component of anonymous pack declaration}0">; +def warn_misplaced_ellipsis_vararg : Warning< + "'...' in this location creates a C-style varargs function" + "%select{, not a function parameter pack|}0">, + InGroup<DiagGroup<"ambiguous-ellipsis">>; +def note_misplaced_ellipsis_vararg_existing_ellipsis : Note< + "preceding '...' declares a function parameter pack">; +def note_misplaced_ellipsis_vararg_add_ellipsis : Note< + "place '...' %select{immediately before declared identifier|here}0 " + "to declare a function parameter pack">; +def note_misplaced_ellipsis_vararg_add_comma : Note< + "insert ',' before '...' to silence this warning">; def ext_abstract_pack_declarator_parens : ExtWarn< "ISO C++11 requires a parenthesized pack declaration to have a name">, InGroup<DiagGroup<"anonymous-pack-parens">>; def err_function_is_not_record : Error< "unexpected %0 in function call; perhaps remove the %0?">; +def err_super_in_using_declaration : Error< + "'__super' cannot be used with a using declaration">; // C++ derived classes def err_dup_virtual : Error<"duplicate 'virtual' in base specifier">; @@ -529,6 +565,10 @@ def warn_cxx98_compat_noexcept_expr : Warning< def warn_cxx98_compat_nullptr : Warning< "'nullptr' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx14_compat_attribute : Warning< + "attributes on %select{a namespace|an enumerator}0 declaration are " + "incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; def warn_cxx98_compat_alignas : Warning<"'alignas' is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def warn_cxx98_compat_attribute : Warning< @@ -564,6 +604,8 @@ def err_ms_property_expected_accessor_name : Error< "expected name of accessor method">; def err_ms_property_expected_comma_or_rparen : Error< "expected ',' or ')' at end of property accessor list">; +def err_ms_property_initializer : Error< + "property declaration cannot have an in-class initializer">; /// C++ Templates def err_expected_template : Error<"expected template">; @@ -576,7 +618,7 @@ def err_class_on_template_template_param : Error< def ext_template_template_param_typename : ExtWarn< "template template parameter using 'typename' is a C++1z extension">, InGroup<CXX1z>; -def warn_cxx1y_compat_template_template_param_typename : Warning< +def warn_cxx14_compat_template_template_param_typename : Warning< "template template parameter using 'typename' is " "incompatible with C++ standards before C++1z">, InGroup<CXXPre1zCompat>, DefaultIgnore; @@ -597,14 +639,16 @@ def warn_cxx11_right_shift_in_template_arg : Warning< def warn_cxx98_compat_two_right_angle_brackets : Warning< "consecutive right angle brackets are incompatible with C++98 (use '> >')">, InGroup<CXX98Compat>, DefaultIgnore; +def err_templated_invalid_declaration : Error< + "a static_assert declaration cannot be a template">; def err_multiple_template_declarators : Error< - "%select{|a template declaration|an explicit template specialization|" - "an explicit template instantiation}0 can " - "only %select{|declare|declare|instantiate}0 a single entity">; + "%select{|a template declaration|an explicit template specialization|" + "an explicit template instantiation}0 can " + "only %select{|declare|declare|instantiate}0 a single entity">; def err_explicit_instantiation_with_definition : Error< - "explicit template instantiation cannot have a definition; if this " - "definition is meant to be an explicit specialization, add '<>' after the " - "'template' keyword">; + "explicit template instantiation cannot have a definition; if this " + "definition is meant to be an explicit specialization, add '<>' after the " + "'template' keyword">; def err_template_defn_explicit_instantiation : Error< "%select{function|class|variable}0 cannot be defined in an explicit instantiation; if this " "declaration is meant to be a %select{function|class|variable}0 definition, remove the 'template' keyword">; @@ -612,7 +656,7 @@ def err_friend_explicit_instantiation : Error< "friend cannot be declared in an explicit instantiation; if this " "declaration is meant to be a friend declaration, remove the 'template' keyword">; def err_explicit_instantiation_enum : Error< - "enumerations cannot be explicitly instantiated">; + "enumerations cannot be explicitly instantiated">; def err_expected_template_parameter : Error<"expected template parameter">; def err_missing_dependent_template_keyword : Error< @@ -654,7 +698,18 @@ def err_explicit_spec_non_template : Error< def err_default_template_template_parameter_not_template : Error< "default template argument for a template template parameter must be a class " "template">; - + +def ext_fold_expression : ExtWarn< + "pack fold expression is a C++1z extension">, + InGroup<CXX1z>; +def warn_cxx14_compat_fold_expression : Warning< + "pack fold expression is incompatible with C++ standards before C++1z">, + InGroup<CXXPre1zCompat>, DefaultIgnore; +def err_expected_fold_operator : Error< + "expected a foldable binary operator in fold expression">; +def err_fold_operator_mismatch : Error< + "operators in fold expression must be the same">; + def err_ctor_init_missing_comma : Error< "missing ',' between base or member initializers">; @@ -699,7 +754,7 @@ def err_alias_declaration_not_identifier : Error< "name defined in alias declaration must be an identifier">; def err_alias_declaration_specialization : Error< "%select{partial specialization|explicit specialization|explicit instantiation}0 of alias templates is not permitted">; - + // C++11 override control def ext_override_control_keyword : ExtWarn< "'%0' keyword is a C++11 extension">, InGroup<CXX11>; @@ -751,6 +806,9 @@ def err_lambda_missing_parens : Error< // Availability attribute def err_expected_version : Error< "expected a version of the form 'major[.minor[.subminor]]'">; +def warn_expected_consistent_version_separator : Warning< + "use same version number separators '_' or '.'; as in " + "'major[.minor[.subminor]]'">, InGroup<Availability>; def err_zero_version : Error< "version number must have non-zero major, minor, or sub-minor version">; def err_availability_expected_platform : Error< @@ -818,7 +876,7 @@ def warn_pragma_expected_non_wide_string : Warning< "expected non-wide string literal in '#pragma %0'">, InGroup<IgnoredPragmas>; // - Generic errors def err_pragma_missing_argument : Error< - "missing argument to '#pragma %0'; expected %1">; + "missing argument to '#pragma %0'%select{|; expected %2}1">; // - #pragma options def warn_pragma_options_expected_align : Warning< "expected 'align' following '#pragma options' - ignored">, @@ -878,8 +936,8 @@ def err_pragma_optimize_extra_argument : Error< "unexpected extra argument '%0' to '#pragma clang optimize'">; // OpenCL Section 6.8.g -def err_not_opencl_storage_class_specifier : Error< - "OpenCL does not support the '%0' storage class specifier">; +def err_opencl_unknown_type_specifier : Error< + "OpenCL does not support the '%0' %select{type qualifier|storage class specifier}1">; // OpenCL EXTENSION pragma (OpenCL 1.1 [9.1]) def warn_pragma_expected_colon : Warning< @@ -923,9 +981,14 @@ def err_omp_expected_identifier_for_critical : Error< "expected identifier specifying the name of the 'omp critical' directive">; // Pragma loop support. +def err_pragma_loop_missing_argument : Error< + "missing argument; expected %select{an integer value|" + "'%select{enable|full}1' or 'disable'}0">; def err_pragma_loop_invalid_option : Error< "%select{invalid|missing}0 option%select{ %1|}0; expected vectorize, " "vectorize_width, interleave, interleave_count, unroll, or unroll_count">; +def err_pragma_invalid_keyword : Error< + "invalid argument; expected '%select{enable|full}0' or 'disable'">; // Pragma unroll support. def warn_pragma_unroll_cuda_value_in_parens : Warning< diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 1665a45e2cbf..8966c55d0963 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -64,6 +64,9 @@ def err_typecheck_converted_constant_expression : Error< "value of type %0 is not implicitly convertible to %1">; def err_typecheck_converted_constant_expression_disallowed : Error< "conversion from %0 to %1 is not allowed in a converted constant expression">; +def err_typecheck_converted_constant_expression_indirect : Error< + "conversion from %0 to %1 in converted constant expression would " + "bind reference to a temporary">; def err_expr_not_cce : Error< "%select{case value|enumerator value|non-type template argument|array size}0 " "is not a constant expression">; @@ -84,6 +87,9 @@ def note_ice_conversion_here : Note< def err_ice_ambiguous_conversion : Error< "ambiguous conversion from type %0 to an integral or unscoped " "enumeration type">; +def err_ice_too_large : Error< + "integer constant expression evaluates to value %0 that cannot be " + "represented in a %1-bit %select{signed|unsigned}2 integer type">; // Semantic analysis of constant literals. def ext_predef_outside_function : Warning< @@ -172,6 +178,9 @@ def warn_unused_parameter : Warning<"unused parameter %0">, InGroup<UnusedParameter>, DefaultIgnore; def warn_unused_variable : Warning<"unused variable %0">, InGroup<UnusedVariable>, DefaultIgnore; +def warn_unused_local_typedef : Warning< + "unused %select{typedef|type alias}0 %1">, + InGroup<UnusedLocalTypedef>, DefaultIgnore; def warn_unused_property_backing_ivar : Warning<"ivar %0 which backs the property is not " "referenced in this property's accessor">, @@ -445,9 +454,13 @@ def note_strncat_wrong_size : Note< "the terminating null byte">; def warn_assume_side_effects : Warning< - "the argument to __assume has side effects that will be discarded">, + "the argument to %0 has side effects that will be discarded">, InGroup<DiagGroup<"assume">>; +def warn_memcpy_chk_overflow : Warning< + "%0 will always overflow destination buffer">, + InGroup<DiagGroup<"builtin-memcpy-chk-size">>; + /// main() // static main() is not an error in C, just in C++. def warn_static_main : Warning<"'main' should not be declared static">, @@ -521,6 +534,11 @@ def warn_cxx_ms_struct : "with base classes or virtual functions">, DefaultError, InGroup<IncompatibleMSStruct>; def err_section_conflict : Error<"%0 causes a section type conflict with %1">; +def err_no_base_classes : Error<"invalid use of '__super', %0 has no base classes">; +def err_invalid_super_scope : Error<"invalid use of '__super', " + "this keyword can only be used inside class or member function scope">; +def err_super_in_lambda_unsupported : Error< + "use of '__super' inside a lambda is unsupported">; def warn_pragma_unused_undeclared_var : Warning< "undeclared variable %0 used as an argument for '#pragma unused'">, @@ -536,10 +554,10 @@ def err_pragma_pop_visibility_mismatch : Error< "#pragma visibility pop with no matching #pragma visibility push">; def note_surrounding_namespace_starts_here : Note< "surrounding namespace with visibility attribute starts here">; -def err_pragma_loop_invalid_value : Error< - "invalid argument; expected a positive integer value">; -def err_pragma_loop_invalid_keyword : Error< - "invalid argument; expected 'enable' or 'disable'">; +def err_pragma_loop_invalid_argument_type : Error< + "invalid argument of type %0; expected an integer type">; +def err_pragma_loop_invalid_argument_value : Error< + "%select{invalid value '%0'; must be positive|value '%0' is too large}1">; def err_pragma_loop_compatibility : Error< "%select{incompatible|duplicate}0 directives '%1' and '%2'">; def err_pragma_loop_precedes_nonloop : Error< @@ -563,14 +581,19 @@ def err_protocol_has_circular_dependency : Error< "protocol has circular dependency">; def err_undeclared_protocol : Error<"cannot find protocol declaration for %0">; def warn_undef_protocolref : Warning<"cannot find protocol definition for %0">; +def warn_atprotocol_protocol : Warning< + "@protocol is using a forward protocol declaration of %0">, InGroup<AtProtocol>; def warn_readonly_property : Warning< "attribute 'readonly' of property %0 restricts attribute " - "'readwrite' of property inherited from %1">; + "'readwrite' of property inherited from %1">, + InGroup<PropertyAttr>; def warn_property_attribute : Warning< - "'%1' attribute on property %0 does not match the property inherited from %2">; + "'%1' attribute on property %0 does not match the property inherited from %2">, + InGroup<PropertyAttr>; def warn_property_types_are_incompatible : Warning< - "property type %0 is incompatible with type %1 inherited from %2">; + "property type %0 is incompatible with type %1 inherited from %2">, + InGroup<DiagGroup<"incompatible-property-type">>; def warn_protocol_property_mismatch : Warning< "property of type %0 was selected for synthesis">, InGroup<DiagGroup<"protocol-property-synthesis-ambiguity">>; @@ -587,6 +610,8 @@ def note_class_declared : Note< "class is declared here">; def note_receiver_class_declared : Note< "receiver is instance of class declared here">; +def note_receiver_expr_here : Note< + "receiver expression is here">; def note_receiver_is_id : Note< "receiver is treated with 'id' type for purpose of method lookup">; def note_suppressed_class_declare : Note< @@ -696,7 +721,8 @@ def warn_implements_nscopying : Warning< "default assign attribute on property %0 which implements " "NSCopying protocol is not appropriate with -fobjc-gc[-only]">; -def warn_multiple_method_decl : Warning<"multiple methods named %0 found">; +def warn_multiple_method_decl : Warning<"multiple methods named %0 found">, + InGroup<ObjCMultipleMethodNames>; def warn_strict_multiple_method_decl : Warning< "multiple methods named %0 found">, InGroup<StrictSelector>, DefaultIgnore; def warn_accessor_property_type_mismatch : Warning< @@ -710,6 +736,11 @@ def err_duplicate_method_decl : Error<"duplicate declaration of method %0">; def warn_duplicate_method_decl : Warning<"multiple declarations of method %0 found and ignored">, InGroup<MethodDuplicate>, DefaultIgnore; +def warn_objc_cdirective_format_string : + Warning<"using %0 directive in %select{NSString|CFString}1 " + "which is being passed as a formatting argument to the formatting " + "%select{method|CFfunction}2">, + InGroup<ObjCCStringFormat>, DefaultIgnore; def err_objc_var_decl_inclass : Error<"cannot declare variable inside @interface or @protocol">; def error_missing_method_context : Error< @@ -738,7 +769,8 @@ def warn_objc_property_default_assign_on_object : Warning< "default property attribute 'assign' not appropriate for non-GC object">, InGroup<ObjCPropertyNoAttribute>; def warn_property_attr_mismatch : Warning< - "property attribute in class extension does not match the primary class">; + "property attribute in class extension does not match the primary class">, + InGroup<PropertyAttr>; def warn_property_implicitly_mismatched : Warning < "primary property declaration is implicitly strong while redeclaration " "in class extension is weak">, @@ -778,6 +810,11 @@ def warn_no_autosynthesis_property : Warning< "%0 because it is 'readwrite' but it will be synthesized 'readonly' " "via another property">, InGroup<ObjCNoPropertyAutoSynthesis>; +def warn_autosynthesis_property_in_superclass : Warning< + "auto property synthesis will not synthesize property " + "%0; it will be implemented by its superclass, use @dynamic to " + "acknowledge intention">, + InGroup<ObjCNoPropertyAutoSynthesis>; def warn_autosynthesis_property_ivar_match :Warning< "autosynthesized property %0 will use %select{|synthesized}1 instance variable " "%2, not existing instance variable %3">, @@ -927,7 +964,7 @@ def err_static_assert_expression_is_not_constant : Error< def err_static_assert_failed : Error<"static_assert failed%select{ %1|}0">; def ext_static_assert_no_message : ExtWarn< "static_assert with no message is a C++1z extension">, InGroup<CXX1z>; -def warn_cxx1y_compat_static_assert_no_message : Warning< +def warn_cxx14_compat_static_assert_no_message : Warning< "static_assert with no message is incompatible with C++ standards before C++1z">, DefaultIgnore, InGroup<CXXPre1zCompat>; @@ -1085,6 +1122,8 @@ def warn_missing_exception_specification : Warning< "%0 is missing exception specification '%1'">; def err_noexcept_needs_constant_expression : Error< "argument to noexcept specifier must be a constant expression">; +def err_exception_spec_not_parsed : Error< + "exception specification is not available until end of class definition">; // C++ access checking def err_class_redeclared_with_different_access : Error< @@ -1098,7 +1137,7 @@ def ext_ms_using_declaration_inaccessible : ExtWarn< def err_access_ctor : Error< "calling a %select{private|protected}0 constructor of class %2">, AccessControl; -def ext_rvalue_to_reference_access_ctor : ExtWarn< +def ext_rvalue_to_reference_access_ctor : Extension< "C++98 requires an accessible copy constructor for class %2 when binding " "a reference to a temporary; was %select{private|protected}0">, AccessControl, InGroup<BindToTemporaryCopy>; @@ -1462,6 +1501,9 @@ def note_uninit_reference_member : Note< "uninitialized reference member is here">; def warn_field_is_uninit : Warning<"field %0 is uninitialized when used here">, InGroup<Uninitialized>; +def warn_base_class_is_uninit : Warning< + "base class %0 is uninitialized when used here to access %q1">, + InGroup<Uninitialized>; def warn_reference_field_is_uninit : Warning< "reference %0 is not yet bound to a value when used here">, InGroup<Uninitialized>; @@ -1505,6 +1547,9 @@ def note_block_var_fixit_add_initialization : Note< def note_in_omitted_aggregate_initializer : Note< "in implicit initialization of %select{array element %1|field %1}0 " "with omitted initializer">; +def note_in_reference_temporary_list_initializer : Note< + "in initialization of temporary of type %0 created to " + "list-initialize this reference">; def note_var_fixit_add_initialization : Note< "initialize the variable %0 to silence this warning">; def note_uninit_fixit_remove_cond : Note< @@ -1522,7 +1567,7 @@ def err_temp_copy_no_viable : Error< "returning object|throwing object|copying member subobject|copying array " "element|allocating object|copying temporary|initializing base subobject|" "initializing vector element|capturing value}0 of type %1">; -def ext_rvalue_to_reference_temp_copy_no_viable : ExtWarn< +def ext_rvalue_to_reference_temp_copy_no_viable : Extension< "no viable constructor %select{copying variable|copying parameter|" "returning object|throwing object|copying member subobject|copying array " "element|allocating object|copying temporary|initializing base subobject|" @@ -1594,9 +1639,9 @@ def err_auto_new_ctor_multiple_expressions : Error< "new expression for type %0 contains multiple constructor arguments">; def err_auto_missing_trailing_return : Error< "'auto' return without trailing return type; deduced return types are a " - "C++1y extension">; + "C++14 extension">; def err_deduced_return_type : Error< - "deduced return types are a C++1y extension">; + "deduced return types are a C++14 extension">; def err_trailing_return_without_auto : Error< "function with trailing return type must specify return type 'auto', not %0">; def err_trailing_return_in_parens : Error< @@ -1656,6 +1701,9 @@ def override_keyword_hides_virtual_member_function : Error< "%select{function|functions}1">; def err_function_marked_override_not_overriding : Error< "%0 marked 'override' but does not override any member functions">; +def warn_function_marked_not_override_overriding : Warning < + "%0 overrides a member function but is not marked 'override'">, + InGroup<CXX11WarnOverrideMethod>; def err_class_marked_final_used_as_base : Error< "base %0 is marked '%select{final|sealed}1'">; def warn_abstract_final_class : Warning< @@ -1745,10 +1793,10 @@ def note_for_range_begin_end : Note< def warn_cxx98_compat_constexpr : Warning< "'constexpr' specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; -// FIXME: Maybe this should also go in -Wc++1y-compat? -def warn_cxx1y_compat_constexpr_not_const : Warning< +// FIXME: Maybe this should also go in -Wc++14-compat? +def warn_cxx14_compat_constexpr_not_const : Warning< "'constexpr' non-static member function will not be implicitly 'const' " - "in C++1y; add 'const' to avoid a change in behavior">, + "in C++14; add 'const' to avoid a change in behavior">, InGroup<DiagGroup<"constexpr-not-const">>; def err_invalid_constexpr : Error< "%select{function parameter|typedef|non-static data member}0 " @@ -1790,28 +1838,28 @@ def err_constexpr_body_invalid_stmt : Error< "statement not allowed in constexpr %select{function|constructor}0">; def ext_constexpr_body_invalid_stmt : ExtWarn< "use of this statement in a constexpr %select{function|constructor}0 " - "is a C++1y extension">, InGroup<CXX1y>; + "is a C++14 extension">, InGroup<CXX14>; def warn_cxx11_compat_constexpr_body_invalid_stmt : Warning< "use of this statement in a constexpr %select{function|constructor}0 " - "is incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompat>, DefaultIgnore; + "is incompatible with C++ standards before C++14">, + InGroup<CXXPre14Compat>, DefaultIgnore; def ext_constexpr_type_definition : ExtWarn< "type definition in a constexpr %select{function|constructor}0 " - "is a C++1y extension">, InGroup<CXX1y>; + "is a C++14 extension">, InGroup<CXX14>; def warn_cxx11_compat_constexpr_type_definition : Warning< "type definition in a constexpr %select{function|constructor}0 " - "is incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompat>, DefaultIgnore; + "is incompatible with C++ standards before C++14">, + InGroup<CXXPre14Compat>, DefaultIgnore; def err_constexpr_vla : Error< "variably-modified type %0 cannot be used in a constexpr " "%select{function|constructor}1">; def ext_constexpr_local_var : ExtWarn< "variable declaration in a constexpr %select{function|constructor}0 " - "is a C++1y extension">, InGroup<CXX1y>; + "is a C++14 extension">, InGroup<CXX14>; def warn_cxx11_compat_constexpr_local_var : Warning< "variable declaration in a constexpr %select{function|constructor}0 " - "is incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompat>, DefaultIgnore; + "is incompatible with C++ standards before C++14">, + InGroup<CXXPre14Compat>, DefaultIgnore; def err_constexpr_local_var_static : Error< "%select{static|thread_local}1 variable not permitted in a constexpr " "%select{function|constructor}0">; @@ -1828,16 +1876,18 @@ def err_enable_if_never_constant_expr : Error< "'enable_if' attribute expression never produces a constant expression">; def err_constexpr_body_no_return : Error< "no return statement in constexpr function">; +def err_constexpr_return_missing_expr : Error< + "non-void constexpr function %0 should return a value">; def warn_cxx11_compat_constexpr_body_no_return : Warning< "constexpr function with no return statements is incompatible with C++ " - "standards before C++1y">, InGroup<CXXPre1yCompat>, DefaultIgnore; + "standards before C++14">, InGroup<CXXPre14Compat>, DefaultIgnore; def ext_constexpr_body_multiple_return : ExtWarn< - "multiple return statements in constexpr function is a C++1y extension">, - InGroup<CXX1y>; + "multiple return statements in constexpr function is a C++14 extension">, + InGroup<CXX14>; def warn_cxx11_compat_constexpr_body_multiple_return : Warning< "multiple return statements in constexpr function " - "is incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompat>, DefaultIgnore; + "is incompatible with C++ standards before C++14">, + InGroup<CXXPre14Compat>, DefaultIgnore; def note_constexpr_body_previous_return : Note< "previous return statement is here">; def err_constexpr_function_try_block : Error< @@ -1848,8 +1898,6 @@ def err_constexpr_ctor_missing_init : Error< "constexpr constructor must initialize all members">; def note_constexpr_ctor_missing_init : Note< "member not initialized by constructor">; -def err_constexpr_method_non_literal : Error< - "non-literal type %0 cannot have constexpr members">; def note_non_literal_no_constexpr_ctors : Note< "%0 is not literal because it is not an aggregate and has no constexpr " "constructors other than copy or move constructors">; @@ -1897,8 +1945,12 @@ def err_attribute_bad_neon_vector_size : Error< "Neon vector size must be 64 or 128 bits">; def err_attribute_unsupported : Error< "%0 attribute is not supported for this target">; +// The err_*_attribute_argument_not_int are seperate because they're used by +// VerifyIntegerConstantExpression. def err_aligned_attribute_argument_not_int : Error< "'aligned' attribute requires integer constant">; +def err_align_value_attribute_argument_not_int : Error< + "'align_value' attribute requires integer constant">; def err_alignas_attribute_wrong_decl_type : Error< "%0 attribute cannot be applied to a %select{function parameter|" "variable with 'register' storage class|'catch' variable|bit-field}1">; @@ -1934,12 +1986,22 @@ def err_attribute_pointers_only : Error<warn_attribute_pointers_only.Text>; def warn_attribute_return_pointers_only : Warning< "%0 attribute only applies to return values that are pointers">, InGroup<IgnoredAttributes>; +def warn_attribute_return_pointers_refs_only : Warning< + "%0 attribute only applies to return values that are pointers or references">, + InGroup<IgnoredAttributes>; +def warn_attribute_pointer_or_reference_only : Warning< + "%0 attribute only applies to a pointer or reference (%1 is invalid)">, + InGroup<IgnoredAttributes>; def err_attribute_no_member_pointers : Error< "%0 attribute cannot be used with pointers to members">; def err_attribute_invalid_implicit_this_argument : Error< "%0 attribute is invalid for the implicit this argument">; def err_ownership_type : Error< "%0 attribute only applies to %select{pointer|integer}1 arguments">; +def err_ownership_returns_index_mismatch : Error< + "'ownership_returns' attribute index does not match; here it is %0">; +def note_ownership_returns_index_mismatch : Note< + "declared with index %0 here">; def err_format_strftime_third_parameter : Error< "strftime format attribute requires 3rd parameter to be 0">; def err_format_attribute_requires_variadic : Error< @@ -2054,14 +2116,22 @@ def err_no_accessor_for_property : Error< def error_cannot_find_suitable_accessor : Error< "cannot find suitable %select{getter|setter}0 for property %1">; -def err_attribute_aligned_not_power_of_two : Error< +def err_alignment_not_power_of_two : Error< "requested alignment is not a power of 2">; + def err_attribute_aligned_too_great : Error< "requested alignment must be %0 bytes or smaller">; def warn_redeclaration_without_attribute_prev_attribute_ignored : Warning< - "%q0 redeclared without %1 attribute: previous %1 ignored">; + "%q0 redeclared without %1 attribute: previous %1 ignored">, + InGroup<DiagGroup<"inconsistent-dllimport">>; +def warn_dllimport_dropped_from_inline_function : Warning< + "%q0 redeclared inline; %1 attribute ignored">, + InGroup<IgnoredAttributes>; def warn_attribute_ignored : Warning<"%0 attribute ignored">, InGroup<IgnoredAttributes>; +def warn_attribute_ignored_on_inline : + Warning<"%0 attribute ignored on inline function">, + InGroup<IgnoredAttributes>; def warn_attribute_after_definition_ignored : Warning< "attribute %0 after definition is ignored">, InGroup<IgnoredAttributes>; @@ -2110,6 +2180,8 @@ def err_declspec_thread_on_thread_variable : Error< "thread-local storage specifier">; def err_attribute_dll_not_extern : Error< "%q0 must have external linkage when declared %q1">; +def err_attribute_dll_thread_local : Error< + "%q0 cannot be thread local when declared %q1">; def warn_attribute_invalid_on_definition : Warning< "'%0' attribute cannot be specified on a definition">, InGroup<IgnoredAttributes>; @@ -2139,7 +2211,7 @@ def warn_attribute_dll_instantiated_base_class : Warning< "propagating dll attribute to %select{already instantiated|explicitly specialized}0 " "base class template " "%select{without dll attribute|with different dll attribute}1 is not supported">, - InGroup<DiagGroup<"unsupported-dll-base-class-template">>; + InGroup<DiagGroup<"unsupported-dll-base-class-template">>, DefaultIgnore; def err_attribute_weakref_not_static : Error< "weakref declaration must have internal linkage">; def err_attribute_weakref_not_global_context : Error< @@ -2164,22 +2236,25 @@ def warn_attribute_wrong_decl_type : Warning< "%0 attribute only applies to %select{functions|unions|" "variables and functions|functions and methods|parameters|" "functions, methods and blocks|functions, methods, and classes|" - "functions, methods, and parameters|classes|variables|methods|" + "functions, methods, and parameters|classes|enums|variables|methods|" "variables, functions and labels|fields and global variables|structs|" - "variables, functions and tag types|thread-local variables|" + "variables and typedefs|thread-local variables|" "variables and fields|variables, data members and tag types|" "types and namespaces|Objective-C interfaces|methods and properties|" "struct or union|struct, union or class|types|" "Objective-C instance methods|init methods of interface or class extension declarations|" "variables, functions and classes|Objective-C protocols|" "functions and global variables|structs or typedefs|" - "interface or protocol declarations}1">, + "interface or protocol declarations|kernel functions}1">, InGroup<IgnoredAttributes>; def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; def warn_type_attribute_wrong_type : Warning< "'%0' only applies to %select{function|pointer|" "Objective-C object or block pointer}1 types; type here is %2">, InGroup<IgnoredAttributes>; +def warn_incomplete_encoded_type : Warning< + "encoding of %0 type is incomplete because %1 component has unknown encoding">, + InGroup<DiagGroup<"encode-type">>; def warn_attribute_requires_functions_or_static_globals : Warning< "%0 only applies to variables with static storage duration and functions">, InGroup<IgnoredAttributes>; @@ -2197,7 +2272,10 @@ def err_cconv_change : Error< def warn_cconv_ignored : Warning< "calling convention %0 ignored for this target">, InGroup<IgnoredAttributes>; def err_cconv_knr : Error< - "function with no prototype cannot use %0 calling convention">; + "function with no prototype cannot use the %0 calling convention">; +def warn_cconv_knr : Warning< + err_cconv_knr.Text>, + InGroup<DiagGroup<"missing-prototype-for-cc">>; def err_cconv_varargs : Error< "variadic function cannot use %0 calling convention">; def warn_cconv_varargs : Warning< @@ -2307,6 +2385,21 @@ def warn_cannot_resolve_lock : Warning< "cannot resolve lock expression">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; +// Thread safety warnings negative capabilities +def warn_acquire_requires_negative_cap : Warning< + "acquiring %0 '%1' requires negative capability '%2'">, + InGroup<ThreadSafetyNegative>, DefaultIgnore; + +// Thread safety warnings on pass by reference +def warn_guarded_pass_by_reference : Warning< + "passing variable '%1' by reference requires holding %0 " + "%select{'%2'|'%2' exclusively}3">, + InGroup<ThreadSafetyReference>, DefaultIgnore; +def warn_pt_guarded_pass_by_reference : Warning< + "passing the value that '%1' points to by reference requires holding %0 " + "%select{'%2'|'%2' exclusively}3">, + InGroup<ThreadSafetyReference>, DefaultIgnore; + // Imprecise thread safety warnings def warn_variable_requires_lock : Warning< "%select{reading|writing}3 variable '%1' requires holding %0 " @@ -2332,9 +2425,15 @@ def warn_fun_requires_lock_precise : InGroup<ThreadSafetyPrecise>, DefaultIgnore; def note_found_mutex_near_match : Note<"found near match '%0'">; +// Verbose thread safety warnings +def warn_thread_safety_verbose : Warning<"Thread safety verbose warning.">, + InGroup<ThreadSafetyVerbose>, DefaultIgnore; +def note_thread_warning_in_fun : Note<"Thread warning in function '%0'">; +def note_guarded_by_declared_here : Note<"Guarded_by declared here.">; + // Dummy warning that will trigger "beta" warnings from the analysis if enabled. -def warn_thread_safety_beta : Warning< - "Thread safety beta warning.">, InGroup<ThreadSafetyBeta>, DefaultIgnore; +def warn_thread_safety_beta : Warning<"Thread safety beta warning.">, + InGroup<ThreadSafetyBeta>, DefaultIgnore; // Consumed warnings def warn_use_in_invalid_state : Warning< @@ -2408,7 +2507,7 @@ def warn_non_literal_null_pointer : Warning< "expression which evaluates to zero treated as a null pointer constant of " "type %0">, InGroup<NonLiteralNullConversion>; def warn_impcast_null_pointer_to_integer : Warning< - "implicit conversion of NULL constant to %0">, + "implicit conversion of %select{NULL|nullptr}0 constant to %1">, InGroup<NullConversion>; def warn_impcast_floating_point_to_bool : Warning< "implicit conversion turns floating-point number into bool: %0 to %1">, @@ -2418,6 +2517,10 @@ def warn_impcast_pointer_to_bool : Warning< "address of%select{| function| array}0 '%1' will always evaluate to " "'true'">, InGroup<PointerBoolConversion>; +def warn_cast_nonnull_to_bool : Warning< + "nonnull parameter '%0' will evaluate to " + "'true' on first encounter">, + InGroup<PointerBoolConversion>; def warn_this_bool_conversion : Warning< "'this' pointer cannot be null in well-defined C++ code; pointer may be " "assumed to always convert to true">, InGroup<UndefinedBoolConversion>; @@ -2430,6 +2533,10 @@ def warn_null_pointer_compare : Warning< "comparison of %select{address of|function|array}0 '%1' %select{not |}2" "equal to a null pointer is always %select{true|false}2">, InGroup<TautologicalPointerCompare>; +def warn_nonnull_parameter_compare : Warning< + "comparison of nonnull parameter '%0' %select{not |}1" + "equal to a null pointer is %select{true|false}1 on first encounter">, + InGroup<TautologicalPointerCompare>; def warn_this_null_compare : Warning< "'this' pointer cannot be null in well-defined C++ code; comparison may be " "assumed to always evaluate to %select{true|false}0">, @@ -2500,6 +2607,7 @@ def warn_attribute_protected_visibility : InGroup<DiagGroup<"unsupported-visibility">>; def err_mismatched_visibility: Error<"visibility does not match previous declaration">; def note_previous_attribute : Note<"previous attribute is here">; +def note_conflicting_attribute : Note<"conflicting attribute is here">; def note_attribute : Note<"attribute is here">; def err_mismatched_ms_inheritance : Error< "inheritance model does not match %select{definition|previous declaration}0">; @@ -2739,6 +2847,9 @@ def note_ovl_candidate : Note<"candidate " "|volatile and restrict|const, volatile, and restrict}4)}2">; def note_ovl_candidate_inherited_constructor : Note<"inherited from here">; +def note_ovl_candidate_illegal_constructor : Note< + "candidate %select{constructor|template}0 ignored: " + "instantiation %select{takes|would take}0 its own class type by value">; def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " @@ -2756,7 +2867,7 @@ def note_ovl_candidate_instantiation_depth : Note< "candidate template ignored: substitution exceeded maximum template " "instantiation depth">; def note_ovl_candidate_underqualified : Note< - "candidate template ignored: can't deduce a type for %0 which would " + "candidate template ignored: can't deduce a type for %0 that would " "make %2 equal %1">; def note_ovl_candidate_substitution_failure : Note< "candidate template ignored: substitution failure%0%1">; @@ -2962,8 +3073,18 @@ def note_ovl_candidate_bad_target : Note< "function (the implicit copy assignment operator)|" "function (the implicit move assignment operator)|" "constructor (inherited)}0 not viable: call to " - "%select{__device__|__global__|__host__|__host__ __device__}1 function from" - " %select{__device__|__global__|__host__|__host__ __device__}2 function">; + "%select{__device__|__global__|__host__|__host__ __device__|invalid}1 function from" + " %select{__device__|__global__|__host__|__host__ __device__|invalid}2 function">; +def note_implicit_member_target_infer_collision : Note< + "implicit %select{" + "default constructor|" + "copy constructor|" + "move constructor|" + "copy assignment operator|" + "move assignment operator|" + "destructor}0 inferred target collision: call to both " + "%select{__device__|__global__|__host__|__host__ __device__}1 and " + "%select{__device__|__global__|__host__|__host__ __device__}2 members">; def note_ambiguous_type_conversion: Note< "because of ambiguity in conversion %diff{of $ to $|between types}0,1">; @@ -3103,11 +3224,11 @@ def err_template_parameter_default_friend_template : Error< def err_template_template_parm_no_parms : Error< "template template parameter must have its own template parameters">; -def ext_variable_template : ExtWarn<"variable templates are a C++1y extension">, - InGroup<CXX1y>; +def ext_variable_template : ExtWarn<"variable templates are a C++14 extension">, + InGroup<CXX14>; def warn_cxx11_compat_variable_template : Warning< - "variable templates are incompatible with C++ standards before C++1y">, - InGroup<CXXPre1yCompat>, DefaultIgnore; + "variable templates are incompatible with C++ standards before C++14">, + InGroup<CXXPre14Compat>, DefaultIgnore; def err_template_variable_noparams : Error< "extraneous 'template<>' in declaration of variable %0">; def err_template_member : Error<"member %0 declared as a template">; @@ -3181,6 +3302,10 @@ def err_template_arg_wrongtype_null_constant : Error< def err_deduced_non_type_template_arg_type_mismatch : Error< "deduced non-type template argument does not have the same type as the " "its corresponding template parameter%diff{ ($ vs $)|}0,1">; +def err_non_type_template_arg_subobject : Error< + "non-type template argument refers to subobject '%0'">; +def err_non_type_template_arg_addr_label_diff : Error< + "template argument / label address difference / what did you expect?">; def err_template_arg_not_convertible : Error< "non-type template argument of type %0 cannot be converted to a value " "of type %1">; @@ -3232,6 +3357,9 @@ def err_template_arg_not_object_or_func : Error< "non-type template argument does not refer to an object or function">; def err_template_arg_not_pointer_to_member_form : Error< "non-type template argument is not a pointer to member constant">; +def err_template_arg_member_ptr_base_derived_not_supported : Error< + "sorry, non-type template argument of pointer-to-member type %1 that refers " + "to member %q0 of a different class is not supported yet">; def ext_template_arg_extra_parens : ExtWarn< "address non-type template argument cannot be surrounded by parentheses">; def warn_cxx98_compat_template_arg_extra_parens : Warning< @@ -3435,6 +3563,8 @@ def note_template_variable_def_here : Note< "in instantiation of variable template specialization %q0 requested here">; def note_template_enum_def_here : Note< "in instantiation of enumeration %q0 requested here">; +def note_template_nsdmi_here : Note< + "in instantiation of default member initializer %q0 requested here">; def note_template_type_alias_instantiation_here : Note< "in instantiation of template type alias %0 requested here">; def note_template_exception_spec_instantiation_here : Note< @@ -3559,6 +3689,11 @@ def err_invalid_var_template_spec_type : Error<"type %2 " "of %select{explicit instantiation|explicit specialization|" "partial specialization|redeclaration}0 of %1 does not match" " expected type %3">; +def err_mismatched_exception_spec_explicit_instantiation : Error< + "exception specification in explicit instantiation does not match instantiated one">; +def ext_mismatched_exception_spec_explicit_instantiation : ExtWarn< + "exception specification in explicit instantiation does not match instantiated one">, + InGroup<Microsoft>; // C++ typename-specifiers def err_typename_nested_not_found : Error<"no type named %0 in %1">; @@ -3680,6 +3815,14 @@ def err_ellipsis_in_declarator_not_parameter : Error< def err_sizeof_pack_no_pack_name : Error< "%0 does not refer to the name of a parameter pack">; +def err_fold_expression_packs_both_sides : Error< + "binary fold expression has unexpanded parameter packs in both operands">; +def err_fold_expression_empty : Error< + "unary fold expression has empty expansion for operator '%0' " + "with no fallback value">; +def err_fold_expression_bad_operand : Error< + "expression not permitted as operand of fold expression">; + def err_unexpected_typedef : Error< "unexpected type name %0: expected expression">; def err_unexpected_namespace : Error< @@ -3706,6 +3849,9 @@ def warn_property_method_deprecated : InGroup<DeprecatedDeclarations>; def warn_deprecated_message : Warning<"%0 is deprecated: %1">, InGroup<DeprecatedDeclarations>; +def warn_deprecated_anonymous_namespace : Warning< + "'deprecated' attribute on anonymous namespace ignored">, + InGroup<IgnoredAttributes>; def warn_deprecated_fwdclass_message : Warning< "%0 may be deprecated because the receiver type is unknown">, InGroup<DeprecatedDeclarations>; @@ -3854,6 +4000,10 @@ def err_redefinition_different_type : Error< "redefinition of %0 with a different type%diff{: $ vs $|}1,2">; def err_redefinition_different_kind : Error< "redefinition of %0 as different kind of symbol">; +def err_redefinition_different_namespace_alias : Error< + "redefinition of %0 as an alias for a different namespace">; +def note_previous_namespace_alias : Note< + "previously defined as an alias for %0">; def warn_forward_class_redefinition : Warning< "redefinition of forward class %0 of a typedef name of an object type is ignored">, InGroup<DiagGroup<"objc-forward-class-redefinition">>; @@ -3909,6 +4059,9 @@ def ext_enum_too_large : ExtWarn< def ext_enumerator_increment_too_large : ExtWarn< "incremented enumerator value %0 is not representable in the " "largest integer type">, InGroup<EnumTooLarge>; +def warn_flag_enum_constant_out_of_range : Warning< + "enumeration value %0 is out of range of flags in enumeration type %1">, + InGroup<FlagEnum>; def warn_illegal_constant_array_size : Extension< "size of static array must be an integer constant expression">; @@ -4067,28 +4220,35 @@ def warn_missing_braces : Warning< def err_redefinition_of_label : Error<"redefinition of label %0">; def err_undeclared_label_use : Error<"use of undeclared label %0">; +def err_goto_ms_asm_label : Error< + "cannot jump from this goto statement to label %0 inside an inline assembly block">; +def note_goto_ms_asm_label : Note< + "inline assembly label %0 declared here">; def warn_unused_label : Warning<"unused label %0">, InGroup<UnusedLabel>, DefaultIgnore; -def err_goto_into_protected_scope : Error<"goto into protected scope">; -def ext_goto_into_protected_scope : ExtWarn<"goto into protected scope">, +def err_goto_into_protected_scope : Error< + "cannot jump from this goto statement to its label">; +def ext_goto_into_protected_scope : ExtWarn< + "jump from this goto statement to its label is a Microsoft extension">, InGroup<Microsoft>; def warn_cxx98_compat_goto_into_protected_scope : Warning< - "goto would jump into protected scope in C++98">, + "jump from this goto statement to its label is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_switch_into_protected_scope : Error< - "switch case is in protected scope">; + "cannot jump from switch statement to this case label">; def warn_cxx98_compat_switch_into_protected_scope : Warning< - "switch case would be in a protected scope in C++98">, + "jump from switch statement to this case label is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def err_indirect_goto_without_addrlabel : Error< "indirect goto in function with no address-of-label expressions">; def err_indirect_goto_in_protected_scope : Error< - "indirect goto might cross protected scopes">; + "cannot jump from this indirect goto statement to one of its possible targets">; def warn_cxx98_compat_indirect_goto_in_protected_scope : Warning< - "indirect goto might cross protected scopes in C++98">, - InGroup<CXX98Compat>, DefaultIgnore; -def note_indirect_goto_target : Note<"possible target of indirect goto">; + "jump from this indirect goto statement to one of its possible targets " + "is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def note_indirect_goto_target : Note< + "possible target of indirect goto statement">; def note_protected_by_variable_init : Note< "jump bypasses variable initialization">; def note_protected_by_variable_nontriv_destructor : Note< @@ -4528,7 +4688,7 @@ def warn_logical_and_in_logical_or : Warning< "'&&' within '||'">, InGroup<LogicalOpParentheses>; def warn_overloaded_shift_in_comparison :Warning< - "overloaded operator %select{>>|<<}0 has lower precedence than " + "overloaded operator %select{>>|<<}0 has higher precedence than " "comparison operator">, InGroup<OverloadedShiftOpParentheses>; def note_evaluate_comparison_first :Note< @@ -4541,6 +4701,9 @@ def warn_addition_in_bitshift : Warning< def warn_self_assignment : Warning< "explicitly assigning value of variable of type %0 to itself">, InGroup<SelfAssignment>, DefaultIgnore; +def warn_self_move : Warning< + "explicitly moving variable of type %0 to itself">, + InGroup<SelfMove>, DefaultIgnore; def warn_string_plus_int : Warning< "adding %0 to a string does not append to the string">, @@ -4819,9 +4982,11 @@ def err_typecheck_comparison_of_distinct_pointers : Error< def ext_typecheck_comparison_of_distinct_pointers_nonstandard : ExtWarn< "comparison of distinct pointer types (%0 and %1) uses non-standard " "composite pointer type %2">, InGroup<CompareDistinctPointerType>; +def err_typecheck_op_on_nonoverlapping_address_space_pointers : Error< + "%select{comparison between %diff{ ($ and $)|}0,1" + "|arithmetic operation with operands of type %diff{ ($ and $)|}0,1}2" + " which are pointers to non-overlapping address spaces">; def err_typecheck_assign_const : Error<"read-only variable is not assignable">; -def err_stmtexpr_file_scope : Error< - "statement expression not allowed at file scope">; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, InGroup<SignCompare>, DefaultIgnore; @@ -5128,7 +5293,7 @@ def err_bad_cxx_cast_member_pointer_size : Error< "cannot %select{||reinterpret_cast||C-style cast|}0 from member pointer " "type %1 to member pointer type %2 of different size">; def err_bad_reinterpret_cast_reference : Error< - "reinterpret_cast of a %0 to %1 needs its address which is not allowed">; + "reinterpret_cast of a %0 to %1 needs its address, which is not allowed">; def warn_undefined_reinterpret_cast : Warning< "reinterpret_cast from %0 to %1 has undefined behavior">, InGroup<UndefinedReinterpretCast>, DefaultIgnore; @@ -5162,6 +5327,7 @@ def err_uuidof_without_guid : Error< def err_uuidof_with_multiple_guids : Error< "cannot call operator __uuidof on a type with multiple GUIDs">; def err_incomplete_typeid : Error<"'typeid' of incomplete type %0">; +def err_variably_modified_typeid : Error<"'typeid' of variably modified type %0">; def err_static_illegal_in_new : Error< "the 'static' modifier for the array size is not legal in new expressions">; def err_array_new_needs_size : Error< @@ -5206,15 +5372,18 @@ def err_address_space_qualified_delete : Error< def err_default_init_const : Error< "default initialization of an object of const type %0" - "%select{| requires a user-provided default constructor}1">; + "%select{| without a user-provided default constructor}1">; +def note_add_initializer : Note< + "add an explicit initializer to initialize %0">; def err_delete_operand : Error<"cannot delete expression of type %0">; def ext_delete_void_ptr_operand : ExtWarn< - "cannot delete expression with pointer-to-'void' type %0">; + "cannot delete expression with pointer-to-'void' type %0">, + InGroup<DeleteIncomplete>; def err_ambiguous_delete_operand : Error< "ambiguous conversion of delete expression of type %0 to a pointer">; def warn_delete_incomplete : Warning< "deleting pointer to incomplete type %0 may cause undefined behavior">, - InGroup<DiagGroup<"delete-incomplete">>; + InGroup<DeleteIncomplete>; def err_delete_incomplete_class_type : Error< "deleting incomplete class type %0; no conversions to pointer type">; def err_delete_explicit_conversion : Error< @@ -5323,9 +5492,6 @@ let CategoryName = "Lambda Issue" in { "'this' cannot be %select{implicitly |}0captured in this context">; def err_lambda_capture_anonymous_var : Error< "unnamed variable cannot be implicitly captured in a lambda expression">; - def err_lambda_capture_vm_type : Error< - "variable %0 with variably modified type cannot be captured in " - "a lambda expression">; def err_lambda_capture_flexarray_type : Error< "variable %0 with flexible array member cannot be captured in " "a lambda expression">; @@ -5361,12 +5527,12 @@ let CategoryName = "Lambda Issue" in { "implicit capture of lambda object due to conversion to block pointer " "here">; - // C++1y lambda init-captures. + // C++14 lambda init-captures. def warn_cxx11_compat_init_capture : Warning< "initialized lambda captures are incompatible with C++ standards " - "before C++1y">, InGroup<CXXPre1yCompat>, DefaultIgnore; + "before C++14">, InGroup<CXXPre14Compat>, DefaultIgnore; def ext_init_capture : ExtWarn< - "initialized lambda captures are a C++1y extension">, InGroup<CXX1y>; + "initialized lambda captures are a C++14 extension">, InGroup<CXX14>; def err_init_capture_no_expression : Error< "initializer missing for lambda capture %0">; def err_init_capture_multiple_expressions : Error< @@ -5936,13 +6102,19 @@ def warn_unused_voidptr : Warning< InGroup<UnusedValue>; def warn_unused_property_expr : Warning< "property access result unused - getters should not be used for side effects">, - InGroup<UnusedValue>; + InGroup<UnusedGetterReturnValue>; def warn_unused_container_subscript_expr : Warning< "container access result unused - container access should not be used for side effects">, InGroup<UnusedValue>; def warn_unused_call : Warning< "ignoring return value of function declared with %0 attribute">, InGroup<UnusedValue>; +def warn_side_effects_unevaluated_context : Warning< + "expression with side effects has no effect in an unevaluated context">, + InGroup<UnevaluatedExpression>; +def warn_side_effects_typeid : Warning< + "expression with side effects will be evaluated despite being used as an " + "operand to 'typeid'">, InGroup<PotentiallyEvaluatedExpression>; def warn_unused_result : Warning< "ignoring return value of function declared with warn_unused_result " "attribute">, InGroup<DiagGroup<"unused-result">>; @@ -5974,11 +6146,15 @@ def warn_zero_size_struct_union_compat : Warning<"%select{|empty }0" def warn_zero_size_struct_union_in_extern_c : Warning<"%select{|empty }0" "%select{struct|union}1 has size 0 in C, %select{size 1|non-zero size}2 in C++">, InGroup<ExternCCompat>; +def warn_cast_qual : Warning<"cast from %0 to %1 drops %select{const and " + "volatile qualifiers|const qualifier|volatile qualifier}2">, + InGroup<CastQual>, DefaultIgnore; +def warn_cast_qual2 : Warning<"cast from %0 to %1 must have all intermediate " + "pointers const qualified to be safe">, InGroup<CastQual>, DefaultIgnore; } // End of general sema category. // inline asm. let CategoryName = "Inline Assembly Issue" in { - def err_asm_wide_character : Error<"wide string is invalid in 'asm'">; def err_asm_invalid_lvalue_in_output : Error<"invalid lvalue in asm output">; def err_asm_invalid_output_constraint : Error< "invalid output constraint '%0' in asm">; @@ -5991,14 +6167,20 @@ let CategoryName = "Inline Assembly Issue" in { def err_asm_tying_incompatible_types : Error< "unsupported inline asm: input with type " "%diff{$ matching output with type $|}0,1">; + def err_asm_unexpected_constraint_alternatives : Error< + "asm constraint has an unexpected number of alternatives: %0 vs %1">; def err_asm_incomplete_type : Error<"asm operand has incomplete type %0">; def err_asm_unknown_register_name : Error<"unknown register name '%0' in asm">; def err_asm_bad_register_type : Error<"bad type for named register variable">; def err_asm_invalid_input_size : Error< "invalid input size for constraint '%0'">; + def err_asm_invalid_output_size : Error< + "invalid output size for constraint '%0'">; def err_invalid_asm_cast_lvalue : Error< "invalid use of a cast in a inline asm context requiring an l-value: " "remove the cast or build with -fheinous-gnu-extensions">; + def err_invalid_asm_value_for_constraint + : Error <"value '%0' out of range for constraint '%1'">; def warn_asm_label_on_auto_decl : Warning< "ignored asm label '%0' on automatic variable">; @@ -6010,6 +6192,9 @@ let CategoryName = "Inline Assembly Issue" in { "value size does not match register size specified by the constraint " "and modifier">, InGroup<ASMOperandWidths>; + + def note_asm_missing_constraint_modifier : Note< + "use constraint modifier \"%0\"">; } let CategoryName = "Semantic Issue" in { @@ -6080,9 +6265,12 @@ def err_in_class_initializer_literal_type : Error< "'constexpr' specifier">; def err_in_class_initializer_non_constant : Error< "in-class initializer for static data member is not a constant expression">; -def err_in_class_initializer_references_def_ctor : Error< - "defaulted default constructor of %0 cannot be used by non-static data " - "member initializer which appears before end of class definition">; +def err_in_class_initializer_not_yet_parsed + : Error<"cannot use defaulted default constructor of %0 within the class " + "outside of member functions because %1 has an initializer">; +def err_in_class_initializer_not_yet_parsed_outer_class + : Error<"cannot use defaulted default constructor of %0 within " + "%1 outside of member functions because %2 has an initializer">; def ext_in_class_initializer_non_constant : Extension< "in-class initializer for static data member is not a constant expression; " @@ -6130,8 +6318,9 @@ def err_anonymous_record_bad_member : Error< def err_anonymous_record_nonpublic_member : Error< "anonymous %select{struct|union}0 cannot contain a " "%select{private|protected}1 data member">; -def ext_ms_anonymous_struct : ExtWarn< - "anonymous structs are a Microsoft extension">, InGroup<Microsoft>; +def ext_ms_anonymous_record : ExtWarn< + "anonymous %select{structs|unions}0 are a Microsoft extension">, + InGroup<Microsoft>; // C++ local classes def err_reference_to_local_var_in_enclosing_function : Error< @@ -6267,7 +6456,13 @@ def err_conv_function_to_array : Error< def err_conv_function_to_function : Error< "conversion function cannot convert to a function type">; def err_conv_function_with_complex_decl : Error< - "must use a typedef to declare a conversion to %0">; + "cannot specify any part of a return type in the " + "declaration of a conversion function" + "%select{" + "; put the complete type after 'operator'|" + "; use a typedef to declare a conversion to %1|" + "; use an alias template to declare a conversion to %1|" + "}0">; def err_conv_function_redeclared : Error< "conversion function cannot be redeclared">; def warn_conv_to_self_not_used : Warning< @@ -6435,7 +6630,7 @@ def note_format_fix_specifier : Note<"did you mean to use '%0'?">; def note_printf_c_str: Note<"did you mean to call the %0 method?">; def warn_null_arg : Warning< - "null passed to a callee which requires a non-null argument">, + "null passed to a callee that requires a non-null argument">, InGroup<NonNull>; def warn_null_ret : Warning< "null returned from %select{function|method}0 that requires a non-null return value">, @@ -6744,6 +6939,17 @@ def err_convertvector_non_vector_type : Error< def err_convertvector_incompatible_vector : Error< "first two arguments to __builtin_convertvector must have the same number of elements">; +def err_first_argument_to_cwsc_not_call : Error< + "first argument to __builtin_call_with_static_chain must be a non-member call expression">; +def err_first_argument_to_cwsc_block_call : Error< + "first argument to __builtin_call_with_static_chain must not be a block call">; +def err_first_argument_to_cwsc_builtin_call : Error< + "first argument to __builtin_call_with_static_chain must not be a builtin call">; +def err_first_argument_to_cwsc_pdtor_call : Error< + "first argument to __builtin_call_with_static_chain must not be a pseudo-destructor call">; +def err_second_argument_to_cwsc_not_pointer : Error< + "second argument to __builtin_call_with_static_chain must be of pointer type">; + def err_vector_incorrect_num_initializers : Error< "%select{too many|too few}0 elements in vector initialization (expected %1 elements, have %2)">; def err_altivec_empty_initializer : Error<"expected initializer">; @@ -6801,6 +7007,11 @@ def warn_duplicate_attribute : Warning< "attribute %0 is already applied with different parameters">, InGroup<IgnoredAttributes>; +def warn_sync_fetch_and_nand_semantics_change : Warning< + "the semantics of this intrinsic changed with GCC " + "version 4.4 - the newer semantics are provided here">, + InGroup<DiagGroup<"sync-fetch-and-nand-semantics-changed">>; + // Type def ext_invalid_sign_spec : Extension<"'%0' cannot be signed or unsigned">; def warn_receiver_forward_class : Warning< @@ -6842,6 +7053,13 @@ def err_invalid_protocol_qualifiers : Error< def warn_ivar_use_hidden : Warning< "local declaration of %0 hides instance variable">, InGroup<DiagGroup<"shadow-ivar">>; +def warn_direct_initialize_call : Warning< + "explicit call to +initialize results in duplicate call to +initialize">, + InGroup<ExplicitInitializeCall>; +def warn_direct_super_initialize_call : Warning< + "explicit call to [super initialize] should only be in implementation " + "of +initialize">, + InGroup<ExplicitInitializeCall>; def error_ivar_use_in_class_method : Error< "instance variable %0 accessed in class method">; def error_implicit_ivar_access : Error< @@ -6891,6 +7109,9 @@ def err_property_not_found_suggest : Error< "property %0 not found on object of type %1; did you mean %2?">; def err_ivar_access_using_property_syntax_suggest : Error< "property %0 not found on object of type %1; did you mean to access instance variable %2?">; +def warn_property_access_suggest : Warning< +"property %0 not found on object of type %1; did you mean to access property %2?">, +InGroup<PropertyAccessDotSyntax>; def err_property_found_suggest : Error< "property %0 found on object of type %1; did you mean to access " "it with the \".\" operator?">; @@ -6938,6 +7159,11 @@ def err_unknown_any_function : Error< def err_filter_expression_integral : Error< "filter expression type should be an integral value not %0">; +def err_non_asm_stmt_in_naked_function : Error< + "non-ASM statement in naked function is not supported">; +def err_asm_naked_parm_ref : Error< + "parameter references not allowed in naked functions">; + // OpenCL warnings and errors. def err_invalid_astype_of_different_size : Error< "invalid reinterpretation: sizes of %0 and %1 must match">; @@ -7000,7 +7226,7 @@ def err_omp_var_scope : Error< def err_omp_var_used : Error< "'#pragma omp %0' must precede all references to variable %q1">; def err_omp_var_thread_local : Error< - "variable %0 cannot be threadprivate because it is thread-local">; + "variable %0 cannot be threadprivate because it is %select{thread-local|a global named register variable}1">; def err_omp_private_incomplete_type : Error< "a private variable with incomplete type %0">; def err_omp_firstprivate_incomplete_type : Error< @@ -7015,8 +7241,8 @@ def err_omp_expected_var_name : Error< "expected variable name">; def err_omp_required_method : Error< "%0 variable must have an accessible, unambiguous %select{default constructor|copy constructor|copy assignment operator|'%2'|destructor}1">; -def err_omp_task_predetermined_firstprivate_required_method : Error< - "predetermined as a firstprivate in a task construct variable must have an accessible, unambiguous %select{copy constructor|destructor}0">; +def note_omp_task_predetermined_firstprivate_here : Note< + "predetermined as a firstprivate in a task construct here">; def err_omp_clause_ref_type_arg : Error< "arguments of OpenMP clause '%0' cannot be of reference type %1">; def err_omp_task_predetermined_firstprivate_ref_type_arg : Error< @@ -7044,6 +7270,8 @@ def note_omp_implicit_dsa : Note< "implicitly determined as %0">; def err_omp_loop_var_dsa : Error< "loop iteration variable in the associated loop of 'omp %1' directive may not be %0, predetermined as %2">; +def err_omp_global_loop_var_dsa : Error< + "loop iteration variable in the associated loop of 'omp %1' directive may not be a variable with global storage without being explicitly marked as %0">; def err_omp_not_for : Error< "%select{statement after '#pragma omp %1' must be a for loop|" "expected %2 for loops after '#pragma omp %1'%select{|, but found only %4}3}0">; @@ -7075,6 +7303,9 @@ def err_omp_linear_expected_int_or_ptr : Error< def warn_omp_linear_step_zero : Warning< "zero linear step (%0 %select{|and other variables in clause }1should probably be const)">, InGroup<OpenMPClauses>; +def warn_omp_alignment_not_power_of_two : Warning< + "aligned clause will be ignored because the requested alignment is not a power of 2">, + InGroup<OpenMPClauses>; def err_omp_aligned_expected_array_or_ptr : Error< "argument of aligned clause should be array" "%select{ or pointer|, pointer, reference to array or reference to pointer}1" @@ -7102,10 +7333,16 @@ def err_omp_loop_incr_not_compatible : Error< "on each iteration of OpenMP for loop">; def note_omp_loop_cond_requres_compatible_incr : Note< "loop step is expected to be %select{negative|positive}0 due to this condition">; +def err_omp_loop_diff_cxx : Error< + "could not calculate number of iterations calling 'operator-' with " + "upper and lower loop bounds">; def err_omp_loop_cannot_use_stmt : Error< "'%0' statement cannot be used in OpenMP for loop">; def err_omp_simd_region_cannot_use_stmt : Error< "'%0' statement cannot be used in OpenMP simd region">; +def warn_omp_loop_64_bit_var : Warning< + "OpenMP loop iteration variable cannot have more than 64 bits size and will be narrowed">, + InGroup<OpenMPLoopForm>; def err_omp_unknown_reduction_identifier : Error< "incorrect reduction identifier, expected one of '+', '-', '*', '&', '|', '^', '&&', '||', 'min' or 'max'">; def err_omp_reduction_type_array : Error< @@ -7126,9 +7363,13 @@ def err_omp_reduction_id_not_compatible : Error< "variable of type %0 is not valid for specified reduction operation">; def err_omp_prohibited_region : Error< "region cannot be%select{| closely}0 nested inside '%1' region" - "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?}2">; + "%select{|; perhaps you forget to enclose 'omp %3' directive into a parallel region?|" + "; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?|" + "; perhaps you forget to enclose 'omp %3' directive into a target region?}2">; def err_omp_prohibited_region_simd : Error< "OpenMP constructs may not be nested inside a simd region">; +def err_omp_prohibited_region_atomic : Error< + "OpenMP constructs may not be nested inside an atomic region">; def err_omp_prohibited_region_critical_same_name : Error< "cannot nest 'critical' regions having the same name %0">; def note_omp_previous_critical_region : Note< @@ -7146,6 +7387,35 @@ def err_omp_parallel_sections_substmt_not_section : Error< "statement in 'omp parallel sections' directive must be enclosed into a section region">; def err_omp_parallel_reduction_in_task_firstprivate : Error< "argument of a reduction clause of a %0 construct must not appear in a firstprivate clause on a task construct">; +def err_omp_atomic_read_not_expression_statement : Error< + "the statement for 'atomic read' must be an expression statement of form 'v = x;'," + " where v and x are both lvalue expressions with scalar type">; +def note_omp_atomic_read_write: Note< + "%select{expected an expression statement|expected built-in assignment operator|expected expression of scalar type|expected lvalue expression}0">; +def err_omp_atomic_write_not_expression_statement : Error< + "the statement for 'atomic write' must be an expression statement of form 'x = expr;'," + " where x is a lvalue expression with scalar type">; +def err_omp_atomic_update_not_expression_statement : Error< + "the statement for 'atomic%select{| update}0' must be an expression statement of form '++x;', '--x;', 'x++;', 'x--;', 'x binop= expr;', 'x = x binop expr' or 'x = expr binop x'," + " where x is an l-value expression with scalar type">; +def err_omp_atomic_capture_not_expression_statement : Error< + "the statement for 'atomic capture' must be an expression statement of form 'v = ++x;', 'v = --x;', 'v = x++;', 'v = x--;', 'v = x binop= expr;', 'v = x = x binop expr' or 'v = x = expr binop x'," + " where x and v are both l-value expressions with scalar type">; +def err_omp_atomic_capture_not_compound_statement : Error< + "the statement for 'atomic capture' must be a compound statement of form '{v = x; x binop= expr;}', '{x binop= expr; v = x;}'," + " '{v = x; x = x binop expr;}', '{v = x; x = expr binop x;}', '{x = x binop expr; v = x;}', '{x = expr binop x; v = x;}' or '{v = x; x = expr;}'," + " '{v = x; x++;}', '{v = x; ++x;}', '{++x; v = x;}', '{x++; v = x;}', '{v = x; x--;}', '{v = x; --x;}', '{--x; v = x;}', '{x--; v = x;}'" + " where x is an l-value expression with scalar type">; +def err_omp_atomic_several_clauses : Error< + "directive '#pragma omp atomic' cannot contain more than one 'read', 'write', 'update' or 'capture' clause">; +def note_omp_atomic_previous_clause : Note< + "'%0' clause used here">; +def err_omp_target_contains_not_only_teams : Error< + "target construct with nested teams region contains statements outside of the teams construct">; +def note_omp_nested_teams_construct_here : Note< + "nested teams construct here">; +def note_omp_nested_statement_here : Note< + "%select{statement|directive}0 outside teams construct here">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { @@ -7197,6 +7467,8 @@ def err_module_import_not_at_top_level : Error< def note_module_import_not_at_top_level : Note<"%0 begins here">; def err_module_self_import : Error< "import of module '%0' appears within same top-level module '%1'">; +def err_module_import_in_implementation : Error< + "@import of module '%0' in implementation of '%1'; use #import">; } let CategoryName = "Documentation Issue" in { diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index be9d2bdbd2de..a685db0137f5 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -52,10 +52,18 @@ def err_pch_with_compiler_errors : Error< "PCH file contains compiler errors">; def err_imported_module_not_found : Error< - "module '%0' imported by AST file '%1' not found">, DefaultFatal; + "module '%0' in AST file '%1' (imported by AST file '%2') " + "is not defined in any loaded module map file; " + "maybe you need to load '%3'?">, DefaultFatal; def err_imported_module_modmap_changed : Error< "module '%0' imported by AST file '%1' found in a different module map file" " (%2) than when the importing AST file was built (%3)">, DefaultFatal; +def err_imported_module_relocated : Error< + "module '%0' was built in directory '%1' but now resides in " + "directory '%2'">, DefaultFatal; +def err_module_different_modmap : Error< + "module '%0' %select{uses|does not use}1 additional module map '%2'" + "%select{| not}1 used when the module was built">; def warn_module_conflict : Warning< "module '%0' conflicts with already-imported module '%1': %2">, InGroup<ModuleConflict>; diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h index edd89ec709d7..132b5ba1e5a7 100644 --- a/include/clang/Basic/ExceptionSpecificationType.h +++ b/include/clang/Basic/ExceptionSpecificationType.h @@ -26,7 +26,8 @@ enum ExceptionSpecificationType { EST_BasicNoexcept, ///< noexcept EST_ComputedNoexcept, ///< noexcept(expression) EST_Unevaluated, ///< not evaluated yet, for special member function - EST_Uninstantiated ///< not instantiated yet + EST_Uninstantiated, ///< not instantiated yet + EST_Unparsed ///< not parsed yet }; inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) { diff --git a/include/clang/Basic/ExpressionTraits.h b/include/clang/Basic/ExpressionTraits.h index e87771572129..0363a1d2c74c 100644 --- a/include/clang/Basic/ExpressionTraits.h +++ b/include/clang/Basic/ExpressionTraits.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_EXPRESSIONTRAITS_H -#define LLVM_CLANG_EXPRESSIONTRAITS_H +#ifndef LLVM_CLANG_BASIC_EXPRESSIONTRAITS_H +#define LLVM_CLANG_BASIC_EXPRESSIONTRAITS_H namespace clang { diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index 0ad53c4df5ac..bd3f27ab9e5e 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FILEMANAGER_H -#define LLVM_CLANG_FILEMANAGER_H +#ifndef LLVM_CLANG_BASIC_FILEMANAGER_H +#define LLVM_CLANG_BASIC_FILEMANAGER_H #include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/LLVM.h" @@ -59,7 +59,7 @@ public: /// If the 'File' member is valid, then this FileEntry has an open file /// descriptor for the file. class FileEntry { - std::string Name; // Name of the file. + const char *Name; // Name of the file. off_t Size; // File size in bytes. time_t ModTime; // Modification time of file. const DirectoryEntry *Dir; // Directory file lives in. @@ -93,7 +93,7 @@ public: assert(!isValid() && "Cannot copy an initialized FileEntry"); } - const char *getName() const { return Name.c_str(); } + const char *getName() const { return Name; } bool isValid() const { return IsValid; } off_t getSize() const { return Size; } unsigned getUID() const { return UID; } @@ -194,7 +194,8 @@ public: /// \param AtBeginning whether this new stat cache must be installed at the /// beginning of the chain of stat caches. Otherwise, it will be added to /// the end of the chain. - void addStatCache(FileSystemStatCache *statCache, bool AtBeginning = false); + void addStatCache(std::unique_ptr<FileSystemStatCache> statCache, + bool AtBeginning = false); /// \brief Removes the specified FileSystemStatCache object from the manager. void removeStatCache(FileSystemStatCache *statCache); @@ -240,12 +241,11 @@ public: /// \brief Open the specified file as a MemoryBuffer, returning a new /// MemoryBuffer if successful, otherwise returning null. - llvm::MemoryBuffer *getBufferForFile(const FileEntry *Entry, - std::string *ErrorStr = nullptr, - bool isVolatile = false, - bool ShouldCloseOpenFile = true); - llvm::MemoryBuffer *getBufferForFile(StringRef Filename, - std::string *ErrorStr = nullptr); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + getBufferForFile(const FileEntry *Entry, bool isVolatile = false, + bool ShouldCloseOpenFile = true); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + getBufferForFile(StringRef Filename); /// \brief Get the 'stat' information for the given \p Path. /// @@ -274,6 +274,9 @@ public: static void modifyFileEntry(FileEntry *File, off_t Size, time_t ModificationTime); + /// \brief Remove any './' components from a path. + static bool removeDotPaths(SmallVectorImpl<char> &Path); + /// \brief Retrieve the canonical name for a given directory. /// /// This is a very expensive operation, despite its results being cached, diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h index 9be8b1074b2f..cad91893489b 100644 --- a/include/clang/Basic/FileSystemStatCache.h +++ b/include/clang/Basic/FileSystemStatCache.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FILESYSTEMSTATCACHE_H -#define LLVM_CLANG_FILESYSTEMSTATCACHE_H +#ifndef LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H +#define LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" @@ -74,8 +74,8 @@ public: /// \brief Sets the next stat call cache in the chain of stat caches. /// Takes ownership of the given stat cache. - void setNextStatCache(FileSystemStatCache *Cache) { - NextStatCache.reset(Cache); + void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) { + NextStatCache = std::move(Cache); } /// \brief Retrieve the next stat call cache in the chain. @@ -84,7 +84,9 @@ public: /// \brief Retrieve the next stat call cache in the chain, transferring /// ownership of this cache (and, transitively, all of the remaining caches) /// to the caller. - FileSystemStatCache *takeNextStatCache() { return NextStatCache.release(); } + std::unique_ptr<FileSystemStatCache> takeNextStatCache() { + return std::move(NextStatCache); + } protected: // FIXME: The pointer here is a non-owning/optional reference to the diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 0c278a17a32d..1de9dd1c0e10 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -249,6 +249,9 @@ public: } bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } + /// \brief Return true if this token is a keyword in the specified language. + bool isKeyword(const LangOptions &LangOpts); + /// getFETokenInfo/setFETokenInfo - The language front-end is allowed to /// associate arbitrary metadata with this token. template<typename T> @@ -444,26 +447,21 @@ public: /// \brief Return the identifier token info for the specified named /// identifier. IdentifierInfo &get(StringRef Name) { - llvm::StringMapEntry<IdentifierInfo*> &Entry = - HashTable.GetOrCreateValue(Name); + auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first; - IdentifierInfo *II = Entry.getValue(); + IdentifierInfo *&II = Entry.second; if (II) return *II; // No entry; if we have an external lookup, look there first. if (ExternalLookup) { II = ExternalLookup->get(Name); - if (II) { - // Cache in the StringMap for subsequent lookups. - Entry.setValue(II); + if (II) return *II; - } } // Lookups failed, make a new IdentifierInfo. void *Mem = getAllocator().Allocate<IdentifierInfo>(); II = new (Mem) IdentifierInfo(); - Entry.setValue(II); // Make sure getName() knows how to find the IdentifierInfo // contents. @@ -486,25 +484,23 @@ public: /// introduce or modify an identifier. If they called get(), they would /// likely end up in a recursion. IdentifierInfo &getOwn(StringRef Name) { - llvm::StringMapEntry<IdentifierInfo*> &Entry = - HashTable.GetOrCreateValue(Name); - - IdentifierInfo *II = Entry.getValue(); - if (!II) { - - // Lookups failed, make a new IdentifierInfo. - void *Mem = getAllocator().Allocate<IdentifierInfo>(); - II = new (Mem) IdentifierInfo(); - Entry.setValue(II); - - // Make sure getName() knows how to find the IdentifierInfo - // contents. - II->Entry = &Entry; - - // If this is the 'import' contextual keyword, mark it as such. - if (Name.equals("import")) - II->setModulesImport(true); - } + auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first; + + IdentifierInfo *&II = Entry.second; + if (II) + return *II; + + // Lookups failed, make a new IdentifierInfo. + void *Mem = getAllocator().Allocate<IdentifierInfo>(); + II = new (Mem) IdentifierInfo(); + + // Make sure getName() knows how to find the IdentifierInfo + // contents. + II->Entry = &Entry; + + // If this is the 'import' contextual keyword, mark it as such. + if (Name.equals("import")) + II->setModulesImport(true); return *II; } @@ -563,6 +559,7 @@ enum ObjCMethodFamily { OMF_retain, OMF_retainCount, OMF_self, + OMF_initialize, // performSelector families OMF_performSelector @@ -588,6 +585,12 @@ enum ObjCInstanceTypeFamily { OIT_ReturnsSelf }; +enum ObjCStringFormatFamily { + SFF_None, + SFF_NSString, + SFF_CFString +}; + /// \brief Smart pointer class that efficiently represents Objective-C method /// names. /// @@ -633,6 +636,8 @@ class Selector { } static ObjCMethodFamily getMethodFamilyImpl(Selector sel); + + static ObjCStringFormatFamily getStringFormatFamilyImpl(Selector sel); public: friend class SelectorTable; // only the SelectorTable can create these @@ -703,7 +708,11 @@ public: ObjCMethodFamily getMethodFamily() const { return getMethodFamilyImpl(*this); } - + + ObjCStringFormatFamily getStringFormatFamily() const { + return getStringFormatFamilyImpl(*this); + } + static Selector getEmptyMarker() { return Selector(uintptr_t(-1)); } diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h index 5a71fa85b3d9..3e01d25add2d 100644 --- a/include/clang/Basic/LLVM.h +++ b/include/clang/Basic/LLVM.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef CLANG_BASIC_LLVM_H -#define CLANG_BASIC_LLVM_H +#ifndef LLVM_CLANG_BASIC_LLVM_H +#define LLVM_CLANG_BASIC_LLVM_H // Do not proliferate #includes here, require clients to #include their // dependencies. diff --git a/include/clang/Basic/Lambda.h b/include/clang/Basic/Lambda.h index 280ae94fedc5..e676e726dd7a 100644 --- a/include/clang/Basic/Lambda.h +++ b/include/clang/Basic/Lambda.h @@ -34,7 +34,8 @@ enum LambdaCaptureDefault { enum LambdaCaptureKind { LCK_This, ///< Capturing the \c this pointer LCK_ByCopy, ///< Capturing by copy (a.k.a., by value) - LCK_ByRef ///< Capturing by reference + LCK_ByRef, ///< Capturing by reference + LCK_VLAType ///< Capturing variable-length array type }; } // end namespace clang diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index a297a4c219cf..cf9638d7ea81 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -9,26 +9,40 @@ // // This file defines the language options. Users of this file must // define the LANGOPT macro to make use of this information. -// Optionally, the user may also define BENIGN_LANGOPT -// (for options that don't affect the construction of the AST in an -// incompatible way), ENUM_LANGOPT (for options that have enumeration, -// rather than unsigned, type), BENIGN_ENUM_LANGOPT (for benign -// options that have enumeration type), and VALUE_LANGOPT is a language option -// that describes a value rather than a flag. // +// Optionally, the user may also define: +// +// BENIGN_LANGOPT: for options that don't affect the construction of the AST in +// any way (that is, the value can be different between an implicit module +// and the user of that module). +// +// COMPATIBLE_LANGOPT: for options that affect the construction of the AST in +// a way that doesn't prevent interoperability (that is, the value can be +// different between an explicit module and the user of that module). +// +// ENUM_LANGOPT: for options that have enumeration, rather than unsigned, type. +// +// VALUE_LANGOPT: for options that describe a value rather than a flag. +// +// BENIGN_ENUM_LANGOPT, COMPATIBLE_ENUM_LANGOPT: combinations of the above. +// +// FIXME: Clients should be able to more easily select whether they want +// different levels of compatibility versus how to handle different kinds +// of option. //===----------------------------------------------------------------------===// + #ifndef LANGOPT # error Define the LANGOPT macro to handle language options #endif -#ifndef VALUE_LANGOPT -# define VALUE_LANGOPT(Name, Bits, Default, Description) \ +#ifndef COMPATIBLE_LANGOPT +# define COMPATIBLE_LANGOPT(Name, Bits, Default, Description) \ LANGOPT(Name, Bits, Default, Description) #endif #ifndef BENIGN_LANGOPT # define BENIGN_LANGOPT(Name, Bits, Default, Description) \ - LANGOPT(Name, Bits, Default, Description) + COMPATIBLE_LANGOPT(Name, Bits, Default, Description) #endif #ifndef ENUM_LANGOPT @@ -36,11 +50,22 @@ LANGOPT(Name, Bits, Default, Description) #endif +#ifndef COMPATIBLE_ENUM_LANGOPT +# define COMPATIBLE_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ + ENUM_LANGOPT(Name, Type, Bits, Default, Description) +#endif + #ifndef BENIGN_ENUM_LANGOPT # define BENIGN_ENUM_LANGOPT(Name, Type, Bits, Default, Description) \ - ENUM_LANGOPT(Name, Type, Bits, Default, Description) + COMPATIBLE_ENUM_LANGOPT(Name, Type, Bits, Default, Description) #endif +#ifndef VALUE_LANGOPT +# define VALUE_LANGOPT(Name, Bits, Default, Description) \ + LANGOPT(Name, Bits, Default, Description) +#endif + +// FIXME: A lot of the BENIGN_ options should be COMPATIBLE_ instead. LANGOPT(C99 , 1, 0, "C99") LANGOPT(C11 , 1, 0, "C11") LANGOPT(MSVCCompat , 1, 0, "Microsoft Visual C++ full compatibility mode") @@ -49,7 +74,7 @@ LANGOPT(AsmBlocks , 1, 0, "Microsoft inline asm blocks") LANGOPT(Borland , 1, 0, "Borland extensions") LANGOPT(CPlusPlus , 1, 0, "C++") LANGOPT(CPlusPlus11 , 1, 0, "C++11") -LANGOPT(CPlusPlus1y , 1, 0, "C++1y") +LANGOPT(CPlusPlus14 , 1, 0, "C++14") LANGOPT(CPlusPlus1z , 1, 0, "C++1z") LANGOPT(ObjC1 , 1, 0, "Objective-C 1") LANGOPT(ObjC2 , 1, 0, "Objective-C 2") @@ -101,16 +126,19 @@ LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") LANGOPT(ModulesSearchAll , 1, 1, "search even non-imported modules to find unresolved references") LANGOPT(ModulesStrictDeclUse, 1, 0, "require declaration of module uses and all headers to be in modules") LANGOPT(ModulesErrorRecovery, 1, 1, "automatically import modules as needed when performing error recovery") -LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") -LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro") +BENIGN_LANGOPT(ModulesImplicitMaps, 1, 1, "use files called module.modulemap implicitly as module maps") +COMPATIBLE_LANGOPT(Optimize , 1, 0, "__OPTIMIZE__ predefined macro") +COMPATIBLE_LANGOPT(OptimizeSize , 1, 0, "__OPTIMIZE_SIZE__ predefined macro") LANGOPT(Static , 1, 0, "__STATIC__ predefined macro (as opposed to __DYNAMIC__)") VALUE_LANGOPT(PackStruct , 32, 0, "default struct packing maximum alignment") +VALUE_LANGOPT(MaxTypeAlign , 32, 0, + "default maximum alignment for types") VALUE_LANGOPT(PICLevel , 2, 0, "__PIC__ level") VALUE_LANGOPT(PIELevel , 2, 0, "__PIE__ level") LANGOPT(GNUInline , 1, 0, "GNU inline semantics") -LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro") -LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") +COMPATIBLE_LANGOPT(NoInlineDefine , 1, 0, "__NO_INLINE__ predefined macro") +COMPATIBLE_LANGOPT(Deprecated , 1, 0, "__DEPRECATED predefined macro") LANGOPT(FastMath , 1, 0, "__FAST_MATH__ predefined macro") LANGOPT(FiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined macro") @@ -126,8 +154,10 @@ LANGOPT(ShortEnums , 1, 0, "short enum types") LANGOPT(OpenCL , 1, 0, "OpenCL") LANGOPT(OpenCLVersion , 32, 0, "OpenCL version") LANGOPT(NativeHalfType , 1, 0, "Native half type support") +LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns") LANGOPT(CUDA , 1, 0, "CUDA") LANGOPT(OpenMP , 1, 0, "OpenMP support") +LANGOPT(CUDAIsDevice , 1, 0, "Compiling for CUDA device") LANGOPT(AssumeSaneOperatorNew , 1, 1, "implicit __attribute__((malloc)) for C++'s new operators") LANGOPT(SizedDeallocation , 1, 0, "enable sized deallocation functions") @@ -187,9 +217,15 @@ LANGOPT(ApplePragmaPack, 1, 0, "Apple gcc-compatible #pragma pack handling") LANGOPT(RetainCommentsFromSystemHeaders, 1, 0, "retain documentation comments from system headers in the AST") +LANGOPT(SanitizeAddressFieldPadding, 2, 0, "controls how aggressive is ASan " + "field padding (0: none, 1:least " + "aggressive, 2: more aggressive)") + #undef LANGOPT -#undef VALUE_LANGOPT +#undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT #undef ENUM_LANGOPT +#undef COMPATIBLE_ENUM_LANGOPT #undef BENIGN_ENUM_LANGOPT +#undef VALUE_LANGOPT diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 9bffc7cb18cf..5ac96c519855 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -12,25 +12,18 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LANGOPTIONS_H -#define LLVM_CLANG_LANGOPTIONS_H +#ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H +#define LLVM_CLANG_BASIC_LANGOPTIONS_H #include "clang/Basic/CommentOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/Sanitizers.h" #include "clang/Basic/Visibility.h" #include <string> namespace clang { -struct SanitizerOptions { -#define SANITIZER(NAME, ID) unsigned ID : 1; -#include "clang/Basic/Sanitizers.def" - - /// \brief Cached set of sanitizer options with all sanitizers disabled. - static const SanitizerOptions Disabled; -}; - /// Bitfields of LangOptions, split out from LangOptions in order to ensure that /// this large collection of bitfields is a trivial class type. class LangOptionsBase { @@ -40,7 +33,6 @@ public: #define ENUM_LANGOPT(Name, Type, Bits, Default, Description) #include "clang/Basic/LangOptions.def" - SanitizerOptions Sanitize; protected: // Define language options of enumeration type. These are private, and will // have accessors (below). @@ -75,6 +67,13 @@ public: enum AddrSpaceMapMangling { ASMM_Target, ASMM_On, ASMM_Off }; public: + /// \brief Set of enabled sanitizers. + SanitizerSet Sanitize; + + /// \brief Path to blacklist file specifying which objects + /// (files, functions, variables) should not be instrumented. + std::string SanitizerBlacklistFile; + clang::ObjCRuntime ObjCRuntime; std::string ObjCConstantStringClass; @@ -88,6 +87,11 @@ public: /// \brief The name of the current module. std::string CurrentModule; + /// \brief The name of the module that the translation unit is an + /// implementation of. Prevents semantic imports, but does not otherwise + /// treat this as the CurrentModule. + std::string ImplementationOfModule; + /// \brief Options for parsing comments. CommentOptions CommentOpts; diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 9b66840ba412..e3953a4571fa 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -56,17 +56,11 @@ public: /// module. Module *Parent; - /// \brief The module map file that (along with the module name) uniquely - /// identifies this module. - /// - /// The particular module that \c Name refers to may depend on how the module - /// was found in header search. However, the combination of \c Name and - /// \c ModuleMap will be globally unique for top-level modules. In the case of - /// inferred modules, \c ModuleMap will contain the module map that allowed - /// the inference (e.g. contained 'Module *') rather than the virtual - /// inferred module map file. - const FileEntry *ModuleMap; - + /// \brief The build directory of this module. This is the directory in + /// which the module is notionally built, and relative to which its headers + /// are found. + const DirectoryEntry *Directory; + /// \brief The umbrella header or directory. llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella; @@ -92,18 +86,28 @@ private: mutable llvm::DenseSet<const Module*> VisibleModulesCache; public: - /// \brief The headers that are part of this module. - SmallVector<const FileEntry *, 2> NormalHeaders; - - /// \brief The headers that are explicitly excluded from this module. - SmallVector<const FileEntry *, 2> ExcludedHeaders; - - /// \brief The headers that are private to this module. - SmallVector<const FileEntry *, 2> PrivateHeaders; + enum HeaderKind { + HK_Normal, + HK_Textual, + HK_Private, + HK_PrivateTextual, + HK_Excluded + }; + static const int NumHeaderKinds = HK_Excluded + 1; /// \brief Information about a header directive as found in the module map /// file. - struct HeaderDirective { + struct Header { + std::string NameAsWritten; + const FileEntry *Entry; + }; + + /// \brief The headers that are part of this module. + SmallVector<Header, 2> Headers[5]; + + /// \brief Stored information about a header directive that was found in the + /// module map file but has not been resolved to a file. + struct UnresolvedHeaderDirective { SourceLocation FileNameLoc; std::string FileName; bool IsUmbrella; @@ -111,7 +115,7 @@ public: /// \brief Headers that are mentioned in the module map file but could not be /// found on the file system. - SmallVector<HeaderDirective, 1> MissingHeaders; + SmallVector<UnresolvedHeaderDirective, 1> MissingHeaders; /// \brief An individual requirement: a feature name and a flag indicating /// the required state of that feature. @@ -283,10 +287,8 @@ public: std::vector<Conflict> Conflicts; /// \brief Construct a new module or submodule. - /// - /// For an explanation of \p ModuleMap, see Module::ModuleMap. Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, - const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit); + bool IsFramework, bool IsExplicit); ~Module(); @@ -308,7 +310,7 @@ public: bool isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, Requirement &Req, - HeaderDirective &MissingHeader) const; + UnresolvedHeaderDirective &MissingHeader) const; /// \brief Determine whether this module is a submodule. bool isSubModule() const { return Parent != nullptr; } diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index fa375f4e183e..e33587d8f30f 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_OBJCRUNTIME_H -#define LLVM_CLANG_OBJCRUNTIME_H +#ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H +#define LLVM_CLANG_BASIC_OBJCRUNTIME_H #include "clang/Basic/VersionTuple.h" #include "llvm/ADT/Triple.h" diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index 6cfa5ea549f1..0145db059329 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -30,6 +30,9 @@ #ifndef OPENMP_FOR_CLAUSE # define OPENMP_FOR_CLAUSE(Name) #endif +#ifndef OPENMP_FOR_SIMD_CLAUSE +# define OPENMP_FOR_SIMD_CLAUSE(Name) +#endif #ifndef OPENMP_SECTIONS_CLAUSE # define OPENMP_SECTIONS_CLAUSE(Name) #endif @@ -39,12 +42,24 @@ #ifndef OPENMP_PARALLEL_FOR_CLAUSE # define OPENMP_PARALLEL_FOR_CLAUSE(Name) #endif +#ifndef OPENMP_PARALLEL_FOR_SIMD_CLAUSE +# define OPENMP_PARALLEL_FOR_SIMD_CLAUSE(Name) +#endif #ifndef OPENMP_PARALLEL_SECTIONS_CLAUSE # define OPENMP_PARALLEL_SECTIONS_CLAUSE(Name) #endif #ifndef OPENMP_TASK_CLAUSE # define OPENMP_TASK_CLAUSE(Name) #endif +#ifndef OPENMP_ATOMIC_CLAUSE +# define OPENMP_ATOMIC_CLAUSE(Name) +#endif +#ifndef OPENMP_TARGET_CLAUSE +# define OPENMP_TARGET_CLAUSE(Name) +#endif +#ifndef OPENMP_TEAMS_CLAUSE +# define OPENMP_TEAMS_CLAUSE(Name) +#endif #ifndef OPENMP_DEFAULT_KIND # define OPENMP_DEFAULT_KIND(Name) #endif @@ -70,8 +85,14 @@ OPENMP_DIRECTIVE(taskyield) OPENMP_DIRECTIVE(barrier) OPENMP_DIRECTIVE(taskwait) OPENMP_DIRECTIVE(flush) +OPENMP_DIRECTIVE(ordered) +OPENMP_DIRECTIVE(atomic) +OPENMP_DIRECTIVE(target) +OPENMP_DIRECTIVE(teams) OPENMP_DIRECTIVE_EXT(parallel_for, "parallel for") +OPENMP_DIRECTIVE_EXT(parallel_for_simd, "parallel for simd") OPENMP_DIRECTIVE_EXT(parallel_sections, "parallel sections") +OPENMP_DIRECTIVE_EXT(for_simd, "for simd") // OpenMP clauses. OPENMP_CLAUSE(if, OMPIfClause) @@ -96,6 +117,11 @@ OPENMP_CLAUSE(nowait, OMPNowaitClause) OPENMP_CLAUSE(untied, OMPUntiedClause) OPENMP_CLAUSE(mergeable, OMPMergeableClause) OPENMP_CLAUSE(flush, OMPFlushClause) +OPENMP_CLAUSE(read, OMPReadClause) +OPENMP_CLAUSE(write, OMPWriteClause) +OPENMP_CLAUSE(update, OMPUpdateClause) +OPENMP_CLAUSE(capture, OMPCaptureClause) +OPENMP_CLAUSE(seq_cst, OMPSeqCstClause) // Clauses allowed for OpenMP directive 'parallel'. OPENMP_PARALLEL_CLAUSE(if) @@ -127,6 +153,18 @@ OPENMP_FOR_CLAUSE(schedule) OPENMP_FOR_CLAUSE(ordered) OPENMP_FOR_CLAUSE(nowait) +// Clauses allowed for directive 'omp for simd'. +OPENMP_FOR_SIMD_CLAUSE(private) +OPENMP_FOR_SIMD_CLAUSE(firstprivate) +OPENMP_FOR_SIMD_CLAUSE(lastprivate) +OPENMP_FOR_SIMD_CLAUSE(reduction) +OPENMP_FOR_SIMD_CLAUSE(schedule) +OPENMP_FOR_SIMD_CLAUSE(collapse) +OPENMP_FOR_SIMD_CLAUSE(nowait) +OPENMP_FOR_SIMD_CLAUSE(safelen) +OPENMP_FOR_SIMD_CLAUSE(linear) +OPENMP_FOR_SIMD_CLAUSE(aligned) + // Clauses allowed for OpenMP directive 'omp sections'. OPENMP_SECTIONS_CLAUSE(private) OPENMP_SECTIONS_CLAUSE(lastprivate) @@ -171,6 +209,23 @@ OPENMP_PARALLEL_FOR_CLAUSE(collapse) OPENMP_PARALLEL_FOR_CLAUSE(schedule) OPENMP_PARALLEL_FOR_CLAUSE(ordered) +// Clauses allowed for OpenMP directive 'parallel for simd'. +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(if) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(num_threads) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(default) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(proc_bind) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(private) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(firstprivate) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(shared) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(reduction) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(copyin) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(lastprivate) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(collapse) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(schedule) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(safelen) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(linear) +OPENMP_PARALLEL_FOR_SIMD_CLAUSE(aligned) + // Clauses allowed for OpenMP directive 'parallel sections'. OPENMP_PARALLEL_SECTIONS_CLAUSE(if) OPENMP_PARALLEL_SECTIONS_CLAUSE(num_threads) @@ -193,6 +248,25 @@ OPENMP_TASK_CLAUSE(shared) OPENMP_TASK_CLAUSE(untied) OPENMP_TASK_CLAUSE(mergeable) +// Clauses allowed for OpenMP directive 'atomic'. +OPENMP_ATOMIC_CLAUSE(read) +OPENMP_ATOMIC_CLAUSE(write) +OPENMP_ATOMIC_CLAUSE(update) +OPENMP_ATOMIC_CLAUSE(capture) +OPENMP_ATOMIC_CLAUSE(seq_cst) + +// Clauses allowed for OpenMP directive 'target'. +// TODO More clauses for 'target' directive. +OPENMP_TARGET_CLAUSE(if) + +// Clauses allowed for OpenMP directive 'teams'. +// TODO More clauses for 'teams' directive. +OPENMP_TEAMS_CLAUSE(default) +OPENMP_TEAMS_CLAUSE(private) +OPENMP_TEAMS_CLAUSE(firstprivate) +OPENMP_TEAMS_CLAUSE(shared) +OPENMP_TEAMS_CLAUSE(reduction) + #undef OPENMP_SCHEDULE_KIND #undef OPENMP_PROC_BIND_KIND #undef OPENMP_DEFAULT_KIND @@ -203,8 +277,13 @@ OPENMP_TASK_CLAUSE(mergeable) #undef OPENMP_SECTIONS_CLAUSE #undef OPENMP_PARALLEL_CLAUSE #undef OPENMP_PARALLEL_FOR_CLAUSE +#undef OPENMP_PARALLEL_FOR_SIMD_CLAUSE #undef OPENMP_PARALLEL_SECTIONS_CLAUSE #undef OPENMP_TASK_CLAUSE +#undef OPENMP_ATOMIC_CLAUSE +#undef OPENMP_TARGET_CLAUSE +#undef OPENMP_TEAMS_CLAUSE #undef OPENMP_SIMD_CLAUSE #undef OPENMP_FOR_CLAUSE +#undef OPENMP_FOR_SIMD_CLAUSE diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h index 526cbb26cf15..e2f115113e20 100644 --- a/include/clang/Basic/OpenMPKinds.h +++ b/include/clang/Basic/OpenMPKinds.h @@ -93,6 +93,12 @@ bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind); /// parallel', otherwise - false. bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind); +/// \brief Checks if the specified directive is a teams-kind directive. +/// \param DKind Specified directive. +/// \return true - the directive is a teams-like directive like 'omp teams', +/// otherwise - false. +bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind); + /// \brief Checks if the specified directive is a simd directive. /// \param DKind Specified directive. /// \return true - the directive is a simd directive like 'omp simd', diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h index d3b70c2f4d22..7120baeef675 100644 --- a/include/clang/Basic/OperatorKinds.h +++ b/include/clang/Basic/OperatorKinds.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_OPERATOR_KINDS_H -#define LLVM_CLANG_BASIC_OPERATOR_KINDS_H +#ifndef LLVM_CLANG_BASIC_OPERATORKINDS_H +#define LLVM_CLANG_BASIC_OPERATORKINDS_H namespace clang { diff --git a/include/clang/Basic/OperatorPrecedence.h b/include/clang/Basic/OperatorPrecedence.h index b68d577c806c..640749fdd10d 100644 --- a/include/clang/Basic/OperatorPrecedence.h +++ b/include/clang/Basic/OperatorPrecedence.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_OPERATOR_PRECEDENCE_H -#define LLVM_CLANG_OPERATOR_PRECEDENCE_H +#ifndef LLVM_CLANG_BASIC_OPERATORPRECEDENCE_H +#define LLVM_CLANG_BASIC_OPERATORPRECEDENCE_H #include "clang/Basic/TokenKinds.h" diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index 8ae3b22b0cc8..84c8dd159615 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PARTIALDIAGNOSTIC_H -#define LLVM_CLANG_PARTIALDIAGNOSTIC_H +#ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H +#define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" diff --git a/include/clang/Basic/PlistSupport.h b/include/clang/Basic/PlistSupport.h index b7a938209a1d..081f22d48d4a 100644 --- a/include/clang/Basic/PlistSupport.h +++ b/include/clang/Basic/PlistSupport.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PLISTSUPPORT_H -#define LLVM_CLANG_PLISTSUPPORT_H +#ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H +#define LLVM_CLANG_BASIC_PLISTSUPPORT_H #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" diff --git a/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h index 0e49295540b4..6badae5c0349 100644 --- a/include/clang/Basic/PrettyStackTrace.h +++ b/include/clang/Basic/PrettyStackTrace.h @@ -14,8 +14,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef CLANG_BASIC_PRETTYSTACKTRACE_H -#define CLANG_BASIC_PRETTYSTACKTRACE_H +#ifndef LLVM_CLANG_BASIC_PRETTYSTACKTRACE_H +#define LLVM_CLANG_BASIC_PRETTYSTACKTRACE_H #include "clang/Basic/SourceLocation.h" #include "llvm/Support/PrettyStackTrace.h" diff --git a/include/clang/Basic/SanitizerBlacklist.h b/include/clang/Basic/SanitizerBlacklist.h new file mode 100644 index 000000000000..2ce268aa0a3b --- /dev/null +++ b/include/clang/Basic/SanitizerBlacklist.h @@ -0,0 +1,45 @@ +//===--- SanitizerBlacklist.h - Blacklist for sanitizers --------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// User-provided blacklist used to disable/alter instrumentation done in +// sanitizers. +// +//===----------------------------------------------------------------------===// +#ifndef LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H +#define LLVM_CLANG_BASIC_SANITIZERBLACKLIST_H + +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/SourceManager.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/SpecialCaseList.h" +#include <memory> + +namespace clang { + +class SanitizerBlacklist { + std::unique_ptr<llvm::SpecialCaseList> SCL; + SourceManager &SM; + +public: + SanitizerBlacklist(StringRef BlacklistPath, SourceManager &SM); + bool isBlacklistedGlobal(StringRef GlobalName, + StringRef Category = StringRef()) const; + bool isBlacklistedType(StringRef MangledTypeName, + StringRef Category = StringRef()) const; + bool isBlacklistedFunction(StringRef FunctionName) const; + bool isBlacklistedFile(StringRef FileName, + StringRef Category = StringRef()) const; + bool isBlacklistedLocation(SourceLocation Loc, + StringRef Category = StringRef()) const; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 0ef39bc710bb..91a1ef4d197c 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -59,9 +59,11 @@ SANITIZER("float-cast-overflow", FloatCastOverflow) SANITIZER("float-divide-by-zero", FloatDivideByZero) SANITIZER("function", Function) SANITIZER("integer-divide-by-zero", IntegerDivideByZero) +SANITIZER("nonnull-attribute", NonnullAttribute) SANITIZER("null", Null) SANITIZER("object-size", ObjectSize) SANITIZER("return", Return) +SANITIZER("returns-nonnull-attribute", ReturnsNonnullAttribute) SANITIZER("shift", Shift) SANITIZER("signed-integer-overflow", SignedIntegerOverflow) SANITIZER("unreachable", Unreachable) @@ -78,9 +80,10 @@ SANITIZER("dataflow", DataFlow) // ABI or address space layout implications, and only catch undefined behavior. SANITIZER_GROUP("undefined", Undefined, Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow | - FloatDivideByZero | Function | IntegerDivideByZero | Null | - ObjectSize | Return | Shift | SignedIntegerOverflow | - Unreachable | VLABound | Vptr) + FloatDivideByZero | Function | IntegerDivideByZero | + NonnullAttribute | Null | ObjectSize | Return | + ReturnsNonnullAttribute | Shift | SignedIntegerOverflow | + Unreachable | VLABound | Vptr) // -fsanitize=undefined-trap includes // all sanitizers included by -fsanitize=undefined, except those that require @@ -88,9 +91,9 @@ SANITIZER_GROUP("undefined", Undefined, // -fsanitize-undefined-trap-on-error flag. SANITIZER_GROUP("undefined-trap", UndefinedTrap, Alignment | Bool | ArrayBounds | Enum | FloatCastOverflow | - FloatDivideByZero | IntegerDivideByZero | Null | ObjectSize | - Return | Shift | SignedIntegerOverflow | Unreachable | - VLABound) + FloatDivideByZero | IntegerDivideByZero | NonnullAttribute | + Null | ObjectSize | Return | ReturnsNonnullAttribute | + Shift | SignedIntegerOverflow | Unreachable | VLABound) SANITIZER_GROUP("integer", Integer, SignedIntegerOverflow | UnsignedIntegerOverflow | Shift | @@ -99,5 +102,9 @@ SANITIZER_GROUP("integer", Integer, SANITIZER("local-bounds", LocalBounds) SANITIZER_GROUP("bounds", Bounds, ArrayBounds | LocalBounds) +// Magic group, containing all sanitizers. For example, "-fno-sanitize=all" +// can be used to disable all the sanitizers. +SANITIZER_GROUP("all", All, ~0) + #undef SANITIZER #undef SANITIZER_GROUP diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h new file mode 100644 index 000000000000..868b331f2f36 --- /dev/null +++ b/include/clang/Basic/Sanitizers.h @@ -0,0 +1,47 @@ +//===--- Sanitizers.h - C Language Family Language Options ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief Defines the clang::SanitizerKind enum. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_SANITIZERS_H +#define LLVM_CLANG_BASIC_SANITIZERS_H + +namespace clang { + +enum class SanitizerKind { +#define SANITIZER(NAME, ID) ID, +#include "clang/Basic/Sanitizers.def" + Unknown +}; + +class SanitizerSet { + /// \brief Bitmask of enabled sanitizers. + unsigned Kinds; +public: + SanitizerSet(); + + /// \brief Check if a certain sanitizer is enabled. + bool has(SanitizerKind K) const; + + /// \brief Enable or disable a certain sanitizer. + void set(SanitizerKind K, bool Value); + + /// \brief Disable all sanitizers. + void clear(); + + /// \brief Returns true if at least one sanitizer is enabled. + bool empty() const; +}; + +} // end namespace clang + +#endif diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 7b637d7e1fb3..7aaee1df2260 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SOURCELOCATION_H -#define LLVM_CLANG_SOURCELOCATION_H +#ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H +#define LLVM_CLANG_BASIC_SOURCELOCATION_H #include "clang/Basic/LLVM.h" #include "llvm/Support/Compiler.h" @@ -292,7 +292,6 @@ public: const char *getCharacterData(bool *Invalid = nullptr) const; - const llvm::MemoryBuffer* getBuffer(bool *Invalid = nullptr) const; /// \brief Return a StringRef to the source buffer data for the /// specified FileID. diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index e567a7a28da5..717258ddcf04 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -32,8 +32,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SOURCEMANAGER_H -#define LLVM_CLANG_SOURCEMANAGER_H +#ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H +#define LLVM_CLANG_BASIC_SOURCEMANAGER_H #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" @@ -205,10 +205,10 @@ namespace SrcMgr { /// this content cache. This is used for performance analysis. llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; - void setBuffer(llvm::MemoryBuffer *B) { + void setBuffer(std::unique_ptr<llvm::MemoryBuffer> B) { assert(!Buffer.getPointer() && "MemoryBuffer already set."); - Buffer.setPointer(B); - Buffer.setInt(false); + Buffer.setPointer(B.release()); + Buffer.setInt(0); } /// \brief Get the underlying buffer, returning NULL if the buffer is not @@ -685,9 +685,9 @@ class SourceManager : public RefCountedBase<SourceManager> { InBeforeInTUCacheEntry &getInBeforeInTUCache(FileID LFID, FileID RFID) const; // Cache for the "fake" buffer used for error-recovery purposes. - mutable llvm::MemoryBuffer *FakeBufferForRecovery; + mutable std::unique_ptr<llvm::MemoryBuffer> FakeBufferForRecovery; - mutable SrcMgr::ContentCache *FakeContentCacheForRecovery; + mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery; /// \brief Lazily computed map of macro argument chunks to their expanded /// source location. @@ -754,7 +754,6 @@ public: /// \brief Set the file ID for the main source file. void setMainFileID(FileID FID) { - assert(MainFileID.isInvalid() && "MainFileID already set!"); MainFileID = FID; } @@ -789,12 +788,12 @@ public: /// /// This does no caching of the buffer and takes ownership of the /// MemoryBuffer, so only pass a MemoryBuffer to this once. - FileID createFileID(llvm::MemoryBuffer *Buffer, + FileID createFileID(std::unique_ptr<llvm::MemoryBuffer> Buffer, SrcMgr::CharacteristicKind FileCharacter = SrcMgr::C_User, int LoadedID = 0, unsigned LoadedOffset = 0, SourceLocation IncludeLoc = SourceLocation()) { - return createFileID(createMemBufferContentCache(Buffer), IncludeLoc, - FileCharacter, LoadedID, LoadedOffset); + return createFileID(createMemBufferContentCache(std::move(Buffer)), + IncludeLoc, FileCharacter, LoadedID, LoadedOffset); } /// \brief Return a new SourceLocation that encodes the @@ -833,7 +832,11 @@ public: /// \param DoNotFree If true, then the buffer will not be freed when the /// source manager is destroyed. void overrideFileContents(const FileEntry *SourceFile, - llvm::MemoryBuffer *Buffer, bool DoNotFree = false); + llvm::MemoryBuffer *Buffer, bool DoNotFree); + void overrideFileContents(const FileEntry *SourceFile, + std::unique_ptr<llvm::MemoryBuffer> Buffer) { + overrideFileContents(SourceFile, Buffer.release(), /*DoNotFree*/ false); + } /// \brief Override the given source file with another one. /// @@ -1624,7 +1627,7 @@ private: /// \brief Create a new ContentCache for the specified memory buffer. const SrcMgr::ContentCache * - createMemBufferContentCache(llvm::MemoryBuffer *Buf); + createMemBufferContentCache(std::unique_ptr<llvm::MemoryBuffer> Buf); FileID getFileIDSlow(unsigned SLocOffset) const; FileID getFileIDLocal(unsigned SLocOffset) const; @@ -1674,7 +1677,7 @@ class BeforeThanCompare<SourceRange> { public: explicit BeforeThanCompare(SourceManager &SM) : SM(SM) { } - bool operator()(SourceRange LHS, SourceRange RHS) { + bool operator()(SourceRange LHS, SourceRange RHS) const { return SM.isBeforeInTranslationUnit(LHS.getBegin(), RHS.getBegin()); } }; diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index af95b78883fe..f31d604244d0 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SOURCEMANAGER_INTERNALS_H -#define LLVM_CLANG_SOURCEMANAGER_INTERNALS_H +#ifndef LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H +#define LLVM_CLANG_BASIC_SOURCEMANAGERINTERNALS_H #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index f89567356be5..a968d00d2089 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -203,6 +203,7 @@ namespace clang { CC_X86StdCall, // __attribute__((stdcall)) CC_X86FastCall, // __attribute__((fastcall)) CC_X86ThisCall, // __attribute__((thiscall)) + CC_X86VectorCall, // __attribute__((vectorcall)) CC_X86Pascal, // __attribute__((pascal)) CC_X86_64Win64, // __attribute__((ms_abi)) CC_X86_64SysV, // __attribute__((sysv_abi)) @@ -212,16 +213,18 @@ namespace clang { CC_IntelOclBicc // __attribute__((intel_ocl_bicc)) }; - /// \brief Checks whether the given calling convention is callee-cleanup. - inline bool isCalleeCleanup(CallingConv CC) { + /// \brief Checks whether the given calling convention supports variadic + /// calls. Unprototyped calls also use the variadic call rules. + inline bool supportsVariadicCall(CallingConv CC) { switch (CC) { case CC_X86StdCall: case CC_X86FastCall: case CC_X86ThisCall: case CC_X86Pascal: - return true; - default: + case CC_X86VectorCall: return false; + default: + return true; } } diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index d9806486497d..750108f39f9a 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -135,6 +135,7 @@ def SubstNonTypeTemplateParmPackExpr : DStmt<Expr>; def FunctionParmPackExpr : DStmt<Expr>; def MaterializeTemporaryExpr : DStmt<Expr>; def LambdaExpr : DStmt<Expr>; +def CXXFoldExpr : DStmt<Expr>; // Obj-C Expressions. def ObjCStringLiteral : DStmt<Expr>; @@ -163,6 +164,7 @@ def ShuffleVectorExpr : DStmt<Expr>; def ConvertVectorExpr : DStmt<Expr>; def BlockExpr : DStmt<Expr>; def OpaqueValueExpr : DStmt<Expr>; +def TypoExpr : DStmt<Expr>; // Microsoft Extensions. def MSPropertyRefExpr : DStmt<Expr>; @@ -178,18 +180,25 @@ def AsTypeExpr : DStmt<Expr>; // OpenMP Directives. def OMPExecutableDirective : Stmt<1>; +def OMPLoopDirective : DStmt<OMPExecutableDirective, 1>; def OMPParallelDirective : DStmt<OMPExecutableDirective>; -def OMPSimdDirective : DStmt<OMPExecutableDirective>; -def OMPForDirective : DStmt<OMPExecutableDirective>; +def OMPSimdDirective : DStmt<OMPLoopDirective>; +def OMPForDirective : DStmt<OMPLoopDirective>; +def OMPForSimdDirective : DStmt<OMPLoopDirective>; def OMPSectionsDirective : DStmt<OMPExecutableDirective>; def OMPSectionDirective : DStmt<OMPExecutableDirective>; def OMPSingleDirective : DStmt<OMPExecutableDirective>; def OMPMasterDirective : DStmt<OMPExecutableDirective>; def OMPCriticalDirective : DStmt<OMPExecutableDirective>; -def OMPParallelForDirective : DStmt<OMPExecutableDirective>; +def OMPParallelForDirective : DStmt<OMPLoopDirective>; +def OMPParallelForSimdDirective : DStmt<OMPLoopDirective>; def OMPParallelSectionsDirective : DStmt<OMPExecutableDirective>; def OMPTaskDirective : DStmt<OMPExecutableDirective>; def OMPTaskyieldDirective : DStmt<OMPExecutableDirective>; def OMPBarrierDirective : DStmt<OMPExecutableDirective>; def OMPTaskwaitDirective : DStmt<OMPExecutableDirective>; def OMPFlushDirective : DStmt<OMPExecutableDirective>; +def OMPOrderedDirective : DStmt<OMPExecutableDirective>; +def OMPAtomicDirective : DStmt<OMPExecutableDirective>; +def OMPTargetDirective : DStmt<OMPExecutableDirective>; +def OMPTeamsDirective : DStmt<OMPExecutableDirective>; diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index b1652bed07f2..e112c654b5d0 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_TARGET_BUILTINS_H -#define LLVM_CLANG_BASIC_TARGET_BUILTINS_H +#ifndef LLVM_CLANG_BASIC_TARGETBUILTINS_H +#define LLVM_CLANG_BASIC_TARGETBUILTINS_H #include "clang/Basic/Builtins.h" #undef PPC @@ -164,6 +164,17 @@ namespace clang { LastTSBuiltin }; } + + /// \brief Le64 builtins + namespace Le64 { + enum { + LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, + #define BUILTIN(ID, TYPE, ATTRS) BI##ID, + #include "clang/Basic/BuiltinsLe64.def" + LastTSBuiltin + }; + } + } // end namespace clang. #endif diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h index f9e37c360b4f..5669d2a55937 100644 --- a/include/clang/Basic/TargetCXXABI.h +++ b/include/clang/Basic/TargetCXXABI.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TARGETCXXABI_H -#define LLVM_CLANG_TARGETCXXABI_H +#ifndef LLVM_CLANG_BASIC_TARGETCXXABI_H +#define LLVM_CLANG_BASIC_TARGETCXXABI_H #include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index edef7c0377f2..69a54044680d 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -370,6 +370,15 @@ public: /// \brief Return the maximum width lock-free atomic operation which can be /// inlined given the supported features of the given target. unsigned getMaxAtomicInlineWidth() const { return MaxAtomicInlineWidth; } + /// \brief Returns true if the given target supports lock-free atomic + /// operations at the specified width and alignment. + virtual bool hasBuiltinAtomic(uint64_t AtomicSizeInBits, + uint64_t AlignmentInBits) const { + return AtomicSizeInBits <= AlignmentInBits && + AtomicSizeInBits <= getMaxAtomicInlineWidth() && + (AtomicSizeInBits <= getCharWidth() || + llvm::isPowerOf2_64(AtomicSizeInBits / getCharWidth())); + } /// \brief Return the maximum vector alignment supported for the given target. unsigned getMaxVectorAlign() const { return MaxVectorAlign; } @@ -519,22 +528,31 @@ public: CI_None = 0x00, CI_AllowsMemory = 0x01, CI_AllowsRegister = 0x02, - CI_ReadWrite = 0x04, // "+r" output constraint (read and write). - CI_HasMatchingInput = 0x08 // This output operand has a matching input. + CI_ReadWrite = 0x04, // "+r" output constraint (read and write). + CI_HasMatchingInput = 0x08, // This output operand has a matching input. + CI_ImmediateConstant = 0x10, // This operand must be an immediate constant + CI_EarlyClobber = 0x20, // "&" output constraint (early clobber). }; unsigned Flags; int TiedOperand; + struct { + int Min; + int Max; + } ImmRange; std::string ConstraintStr; // constraint: "=rm" std::string Name; // Operand name: [foo] with no []'s. public: ConstraintInfo(StringRef ConstraintStr, StringRef Name) - : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()), - Name(Name.str()) {} + : Flags(0), TiedOperand(-1), ConstraintStr(ConstraintStr.str()), + Name(Name.str()) { + ImmRange.Min = ImmRange.Max = 0; + } const std::string &getConstraintStr() const { return ConstraintStr; } const std::string &getName() const { return Name; } bool isReadWrite() const { return (Flags & CI_ReadWrite) != 0; } + bool earlyClobber() { return (Flags & CI_EarlyClobber) != 0; } bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; } bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; } @@ -553,10 +571,22 @@ public: return (unsigned)TiedOperand; } + bool requiresImmediateConstant() const { + return (Flags & CI_ImmediateConstant) != 0; + } + int getImmConstantMin() const { return ImmRange.Min; } + int getImmConstantMax() const { return ImmRange.Max; } + void setIsReadWrite() { Flags |= CI_ReadWrite; } + void setEarlyClobber() { Flags |= CI_EarlyClobber; } void setAllowsMemory() { Flags |= CI_AllowsMemory; } void setAllowsRegister() { Flags |= CI_AllowsRegister; } void setHasMatchingInput() { Flags |= CI_HasMatchingInput; } + void setRequiresImmediate(int Min, int Max) { + Flags |= CI_ImmediateConstant; + ImmRange.Min = Min; + ImmRange.Max = Max; + } /// \brief Indicate that this is an input operand that is tied to /// the specified output operand. @@ -577,13 +607,21 @@ public: bool validateInputConstraint(ConstraintInfo *OutputConstraints, unsigned NumOutputs, ConstraintInfo &info) const; + + virtual bool validateOutputSize(StringRef /*Constraint*/, + unsigned /*Size*/) const { + return true; + } + virtual bool validateInputSize(StringRef /*Constraint*/, unsigned /*Size*/) const { return true; } - virtual bool validateConstraintModifier(StringRef /*Constraint*/, - const char /*Modifier*/, - unsigned /*Size*/) const { + virtual bool + validateConstraintModifier(StringRef /*Constraint*/, + char /*Modifier*/, + unsigned /*Size*/, + std::string &/*SuggestedModifier*/) const { return true; } bool resolveSymbolicName(const char *&Name, diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 2c86c31c2391..97825394202f 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_TARGETOPTIONS_H -#define LLVM_CLANG_FRONTEND_TARGETOPTIONS_H +#ifndef LLVM_CLANG_BASIC_TARGETOPTIONS_H +#define LLVM_CLANG_BASIC_TARGETOPTIONS_H #include <string> #include <vector> diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h index b730143b6391..aed287b46228 100644 --- a/include/clang/Basic/TemplateKinds.h +++ b/include/clang/Basic/TemplateKinds.h @@ -11,8 +11,8 @@ /// \brief Defines the clang::TemplateNameKind enum. /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TEMPLATEKINDS_H -#define LLVM_CLANG_TEMPLATEKINDS_H +#ifndef LLVM_CLANG_BASIC_TEMPLATEKINDS_H +#define LLVM_CLANG_BASIC_TEMPLATEKINDS_H namespace clang { diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 5d088336dfe2..3319d4ed35e0 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -116,7 +116,6 @@ TOK(eof) // End of file. TOK(eod) // End of preprocessing directive (end of line inside a // directive). TOK(code_completion) // Code completion marker -TOK(cxx_defaultarg_end) // C++ default argument end marker // C99 6.4.9: Comments. TOK(comment) // Comment (only in -E -C[C] mode) @@ -133,6 +132,9 @@ TOK(numeric_constant) // 0x123 TOK(char_constant) // 'a' TOK(wide_char_constant) // L'b' +// C++1z Character Constants +TOK(utf8_char_constant) // u8'a' + // C++11 Character Constants TOK(utf16_char_constant) // u'a' TOK(utf32_char_constant) // U'a' @@ -457,18 +459,22 @@ KEYWORD(__cdecl , KEYALL) KEYWORD(__stdcall , KEYALL) KEYWORD(__fastcall , KEYALL) KEYWORD(__thiscall , KEYALL) +KEYWORD(__vectorcall , KEYALL) KEYWORD(__forceinline , KEYMS) KEYWORD(__unaligned , KEYMS) +KEYWORD(__super , KEYMS) // OpenCL address space qualifiers KEYWORD(__global , KEYOPENCL) KEYWORD(__local , KEYOPENCL) KEYWORD(__constant , KEYOPENCL) KEYWORD(__private , KEYOPENCL) +KEYWORD(__generic , KEYOPENCL) ALIAS("global", __global , KEYOPENCL) ALIAS("local", __local , KEYOPENCL) ALIAS("constant", __constant , KEYOPENCL) ALIAS("private", __private , KEYOPENCL) +ALIAS("generic", __generic , KEYOPENCL) // OpenCL function qualifiers KEYWORD(__kernel , KEYOPENCL) ALIAS("kernel", __kernel , KEYOPENCL) @@ -489,6 +495,7 @@ KEYWORD(__pascal , KEYALL) // Altivec Extension. KEYWORD(__vector , KEYALTIVEC) KEYWORD(__pixel , KEYALTIVEC) +KEYWORD(__bool , KEYALTIVEC) // ARM NEON extensions. ALIAS("__fp16", half , KEYALL) @@ -545,8 +552,12 @@ KEYWORD(__multiple_inheritance , KEYMS) KEYWORD(__virtual_inheritance , KEYMS) KEYWORD(__interface , KEYMS) ALIAS("__int8" , char , KEYMS) +ALIAS("_int8" , char , KEYMS) ALIAS("__int16" , short , KEYMS) +ALIAS("_int16" , short , KEYMS) ALIAS("__int32" , int , KEYMS) +ALIAS("_int32" , int , KEYMS) +ALIAS("_int64" , __int64 , KEYMS) ALIAS("__wchar_t" , wchar_t , KEYMS) ALIAS("_asm" , asm , KEYMS) ALIAS("_alignof" , __alignof , KEYMS) @@ -555,6 +566,7 @@ ALIAS("_cdecl" , __cdecl , KEYMS | KEYBORLAND) ALIAS("_fastcall" , __fastcall , KEYMS | KEYBORLAND) ALIAS("_stdcall" , __stdcall , KEYMS | KEYBORLAND) ALIAS("_thiscall" , __thiscall , KEYMS) +ALIAS("_vectorcall" , __vectorcall, KEYMS) ALIAS("_uuidof" , __uuidof , KEYMS | KEYBORLAND) ALIAS("_inline" , inline , KEYMS) ALIAS("_declspec" , __declspec , KEYMS) diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h index 794625ca91e3..f4ecb3eb306f 100644 --- a/include/clang/Basic/TokenKinds.h +++ b/include/clang/Basic/TokenKinds.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOKENKINDS_H -#define LLVM_CLANG_TOKENKINDS_H +#ifndef LLVM_CLANG_BASIC_TOKENKINDS_H +#define LLVM_CLANG_BASIC_TOKENKINDS_H #include "llvm/Support/Compiler.h" @@ -86,9 +86,9 @@ inline bool isStringLiteral(TokenKind K) { /// constant, string, etc. inline bool isLiteral(TokenKind K) { return K == tok::numeric_constant || K == tok::char_constant || - K == tok::wide_char_constant || K == tok::utf16_char_constant || - K == tok::utf32_char_constant || isStringLiteral(K) || - K == tok::angle_string_literal; + K == tok::wide_char_constant || K == tok::utf8_char_constant || + K == tok::utf16_char_constant || K == tok::utf32_char_constant || + isStringLiteral(K) || K == tok::angle_string_literal; } /// \brief Return true if this is any of tok::annot_* kinds. diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index d7d2b18f3101..ef84d2b11163 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TYPETRAITS_H -#define LLVM_CLANG_TYPETRAITS_H +#ifndef LLVM_CLANG_BASIC_TYPETRAITS_H +#define LLVM_CLANG_BASIC_TYPETRAITS_H namespace clang { diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h index 54d06e07396a..77fd947f96a9 100644 --- a/include/clang/Basic/VersionTuple.h +++ b/include/clang/Basic/VersionTuple.h @@ -24,30 +24,35 @@ namespace clang { /// \brief Represents a version number in the form major[.minor[.subminor]]. class VersionTuple { - unsigned Major; + unsigned Major : 31; unsigned Minor : 31; unsigned Subminor : 31; unsigned HasMinor : 1; unsigned HasSubminor : 1; + unsigned UsesUnderscores : 1; public: VersionTuple() - : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) { } + : Major(0), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false), + UsesUnderscores(false) { } explicit VersionTuple(unsigned Major) - : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false) + : Major(Major), Minor(0), Subminor(0), HasMinor(false), HasSubminor(false), + UsesUnderscores(false) { } - explicit VersionTuple(unsigned Major, unsigned Minor) + explicit VersionTuple(unsigned Major, unsigned Minor, + bool UsesUnderscores = false) : Major(Major), Minor(Minor), Subminor(0), HasMinor(true), - HasSubminor(false) + HasSubminor(false), UsesUnderscores(UsesUnderscores) { } - explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor) + explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, + bool UsesUnderscores = false) : Major(Major), Minor(Minor), Subminor(Subminor), HasMinor(true), - HasSubminor(true) + HasSubminor(true), UsesUnderscores(UsesUnderscores) { } - + /// \brief Determine whether this version information is empty /// (e.g., all version components are zero). bool empty() const { return Major == 0 && Minor == 0 && Subminor == 0; } @@ -69,6 +74,14 @@ public: return Subminor; } + bool usesUnderscores() const { + return UsesUnderscores; + } + + void UseDotAsSeparator() { + UsesUnderscores = false; + } + /// \brief Determine if two version numbers are equivalent. If not /// provided, minor and subminor version numbers are considered to be zero. friend bool operator==(const VersionTuple& X, const VersionTuple &Y) { diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 36f78fd8725f..1c65fb5eac06 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -10,16 +10,16 @@ /// \brief Defines the virtual file system interface vfs::FileSystem. //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H -#define LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H +#ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H +#define LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SourceMgr.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { class MemoryBuffer; @@ -89,11 +89,9 @@ public: /// \brief Get the status of the file. virtual llvm::ErrorOr<Status> status() = 0; /// \brief Get the contents of the file as a \p MemoryBuffer. - virtual std::error_code getBuffer(const Twine &Name, - std::unique_ptr<llvm::MemoryBuffer> &Result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true, - bool IsVolatile = false) = 0; + virtual llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + getBuffer(const Twine &Name, int64_t FileSize = -1, + bool RequiresNullTerminator = true, bool IsVolatile = false) = 0; /// \brief Closes the file. virtual std::error_code close() = 0; /// \brief Sets the name to use for this file. @@ -188,16 +186,14 @@ public: /// \brief Get the status of the entry at \p Path, if one exists. virtual llvm::ErrorOr<Status> status(const Twine &Path) = 0; /// \brief Get a \p File object for the file at \p Path, if one exists. - virtual std::error_code openFileForRead(const Twine &Path, - std::unique_ptr<File> &Result) = 0; + virtual llvm::ErrorOr<std::unique_ptr<File>> + openFileForRead(const Twine &Path) = 0; /// This is a convenience method that opens a file, gets its content and then /// closes the file. - std::error_code getBufferForFile(const Twine &Name, - std::unique_ptr<llvm::MemoryBuffer> &Result, - int64_t FileSize = -1, - bool RequiresNullTerminator = true, - bool IsVolatile = false); + llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> + getBufferForFile(const Twine &Name, int64_t FileSize = -1, + bool RequiresNullTerminator = true, bool IsVolatile = false); /// \brief Get a directory_iterator for \p Dir. /// \note The 'end' iterator is directory_iterator(). @@ -231,8 +227,8 @@ public: void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS); llvm::ErrorOr<Status> status(const Twine &Path) override; - std::error_code openFileForRead(const Twine &Path, - std::unique_ptr<File> &Result) override; + llvm::ErrorOr<std::unique_ptr<File>> + openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; typedef FileSystemList::reverse_iterator iterator; @@ -250,10 +246,8 @@ llvm::sys::fs::UniqueID getNextVirtualUniqueID(); /// \brief Gets a \p FileSystem for a virtual file system described in YAML /// format. -/// -/// Takes ownership of \p Buffer. IntrusiveRefCntPtr<FileSystem> -getVFSFromYAML(llvm::MemoryBuffer *Buffer, +getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer, llvm::SourceMgr::DiagHandlerTy DiagHandler, void *DiagContext = nullptr, IntrusiveRefCntPtr<FileSystem> ExternalFS = getRealFileSystem()); @@ -280,4 +274,4 @@ public: } // end namespace vfs } // end namespace clang -#endif // LLVM_CLANG_BASIC_VIRTUAL_FILE_SYSTEM_H +#endif diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index 0247bb5dd0d7..933f204bfb52 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -944,13 +944,6 @@ def VCVT_F64 : SInst<"vcvt_f64", "Fd", "lUlQlQUl">; def VCVT_HIGH_F64_F32 : SOpInst<"vcvt_high_f64", "wj", "f", OP_VCVT_EX_HI_F64>; def VCVTX_F32_F64 : SInst<"vcvtx_f32", "fj", "d">; def VCVTX_HIGH_F32_F64 : SOpInst<"vcvtx_high_f32", "qfj", "d", OP_VCVTX_HI>; -def FRINTN : SInst<"vrndn", "dd", "fdQfQd">; -def FRINTA : SInst<"vrnda", "dd", "fdQfQd">; -def FRINTP : SInst<"vrndp", "dd", "fdQfQd">; -def FRINTM : SInst<"vrndm", "dd", "fdQfQd">; -def FRINTX : SInst<"vrndx", "dd", "fdQfQd">; -def FRINTZ : SInst<"vrnd", "dd", "fdQfQd">; -def FRINTI : SInst<"vrndi", "dd", "fdQfQd">; def VCVT_S64 : SInst<"vcvt_s64", "xd", "dQd">; def VCVT_U64 : SInst<"vcvt_u64", "ud", "dQd">; def FRECPE : SInst<"vrecpe", "dd", "dQd">; @@ -983,11 +976,6 @@ def MAX : SInst<"vmax", "ddd", "dQd">; def MIN : SInst<"vmin", "ddd", "dQd">; //////////////////////////////////////////////////////////////////////////////// -// MaxNum/MinNum Floating Point -def FMAXNM : SInst<"vmaxnm", "ddd", "fdQfQd">; -def FMINNM : SInst<"vminnm", "ddd", "fdQfQd">; - -//////////////////////////////////////////////////////////////////////////////// // Pairwise Max/Min def MAXP : SInst<"vpmax", "ddd", "QcQsQiQUcQUsQUiQfQd">; def MINP : SInst<"vpmin", "ddd", "QcQsQiQUcQUsQUiQfQd">; @@ -1089,7 +1077,7 @@ def VDUP_LANE2: WOpInst<"vdup_laneq", "dji", "csilUcUsUiUlPcPshfdQcQsQiQlQPcQPsQUcQUsQUiQUlQhQfQdPlQPl", OP_DUP_LN>; def DUP_N : WOpInst<"vdup_n", "ds", "dQdPlQPl", OP_DUP>; -def MOV_N : WOpInst<"vmov_n", "ds", "dQd", OP_DUP>; +def MOV_N : WOpInst<"vmov_n", "ds", "dQdPlQPl", OP_DUP>; //////////////////////////////////////////////////////////////////////////////// def COMBINE : NoTestOpInst<"vcombine", "kdd", "dPl", OP_CONC>; @@ -1223,6 +1211,41 @@ def FCVTAU_S64 : SInst<"vcvta_u64", "ud", "dQd">; } //////////////////////////////////////////////////////////////////////////////// +// Round to Integral + +let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in { +def FRINTN_S32 : SInst<"vrndn", "dd", "fQf">; +def FRINTA_S32 : SInst<"vrnda", "dd", "fQf">; +def FRINTP_S32 : SInst<"vrndp", "dd", "fQf">; +def FRINTM_S32 : SInst<"vrndm", "dd", "fQf">; +def FRINTX_S32 : SInst<"vrndx", "dd", "fQf">; +def FRINTZ_S32 : SInst<"vrnd", "dd", "fQf">; +} + +let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in { +def FRINTN_S64 : SInst<"vrndn", "dd", "dQd">; +def FRINTA_S64 : SInst<"vrnda", "dd", "dQd">; +def FRINTP_S64 : SInst<"vrndp", "dd", "dQd">; +def FRINTM_S64 : SInst<"vrndm", "dd", "dQd">; +def FRINTX_S64 : SInst<"vrndx", "dd", "dQd">; +def FRINTZ_S64 : SInst<"vrnd", "dd", "dQd">; +def FRINTI_S64 : SInst<"vrndi", "dd", "fdQfQd">; +} + +//////////////////////////////////////////////////////////////////////////////// +// MaxNum/MinNum Floating Point + +let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN)" in { +def FMAXNM_S32 : SInst<"vmaxnm", "ddd", "fQf">; +def FMINNM_S32 : SInst<"vminnm", "ddd", "fQf">; +} + +let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_NUMERIC_MAXMIN)" in { +def FMAXNM_S64 : SInst<"vmaxnm", "ddd", "dQd">; +def FMINNM_S64 : SInst<"vminnm", "ddd", "dQd">; +} + +//////////////////////////////////////////////////////////////////////////////// // Permutation def VTRN1 : SOpInst<"vtrn1", "ddd", "csiUcUsUifPcPsQcQsQiQlQUcQUsQUiQUlQfQdQPcQPsQPl", OP_TRN1>; diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h index f8b90b34eeec..07c618368329 100644 --- a/include/clang/CodeGen/BackendUtil.h +++ b/include/clang/CodeGen/BackendUtil.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CODEGEN_BACKEND_UTIL_H -#define LLVM_CLANG_CODEGEN_BACKEND_UTIL_H +#ifndef LLVM_CLANG_CODEGEN_BACKENDUTIL_H +#define LLVM_CLANG_CODEGEN_BACKENDUTIL_H #include "clang/Basic/LLVM.h" diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h index 449827e02891..102d25d79e04 100644 --- a/include/clang/CodeGen/CGFunctionInfo.h +++ b/include/clang/CodeGen/CGFunctionInfo.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CODEGEN_FUNCTION_INFO_H -#define LLVM_CLANG_CODEGEN_FUNCTION_INFO_H +#ifndef LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H +#define LLVM_CLANG_CODEGEN_CGFUNCTIONINFO_H #include "clang/AST/CanonicalType.h" #include "clang/AST/Type.h" @@ -87,6 +87,7 @@ private: bool IndirectRealign : 1; // isIndirect() bool SRetAfterThis : 1; // isIndirect() bool InReg : 1; // isDirect() || isExtend() || isIndirect() + bool CanBeFlattened: 1; // isDirect() ABIArgInfo(Kind K) : PaddingType(nullptr), TheKind(K), PaddingInReg(false), InReg(false) {} @@ -97,11 +98,13 @@ public: TheKind(Direct), PaddingInReg(false), InReg(false) {} static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, - llvm::Type *Padding = nullptr) { + llvm::Type *Padding = nullptr, + bool CanBeFlattened = true) { auto AI = ABIArgInfo(Direct); AI.setCoerceToType(T); AI.setDirectOffset(Offset); AI.setPaddingType(Padding); + AI.setCanBeFlattened(CanBeFlattened); return AI; } static ABIArgInfo getDirectInReg(llvm::Type *T = nullptr) { @@ -265,6 +268,16 @@ public: InAllocaSRet = SRet; } + bool getCanBeFlattened() const { + assert(isDirect() && "Invalid kind!"); + return CanBeFlattened; + } + + void setCanBeFlattened(bool Flatten) { + assert(isDirect() && "Invalid kind!"); + CanBeFlattened = Flatten; + } + void dump() const; }; @@ -339,6 +352,9 @@ class CGFunctionInfo : public llvm::FoldingSetNode { /// Whether this is an instance method. unsigned InstanceMethod : 1; + /// Whether this is a chain call. + unsigned ChainCall : 1; + /// Whether this function is noreturn. unsigned NoReturn : 1; @@ -347,7 +363,7 @@ class CGFunctionInfo : public llvm::FoldingSetNode { /// How many arguments to pass inreg. unsigned HasRegParm : 1; - unsigned RegParm : 4; + unsigned RegParm : 3; RequiredArgs Required; @@ -367,7 +383,8 @@ class CGFunctionInfo : public llvm::FoldingSetNode { public: static CGFunctionInfo *create(unsigned llvmCC, - bool InstanceMethod, + bool instanceMethod, + bool chainCall, const FunctionType::ExtInfo &extInfo, CanQualType resultType, ArrayRef<CanQualType> argTypes, @@ -393,9 +410,14 @@ public: bool isVariadic() const { return Required.allowsOptionalArgs(); } RequiredArgs getRequiredArgs() const { return Required; } + unsigned getNumRequiredArgs() const { + return isVariadic() ? getRequiredArgs().getNumRequiredArgs() : arg_size(); + } bool isInstanceMethod() const { return InstanceMethod; } + bool isChainCall() const { return ChainCall; } + bool isNoReturn() const { return NoReturn; } /// In ARC, whether this function retains its return value. This @@ -446,6 +468,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID) { ID.AddInteger(getASTCallingConvention()); ID.AddBoolean(InstanceMethod); + ID.AddBoolean(ChainCall); ID.AddBoolean(NoReturn); ID.AddBoolean(ReturnsRetained); ID.AddBoolean(HasRegParm); @@ -457,12 +480,14 @@ public: } static void Profile(llvm::FoldingSetNodeID &ID, bool InstanceMethod, + bool ChainCall, const FunctionType::ExtInfo &info, RequiredArgs required, CanQualType resultType, ArrayRef<CanQualType> argTypes) { ID.AddInteger(info.getCC()); ID.AddBoolean(InstanceMethod); + ID.AddBoolean(ChainCall); ID.AddBoolean(info.getNoReturn()); ID.AddBoolean(info.getProducesResult()); ID.AddBoolean(info.getHasRegParm()); diff --git a/include/clang/CodeGen/CodeGenABITypes.h b/include/clang/CodeGen/CodeGenABITypes.h index 2502982b23fb..97a9dc82940d 100644 --- a/include/clang/CodeGen/CodeGenABITypes.h +++ b/include/clang/CodeGen/CodeGenABITypes.h @@ -21,8 +21,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CODEGEN_ABITYPES_H -#define LLVM_CLANG_CODEGEN_ABITYPES_H +#ifndef LLVM_CLANG_CODEGEN_CODEGENABITYPES_H +#define LLVM_CLANG_CODEGEN_CODEGENABITYPES_H #include "clang/AST/CanonicalType.h" #include "clang/AST/Type.h" @@ -39,6 +39,7 @@ class CXXRecordDecl; class CodeGenOptions; class DiagnosticsEngine; class ObjCMethodDecl; +class CoverageSourceInfo; namespace CodeGen { class CGFunctionInfo; @@ -47,7 +48,8 @@ class CodeGenModule; class CodeGenABITypes { public: - CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD); + CodeGenABITypes(ASTContext &C, llvm::Module &M, const llvm::DataLayout &TD, + CoverageSourceInfo *CoverageInfo = nullptr); ~CodeGenABITypes(); /// These methods all forward to methods in the private implementation class diff --git a/include/clang/CodeGen/CodeGenAction.h b/include/clang/CodeGen/CodeGenAction.h index 37819c780d5d..f8fd56152f23 100644 --- a/include/clang/CodeGen/CodeGenAction.h +++ b/include/clang/CodeGen/CodeGenAction.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H -#define LLVM_CLANG_CODEGEN_CODE_GEN_ACTION_H +#ifndef LLVM_CLANG_CODEGEN_CODEGENACTION_H +#define LLVM_CLANG_CODEGEN_CODEGENACTION_H #include "clang/Frontend/FrontendAction.h" #include <memory> @@ -37,8 +37,8 @@ protected: bool hasIRSupport() const override; - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; void ExecuteAction() override; @@ -52,9 +52,9 @@ public: /// the action will load it from the specified file. void setLinkModule(llvm::Module *Mod) { LinkModule = Mod; } - /// takeModule - Take the generated LLVM module, for use after the action has - /// been run. The result may be null on failure. - llvm::Module *takeModule(); + /// Take the generated LLVM module, for use after the action has been run. + /// The result may be null on failure. + std::unique_ptr<llvm::Module> takeModule(); /// Take the LLVM context used by this action. llvm::LLVMContext *takeLLVMContext(); diff --git a/include/clang/CodeGen/ModuleBuilder.h b/include/clang/CodeGen/ModuleBuilder.h index 4b7236bfd03b..f4c31074e9cd 100644 --- a/include/clang/CodeGen/ModuleBuilder.h +++ b/include/clang/CodeGen/ModuleBuilder.h @@ -24,6 +24,7 @@ namespace llvm { namespace clang { class DiagnosticsEngine; + class CoverageSourceInfo; class LangOptions; class CodeGenOptions; class TargetOptions; @@ -44,7 +45,8 @@ namespace clang { const std::string &ModuleName, const CodeGenOptions &CGO, const TargetOptions &TO, - llvm::LLVMContext& C); + llvm::LLVMContext& C, + CoverageSourceInfo *CoverageInfo = nullptr); } #endif diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake index 7629ef9129b1..5d89b1aaa1ac 100644 --- a/include/clang/Config/config.h.cmake +++ b/include/clang/Config/config.h.cmake @@ -8,6 +8,9 @@ /* Bug report URL. */ #define BUG_REPORT_URL "${BUG_REPORT_URL}" +/* Multilib suffix for libdir. */ +#define CLANG_LIBDIR_SUFFIX "${CLANG_LIBDIR_SUFFIX}" + /* Relative directory for resource files */ #define CLANG_RESOURCE_DIR "${CLANG_RESOURCE_DIR}" @@ -26,4 +29,7 @@ /* The LLVM product name and version */ #define BACKEND_PACKAGE_STRING "${BACKEND_PACKAGE_STRING}" +/* Linker version detected at compile time. */ +#cmakedefine HOST_LINK_VERSION "${HOST_LINK_VERSION}" + #endif diff --git a/include/clang/Config/config.h.in b/include/clang/Config/config.h.in index 1530fefaa53d..dba05db2b99d 100644 --- a/include/clang/Config/config.h.in +++ b/include/clang/Config/config.h.in @@ -8,15 +8,15 @@ /* Bug report URL. */ #undef BUG_REPORT_URL +/* Multilib suffix for libdir. */ +#undef CLANG_LIBDIR_SUFFIX + /* Relative directory for resource files */ #undef CLANG_RESOURCE_DIR /* Directories clang will search for headers */ #undef C_INCLUDE_DIRS -/* Linker version detected at compile time. */ -#undef HOST_LINK_VERSION - /* Default <path> to all compiler invocations for --sysroot=<path>. */ #undef DEFAULT_SYSROOT @@ -31,4 +31,7 @@ /* The LLVM product name and version */ #define BACKEND_PACKAGE_STRING PACKAGE_STRING +/* Linker version detected at compile time. */ +#undef HOST_LINK_VERSION + #endif diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index 2cdb581b85c3..dd0261c2f3a1 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_ACTION_H_ -#define CLANG_DRIVER_ACTION_H_ +#ifndef LLVM_CLANG_DRIVER_ACTION_H +#define LLVM_CLANG_DRIVER_ACTION_H #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" @@ -46,6 +46,7 @@ public: AnalyzeJobClass, MigrateJobClass, CompileJobClass, + BackendJobClass, AssembleJobClass, LinkJobClass, LipoJobClass, @@ -72,8 +73,12 @@ private: protected: Action(ActionClass _Kind, types::ID _Type) : Kind(_Kind), Type(_Type), OwnsInputs(true) {} - Action(ActionClass _Kind, Action *Input, types::ID _Type) - : Kind(_Kind), Type(_Type), Inputs(&Input, &Input + 1), OwnsInputs(true) {} + Action(ActionClass _Kind, std::unique_ptr<Action> Input, types::ID _Type) + : Kind(_Kind), Type(_Type), Inputs(1, Input.release()), OwnsInputs(true) { + } + Action(ActionClass _Kind, std::unique_ptr<Action> Input) + : Kind(_Kind), Type(Input->getType()), Inputs(1, Input.release()), + OwnsInputs(true) {} Action(ActionClass _Kind, const ActionList &_Inputs, types::ID _Type) : Kind(_Kind), Type(_Type), Inputs(_Inputs), OwnsInputs(true) {} public: @@ -119,7 +124,7 @@ class BindArchAction : public Action { const char *ArchName; public: - BindArchAction(Action *Input, const char *_ArchName); + BindArchAction(std::unique_ptr<Action> Input, const char *_ArchName); const char *getArchName() const { return ArchName; } @@ -131,7 +136,7 @@ public: class JobAction : public Action { virtual void anchor(); protected: - JobAction(ActionClass Kind, Action *Input, types::ID Type); + JobAction(ActionClass Kind, std::unique_ptr<Action> Input, types::ID Type); JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); public: @@ -144,7 +149,7 @@ public: class PreprocessJobAction : public JobAction { void anchor() override; public: - PreprocessJobAction(Action *Input, types::ID OutputType); + PreprocessJobAction(std::unique_ptr<Action> Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == PreprocessJobClass; @@ -154,7 +159,7 @@ public: class PrecompileJobAction : public JobAction { void anchor() override; public: - PrecompileJobAction(Action *Input, types::ID OutputType); + PrecompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == PrecompileJobClass; @@ -164,7 +169,7 @@ public: class AnalyzeJobAction : public JobAction { void anchor() override; public: - AnalyzeJobAction(Action *Input, types::ID OutputType); + AnalyzeJobAction(std::unique_ptr<Action> Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == AnalyzeJobClass; @@ -174,7 +179,7 @@ public: class MigrateJobAction : public JobAction { void anchor() override; public: - MigrateJobAction(Action *Input, types::ID OutputType); + MigrateJobAction(std::unique_ptr<Action> Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == MigrateJobClass; @@ -184,17 +189,27 @@ public: class CompileJobAction : public JobAction { void anchor() override; public: - CompileJobAction(Action *Input, types::ID OutputType); + CompileJobAction(std::unique_ptr<Action> Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == CompileJobClass; } }; +class BackendJobAction : public JobAction { + void anchor() override; +public: + BackendJobAction(std::unique_ptr<Action> Input, types::ID OutputType); + + static bool classof(const Action *A) { + return A->getKind() == BackendJobClass; + } +}; + class AssembleJobAction : public JobAction { void anchor() override; public: - AssembleJobAction(Action *Input, types::ID OutputType); + AssembleJobAction(std::unique_ptr<Action> Input, types::ID OutputType); static bool classof(const Action *A) { return A->getKind() == AssembleJobClass; @@ -234,7 +249,8 @@ public: class VerifyJobAction : public JobAction { void anchor() override; public: - VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); + VerifyJobAction(ActionClass Kind, std::unique_ptr<Action> Input, + types::ID Type); VerifyJobAction(ActionClass Kind, ActionList &Inputs, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass || @@ -245,7 +261,7 @@ public: class VerifyDebugInfoJobAction : public VerifyJobAction { void anchor() override; public: - VerifyDebugInfoJobAction(Action *Input, types::ID Type); + VerifyDebugInfoJobAction(std::unique_ptr<Action> Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass; } @@ -254,7 +270,7 @@ public: class VerifyPCHJobAction : public VerifyJobAction { void anchor() override; public: - VerifyPCHJobAction(Action *Input, types::ID Type); + VerifyPCHJobAction(std::unique_ptr<Action> Input, types::ID Type); static bool classof(const Action *A) { return A->getKind() == VerifyPCHJobClass; } diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index d25560c9f3ac..e0430014105c 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -108,6 +108,9 @@ def analyzer_disable_checker : Separate<["-"], "analyzer-disable-checker">, def analyzer_disable_checker_EQ : Joined<["-"], "analyzer-disable-checker=">, Alias<analyzer_disable_checker>; +def analyzer_disable_all_checks : Flag<["-"], "analyzer-disable-all-checks">, + HelpText<"Disable all static analyzer checks">; + def analyzer_checker_help : Flag<["-"], "analyzer-checker-help">, HelpText<"Display the list of analyzer checkers that are available">; @@ -135,6 +138,8 @@ def dwarf_debug_flags : Separate<["-"], "dwarf-debug-flags">, HelpText<"The string to embed in the Dwarf debug flags record.">; def mno_exec_stack : Flag<["-"], "mnoexecstack">, HelpText<"Mark the file as not needing an executable stack">; +def massembler_fatal_warnings : Flag<["-"], "massembler-fatal-warnings">, + HelpText<"Make assembler warnings fatal">; def compress_debug_sections : Flag<["-"], "compress-debug-sections">, HelpText<"Compress DWARF debug sections using zlib">; def msave_temp_labels : Flag<["-"], "msave-temp-labels">, @@ -164,6 +169,8 @@ def no_implicit_float : Flag<["-"], "no-implicit-float">, HelpText<"Don't generate implicit floating point instructions">; def fdump_vtable_layouts : Flag<["-"], "fdump-vtable-layouts">, HelpText<"Dump the layouts of all vtables that will be emitted in a translation unit">; +def fmerge_functions : Flag<["-"], "fmerge-functions">, + HelpText<"Permit merging of identical functions when optimizing.">; def femit_coverage_notes : Flag<["-"], "femit-coverage-notes">, HelpText<"Emit a gcov coverage notes file when compiling.">; def femit_coverage_data: Flag<["-"], "femit-coverage-data">, @@ -179,6 +186,8 @@ def coverage_version_EQ : Joined<["-"], "coverage-version=">, HelpText<"Four-byte version string for gcov files.">; def test_coverage : Flag<["-"], "test-coverage">, HelpText<"Do not generate coverage files or remove coverage changes from IR">; +def dump_coverage_mapping : Flag<["-"], "dump-coverage-mapping">, + HelpText<"Dump the coverage mapping records, for testing">; def fuse_register_sized_bitfield_access: Flag<["-"], "fuse-register-sized-bitfield-access">, HelpText<"Use register sized accesses to bit-fields, when possible.">; def relaxed_aliasing : Flag<["-"], "relaxed-aliasing">, @@ -270,6 +279,8 @@ def ftemplate_backtrace_limit : Separate<["-"], "ftemplate-backtrace-limit">, Me HelpText<"Set the maximum number of entries to print in a template instantiation backtrace (0 = no limit).">; def fconstexpr_backtrace_limit : Separate<["-"], "fconstexpr-backtrace-limit">, MetaVarName<"<N>">, HelpText<"Set the maximum number of entries to print in a constexpr evaluation backtrace (0 = no limit).">; +def fspell_checking_limit : Separate<["-"], "fspell-checking-limit">, MetaVarName<"<N>">, + HelpText<"Set the maximum number of times to perform spell checking on unrecognized identifiers (0 = no limit).">; def fmessage_length : Separate<["-"], "fmessage-length">, MetaVarName<"<N>">, HelpText<"Format message diagnostics so that they fit within N columns or fewer, when possible.">; def verify : Flag<["-"], "verify">, @@ -321,12 +332,16 @@ def ast_dump_filter : Separate<["-"], "ast-dump-filter">, HelpText<"Use with -ast-dump or -ast-print to dump/print only AST declaration" " nodes having a certain substring in a qualified name. Use" " -ast-list to list all filterable declaration node names.">; -def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, - HelpText<"Include name lookup table dumps in AST dumps">; def fno_modules_global_index : Flag<["-"], "fno-modules-global-index">, HelpText<"Do not automatically generate or update the global module index">; def fno_modules_error_recovery : Flag<["-"], "fno-modules-error-recovery">, HelpText<"Do not automatically import modules for error recovery">; +def fmodule_implementation_of : Separate<["-"], "fmodule-implementation-of">, + MetaVarName<"<name>">, + HelpText<"Specify the name of the module whose implementation file this is">; +def fmodule_map_file_home_is_cwd : Flag<["-"], "fmodule-map-file-home-is-cwd">, + HelpText<"Use the current working directory as the home directory of " + "module maps specified by -fmodule-map-file=<FILE>">; let Group = Action_Group in { @@ -355,6 +370,8 @@ def ast_list : Flag<["-"], "ast-list">, HelpText<"Build ASTs and print the list of declaration node qualified names">; def ast_dump : Flag<["-"], "ast-dump">, HelpText<"Build ASTs and then debug dump them">; +def ast_dump_lookups : Flag<["-"], "ast-dump-lookups">, + HelpText<"Build ASTs and then debug dump their name lookup tables">; def ast_view : Flag<["-"], "ast-view">, HelpText<"Build ASTs and view them with GraphViz">; def print_decl_contexts : Flag<["-"], "print-decl-contexts">, @@ -497,13 +514,15 @@ def fdeprecated_macro : Flag<["-"], "fdeprecated-macro">, def fno_deprecated_macro : Flag<["-"], "fno-deprecated-macro">, HelpText<"Undefines the __DEPRECATED macro">; def fsized_deallocation : Flag<["-"], "fsized-deallocation">, - HelpText<"Enable C++1y sized global deallocation functions">; + HelpText<"Enable C++14 sized global deallocation functions">; def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-runtime">, HelpText<"Allow Objective-C array and dictionary subscripting in legacy runtime">; def vtordisp_mode_EQ : Joined<["-"], "vtordisp-mode=">, HelpText<"Control vtordisp placement on win32 targets">; def fno_rtti_data : Flag<["-"], "fno-rtti-data">, HelpText<"Control emission of RTTI data">; +def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">, + HelpText<"Allow function arguments and returns of type half">; //===----------------------------------------------------------------------===// // Header Search Options @@ -561,6 +580,8 @@ def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">, HelpText<"OpenCL only. Allow floating-point optimizations that assume arguments and results are not NaNs or +-Inf.">; def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, HelpText<"OpenCL only. Generate kernel argument metadata.">; +def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, + HelpText<"OpenCL only. Allow optimizations to ignore the signedness of the floating-point zero.">; def cl_unsafe_math_optimizations : Flag<["-"], "cl-unsafe-math-optimizations">, HelpText<"OpenCL only. Allow unsafe floating-point optimizations. Also implies -cl-no-signed-zeros and -cl-mad-enable">; def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">, @@ -569,6 +590,8 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, HelpText<"OpenCL only. Enable less precise MAD instructions to be generated.">; def cl_std_EQ : Joined<["-"], "cl-std=">, HelpText<"OpenCL language standard to compile for">; +def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, + HelpText<"OpenCL only. Allow denormals to be flushed to zero">; //===----------------------------------------------------------------------===// // CUDA Options diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index 7278bf868355..363dd4933c10 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -129,9 +129,22 @@ def _SLASH_wd4005 : CLFlag<"wd4005">, Alias<W_Joined>, AliasArgs<["no-macro-redefined"]>; def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">, Alias<vtordisp_mode_EQ>; +def _SLASH_Zc_strictStrings : CLFlag<"Zc:strictStrings">, + HelpText<"Treat string literals as const">, Alias<W_Joined>, + AliasArgs<["error=c++11-compat-deprecated-writable-strings"]>; +def _SLASH_Zc_trigraphs : CLFlag<"Zc:trigraphs">, + HelpText<"Enable trigraphs">, Alias<ftrigraphs>; +def _SLASH_Zc_trigraphs_off : CLFlag<"Zc:trigraphs-">, + HelpText<"Disable trigraphs (default)">, Alias<fno_trigraphs>; def _SLASH_Z7 : CLFlag<"Z7">, Alias<gline_tables_only>; def _SLASH_Zi : CLFlag<"Zi">, HelpText<"Enable debug information">, Alias<gline_tables_only>; +def _SLASH_Zp : CLJoined<"Zp">, + HelpText<"Specify the default maximum struct packing alignment">, + Alias<fpack_struct_EQ>; +def _SLASH_Zp_flag : CLFlag<"Zp">, + HelpText<"Set the default maximum struct packing alignment to 1">, + Alias<fpack_struct_EQ>, AliasArgs<["1"]>; def _SLASH_Zs : CLFlag<"Zs">, HelpText<"Syntax-check only">, Alias<fsyntax_only>; @@ -176,6 +189,9 @@ def _SLASH_MT : Option<["/", "-"], "MT", KIND_FLAG>, Group<_SLASH_M_Group>, Flags<[CLOption, DriverOption]>, HelpText<"Use static run-time">; def _SLASH_MTd : Option<["/", "-"], "MTd", KIND_FLAG>, Group<_SLASH_M_Group>, Flags<[CLOption, DriverOption]>, HelpText<"Use static debug run-time">; +def _SLASH_o : CLJoinedOrSeparate<"o">, + HelpText<"Set output file or directory (ends in / or \\)">, + MetaVarName<"<file or directory>">; def _SLASH_P : CLFlag<"P">, HelpText<"Preprocess to file">; def _SLASH_Tc : CLCompileJoinedOrSeparate<"Tc">, HelpText<"Specify a C source file">, MetaVarName<"<filename>">; @@ -188,8 +204,11 @@ def _SLASH_TP : CLCompileFlag<"TP">, HelpText<"Treat all source files as C++">; // Ignored: def _SLASH_analyze_ : CLIgnoredFlag<"analyze-">; +def _SLASH_cgthreads : CLIgnoredJoined<"cgthreads">; +def _SLASH_d2Zi_PLUS : CLIgnoredFlag<"d2Zi+">; def _SLASH_errorReport : CLIgnoredJoined<"errorReport">; def _SLASH_FS : CLIgnoredFlag<"FS">, HelpText<"Force synchronous PDB writes">; +def _SLASH_Gd : CLIgnoredFlag<"Gd">; def _SLASH_GF : CLIgnoredFlag<"GF">; def _SLASH_GS_ : CLIgnoredFlag<"GS-">; def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">; @@ -199,12 +218,16 @@ def _SLASH_Ob2 : CLIgnoredFlag<"Ob2">; def _SLASH_RTC : CLIgnoredJoined<"RTC">; def _SLASH_sdl : CLIgnoredFlag<"sdl">; def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">; +def _SLASH_volatile_iso : CLIgnoredFlag<"volatile:iso">; def _SLASH_w : CLIgnoredJoined<"w">; +def _SLASH_Zc_auto : CLIgnoredFlag<"Zc:auto">; def _SLASH_Zc_forScope : CLIgnoredFlag<"Zc:forScope">; def _SLASH_Zc_inline : CLIgnoredFlag<"Zc:inline">; def _SLASH_Zc_rvalueCast : CLIgnoredFlag<"Zc:rvalueCast">; def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">; def _SLASH_Zm : CLIgnoredJoined<"Zm">; +def _SLASH_Zo : CLIgnoredFlag<"Zo">; +def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">; // Unsupported: @@ -212,7 +235,6 @@ def _SLASH_Zm : CLIgnoredJoined<"Zm">; def _SLASH_AI : CLJoined<"AI">; def _SLASH_bigobj : CLFlag<"bigobj">; def _SLASH_clr : CLJoined<"clr">; -def _SLASH_d2Zi_PLUS : CLFlag<"d2Zi+">; def _SLASH_doc : CLJoined<"doc">; def _SLASH_FA_joined : CLJoined<"FA">; def _SLASH_favor : CLJoined<"favor">; @@ -229,7 +251,6 @@ def _SLASH_Fx : CLFlag<"Fx">; def _SLASH_G1 : CLFlag<"G1">; def _SLASH_G2 : CLFlag<"G2">; def _SLASH_GA : CLFlag<"GA">; -def _SLASH_Gd : CLFlag<"Gd">; def _SLASH_Ge : CLFlag<"Ge">; def _SLASH_Gh : CLFlag<"Gh">; def _SLASH_GH : CLFlag<"GH">; @@ -242,6 +263,7 @@ def _SLASH_GS : CLFlag<"GS">; def _SLASH_Gs : CLJoined<"Gs">; def _SLASH_GT : CLFlag<"GT">; def _SLASH_GX : CLFlag<"GX">; +def _SLASH_Gv : CLFlag<"Gv">; def _SLASH_Gz : CLFlag<"Gz">; def _SLASH_GZ : CLFlag<"GZ">; def _SLASH_H : CLFlag<"H">; @@ -250,7 +272,6 @@ def _SLASH_hotpatch : CLFlag<"hotpatch">; def _SLASH_kernel : CLFlag<"kernel">; def _SLASH_LN : CLFlag<"LN">; def _SLASH_MP : CLJoined<"MP">; -def _SLASH_o : CLJoinedOrSeparate<"o">; def _SLASH_openmp : CLFlag<"openmp">; def _SLASH_Qfast_transcendentals : CLFlag<"Qfast_transcendentals">; def _SLASH_QIfist : CLFlag<"QIfist">; @@ -259,7 +280,7 @@ def _SLASH_Qpar : CLFlag<"Qpar">; def _SLASH_Qvec_report : CLJoined<"Qvec-report">; def _SLASH_u : CLFlag<"u">; def _SLASH_V : CLFlag<"V">; -def _SLASH_volatile : CLFlag<"volatile">; +def _SLASH_volatile_ms : CLFlag<"volatile:ms">; def _SLASH_WL : CLFlag<"WL">; def _SLASH_Wp64 : CLFlag<"Wp64">; def _SLASH_X : CLFlag<"X">; @@ -274,5 +295,4 @@ def _SLASH_Ze : CLFlag<"Ze">; def _SLASH_Zg : CLFlag<"Zg">; def _SLASH_ZI : CLFlag<"ZI">; def _SLASH_Zl : CLFlag<"Zl">; -def _SLASH_Zp : CLJoined<"Zp">; def _SLASH_ZW : CLJoined<"ZW">; diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index c1c0f4326d76..5574e2ca0533 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_COMPILATION_H_ -#define CLANG_DRIVER_COMPILATION_H_ +#ifndef LLVM_CLANG_DRIVER_COMPILATION_H +#define LLVM_CLANG_DRIVER_COMPILATION_H #include "clang/Driver/Job.h" #include "clang/Driver/Util.h" @@ -94,7 +94,7 @@ public: JobList &getJobs() { return Jobs; } const JobList &getJobs() const { return Jobs; } - void addCommand(Command *C) { Jobs.addJob(C); } + void addCommand(std::unique_ptr<Command> C) { Jobs.addJob(std::move(C)); } const llvm::opt::ArgStringList &getTempFiles() const { return TempFiles; } diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index df974ad1d760..67d67c3074d7 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_DRIVER_H_ -#define CLANG_DRIVER_DRIVER_H_ +#ifndef LLVM_CLANG_DRIVER_DRIVER_H +#define LLVM_CLANG_DRIVER_DRIVER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" @@ -42,6 +42,7 @@ namespace driver { class Command; class Compilation; class InputInfo; + class Job; class JobAction; class SanitizerArgs; class ToolChain; @@ -103,9 +104,6 @@ public: /// Default target triple. std::string DefaultTargetTriple; - /// Default name for linked images (e.g., "a.out"). - std::string DefaultImageName; - /// Driver title to use with help. std::string DriverTitle; @@ -190,6 +188,12 @@ private: phases::ID getFinalPhase(const llvm::opt::DerivedArgList &DAL, llvm::opt::Arg **FinalPhaseArg = nullptr) const; + // Before executing jobs, sets up response files for commands that need them. + void setUpResponseFiles(Compilation &C, Job &J); + + void generatePrefixedToolNames(const char *Tool, const ToolChain &TC, + SmallVectorImpl<std::string> &Names) const; + public: Driver(StringRef _ClangExecutable, StringRef _DefaultTargetTriple, @@ -291,16 +295,16 @@ public: /// arguments and return an appropriate exit code. /// /// This routine handles additional processing that must be done in addition - /// to just running the subprocesses, for example reporting errors, removing - /// temporary files, etc. - int ExecuteCompilation(const Compilation &C, - SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const; + /// to just running the subprocesses, for example reporting errors, setting + /// up response files, removing temporary files, etc. + int ExecuteCompilation(Compilation &C, + SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands); /// generateCompilationDiagnostics - Generate diagnostics information /// including preprocessed source file(s). /// void generateCompilationDiagnostics(Compilation &C, - const Command *FailingCommand); + const Command &FailingCommand); /// @} /// @name Helper Methods @@ -343,8 +347,9 @@ public: /// ConstructAction - Construct the appropriate action to do for /// \p Phase on the \p Input, taking in to account arguments /// like -fsyntax-only or --analyze. - Action *ConstructPhaseAction(const llvm::opt::ArgList &Args, phases::ID Phase, - Action *Input) const; + std::unique_ptr<Action> + ConstructPhaseAction(const llvm::opt::ArgList &Args, phases::ID Phase, + std::unique_ptr<Action> Input) const; /// BuildJobsForAction - Construct the jobs to perform for the /// action \p A. @@ -357,6 +362,9 @@ public: const char *LinkingOutput, InputInfo &Result) const; + /// Returns the default name for linked images (e.g., "a.out"). + const char *getDefaultImageName() const; + /// GetNamedOutputPath - Return the name to use for the output of /// the action \p JA. The result is appended to the compilation's /// list of temporary or result files, as appropriate. diff --git a/include/clang/Driver/DriverDiagnostic.h b/include/clang/Driver/DriverDiagnostic.h index f3c33aeccb42..680338a2ea7a 100644 --- a/include/clang/Driver/DriverDiagnostic.h +++ b/include/clang/Driver/DriverDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DRIVERDIAGNOSTIC_H -#define LLVM_CLANG_DRIVERDIAGNOSTIC_H +#ifndef LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H +#define LLVM_CLANG_DRIVER_DRIVERDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index 5b19efeddeea..b510676c09a7 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_JOB_H_ -#define CLANG_DRIVER_JOB_H_ +#ifndef LLVM_CLANG_DRIVER_JOB_H +#define LLVM_CLANG_DRIVER_JOB_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator.h" #include "llvm/Option/Option.h" #include <memory> @@ -28,6 +29,14 @@ class Tool; // Re-export this as clang::driver::ArgStringList. using llvm::opt::ArgStringList; +struct CrashReportInfo { + StringRef Filename; + StringRef VFSPath; + + CrashReportInfo(StringRef Filename, StringRef VFSPath) + : Filename(Filename), VFSPath(VFSPath) {} +}; + class Job { public: enum JobClass { @@ -51,9 +60,9 @@ public: /// \param OS - The stream to print on. /// \param Terminator - A string to print at the end of the line. /// \param Quote - Should separate arguments be quoted. - /// \param CrashReport - Whether to print for inclusion in a crash report. - virtual void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const = 0; + /// \param CrashInfo - Details for inclusion in a crash report. + virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, + CrashReportInfo *CrashInfo = nullptr) const = 0; }; /// Command - An executable path/name and argument vector to @@ -72,12 +81,36 @@ class Command : public Job { /// argument, which will be the executable). llvm::opt::ArgStringList Arguments; + /// Response file name, if this command is set to use one, or nullptr + /// otherwise + const char *ResponseFile; + + /// The input file list in case we need to emit a file list instead of a + /// proper response file + llvm::opt::ArgStringList InputFileList; + + /// String storage if we need to create a new argument to specify a response + /// file + std::string ResponseFileFlag; + + /// When a response file is needed, we try to put most arguments in an + /// exclusive file, while others remains as regular command line arguments. + /// This functions fills a vector with the regular command line arguments, + /// argv, excluding the ones passed in a response file. + void buildArgvForResponseFile(llvm::SmallVectorImpl<const char *> &Out) const; + + /// Encodes an array of C strings into a single string separated by whitespace. + /// This function will also put in quotes arguments that have whitespaces and + /// will escape the regular backslashes (used in Windows paths) and quotes. + /// The results are the contents of a response file, written into a raw_ostream. + void writeResponseFile(raw_ostream &OS) const; + public: Command(const Action &_Source, const Tool &_Creator, const char *_Executable, const llvm::opt::ArgStringList &_Arguments); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport = false) const override; + CrashReportInfo *CrashInfo = nullptr) const override; virtual int Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const; @@ -88,6 +121,15 @@ public: /// getCreator - Return the Tool which caused the creation of this job. const Tool &getCreator() const { return Creator; } + /// Set to pass arguments via a response file when launching the command + void setResponseFile(const char *FileName); + + /// Set an input file list, necessary if we need to use a response file but + /// the tool being called only supports input files lists. + void setInputFileList(llvm::opt::ArgStringList List) { + InputFileList = std::move(List); + } + const char *getExecutable() const { return Executable; } const llvm::opt::ArgStringList &getArguments() const { return Arguments; } @@ -104,10 +146,10 @@ class FallbackCommand : public Command { public: FallbackCommand(const Action &Source_, const Tool &Creator_, const char *Executable_, const ArgStringList &Arguments_, - Command *Fallback_); + std::unique_ptr<Command> Fallback_); void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, - bool CrashReport = false) const override; + CrashReportInfo *CrashInfo = nullptr) const override; int Execute(const StringRef **Redirects, std::string *ErrMsg, bool *ExecutionFailed) const override; @@ -123,23 +165,23 @@ private: /// JobList - A sequence of jobs to perform. class JobList : public Job { public: - typedef SmallVector<Job*, 4> list_type; + typedef SmallVector<std::unique_ptr<Job>, 4> list_type; typedef list_type::size_type size_type; - typedef list_type::iterator iterator; - typedef list_type::const_iterator const_iterator; + typedef llvm::pointee_iterator<list_type::iterator> iterator; + typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator; private: list_type Jobs; public: JobList(); - virtual ~JobList(); + virtual ~JobList() {} void Print(llvm::raw_ostream &OS, const char *Terminator, - bool Quote, bool CrashReport = false) const override; + bool Quote, CrashReportInfo *CrashInfo = nullptr) const override; /// Add a job to the list (taking ownership). - void addJob(Job *J) { Jobs.push_back(J); } + void addJob(std::unique_ptr<Job> J) { Jobs.push_back(std::move(J)); } /// Clear the job list. void clear(); diff --git a/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h index 6c3738a9cc03..dcf609ab99c6 100644 --- a/include/clang/Driver/Multilib.h +++ b/include/clang/Driver/Multilib.h @@ -7,12 +7,13 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_LIB_DRIVER_MULTILIB_H_ -#define CLANG_LIB_DRIVER_MULTILIB_H_ +#ifndef LLVM_CLANG_DRIVER_MULTILIB_H +#define LLVM_CLANG_DRIVER_MULTILIB_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/Triple.h" #include "llvm/Option/Option.h" +#include <functional> #include <string> #include <vector> @@ -97,6 +98,10 @@ public: typedef multilib_list::iterator iterator; typedef multilib_list::const_iterator const_iterator; + typedef std::function<std::vector<std::string>( + StringRef InstallDir, StringRef Triple, const Multilib &M)> + IncludeDirsFunc; + struct FilterCallback { virtual ~FilterCallback() {}; /// \return true iff the filter should remove the Multilib from the set @@ -105,6 +110,7 @@ public: private: multilib_list Multilibs; + IncludeDirsFunc IncludeCallback; public: MultilibSet() {} @@ -150,6 +156,12 @@ public: void print(raw_ostream &OS) const; + MultilibSet &setIncludeDirsCallback(IncludeDirsFunc F) { + IncludeCallback = F; + return *this; + } + IncludeDirsFunc includeDirsCallback() const { return IncludeCallback; } + private: /// Apply the filter to Multilibs and return the subset that remains static multilib_list filterCopy(const FilterCallback &F, diff --git a/include/clang/Driver/Options.h b/include/clang/Driver/Options.h index cee705deac63..2716fa9ae85e 100644 --- a/include/clang/Driver/Options.h +++ b/include/clang/Driver/Options.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_OPTIONS_H -#define CLANG_DRIVER_OPTIONS_H +#ifndef LLVM_CLANG_DRIVER_OPTIONS_H +#define LLVM_CLANG_DRIVER_OPTIONS_H namespace llvm { namespace opt { diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 9d4fdad46ade..4daddba332d7 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -80,6 +80,7 @@ def m_hexagon_Features_Group : OptionGroup<"<m hexagon features group>">, Group def m_arm_Features_Group : OptionGroup<"<m arm features group>">, Group<m_Group>; def m_aarch64_Features_Group : OptionGroup<"<m aarch64 features group>">, Group<m_Group>; def m_ppc_Features_Group : OptionGroup<"<m ppc features group>">, Group<m_Group>; +def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>; def u_Group : OptionGroup<"<u group>">; def pedantic_Group : OptionGroup<"<pedantic group>">, @@ -180,6 +181,8 @@ def objcmt_migrate_readonly_property : Flag<["-"], "objcmt-migrate-readonly-prop HelpText<"Enable migration to modern ObjC readonly property">; def objcmt_migrate_readwrite_property : Flag<["-"], "objcmt-migrate-readwrite-property">, Flags<[CC1Option]>, HelpText<"Enable migration to modern ObjC readwrite property">; +def objcmt_migrate_property_dot_syntax : Flag<["-"], "objcmt-migrate-property-dot-syntax">, Flags<[CC1Option]>, + HelpText<"Enable migration of setter/getter messages to property-dot syntax">; def objcmt_migrate_annotation : Flag<["-"], "objcmt-migrate-annotation">, Flags<[CC1Option]>, HelpText<"Enable migration to property and method annotations">; def objcmt_migrate_instancetype : Flag<["-"], "objcmt-migrate-instancetype">, Flags<[CC1Option]>, @@ -413,6 +416,9 @@ def fprofile_instr_use : Flag<["-"], "fprofile-instr-use">, Group<f_Group>; def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use instrumentation data for profile-guided optimization">; +def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Generate coverage mapping to enable code coverage analysis">; def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable the 'blocks' language feature">; @@ -480,6 +486,8 @@ def fencoding_EQ : Joined<["-"], "fencoding=">, Group<f_Group>; def ferror_limit_EQ : Joined<["-"], "ferror-limit=">, Group<f_Group>, Flags<[CoreOption]>; def fexceptions : Flag<["-"], "fexceptions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Enable support for exception handling">; +def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, + Group<clang_ignored_gcc_optimization_f_Group>; def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>; def : Flag<["-"], "fno-expensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>; def fextdirs_EQ : Joined<["-"], "fextdirs=">, Group<f_Group>; @@ -501,9 +509,8 @@ def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>; def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>; def fsanitize_EQ : CommaJoined<["-"], "fsanitize=">, Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>, MetaVarName<"<check>">, - HelpText<"Enable runtime instrumentation for bug detection: " - "address (memory errors) | thread (race detection) | " - "undefined (miscellaneous undefined behavior)">; + HelpText<"Turn on runtime checks for various forms of undefined " + "or suspicious behavior. See user manual for available checks ">; def fno_sanitize_EQ : CommaJoined<["-"], "fno-sanitize=">, Group<f_clang_Group>; def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, Group<f_clang_Group>, Flags<[CC1Option, CoreOption]>, @@ -511,6 +518,9 @@ def fsanitize_blacklist : Joined<["-"], "fsanitize-blacklist=">, def fno_sanitize_blacklist : Flag<["-"], "fno-sanitize-blacklist">, Group<f_clang_Group>, HelpText<"Don't use blacklist file for sanitizers">; +def fsanitize_coverage : Joined<["-"], "fsanitize-coverage=">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Enable coverage instrumentation for Sanitizers">; def fsanitize_memory_track_origins_EQ : Joined<["-"], "fsanitize-memory-track-origins=">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Enable origins tracking in MemorySanitizer">; @@ -520,15 +530,26 @@ def fsanitize_memory_track_origins : Flag<["-"], "fsanitize-memory-track-origins def fno_sanitize_memory_track_origins : Flag<["-"], "fno-sanitize-memory-track-origins">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Disable origins tracking in MemorySanitizer">; -def fsanitize_recover : Flag<["-"], "fsanitize-recover">, - Group<f_clang_Group>; +def fsanitize_address_field_padding : Joined<["-"], "fsanitize-address-field-padding=">, + Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Level of field padding for AddressSanitizer">; +def fsanitize_recover : Flag<["-"], "fsanitize-recover">, Group<f_clang_Group>; def fno_sanitize_recover : Flag<["-"], "fno-sanitize-recover">, - Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"Disable sanitizer check recovery">; + Group<f_clang_Group>; +def fsanitize_recover_EQ : CommaJoined<["-"], "fsanitize-recover=">, + Group<f_clang_Group>, + Flags<[CC1Option]>, + HelpText<"Enable recovery for specified sanitizers">; +def fno_sanitize_recover_EQ + : CommaJoined<["-"], "fno-sanitize-recover=">, + Group<f_clang_Group>, + HelpText<"Disable recovery for specified sanitizers">; def fsanitize_undefined_trap_on_error : Flag<["-"], "fsanitize-undefined-trap-on-error">, Group<f_clang_Group>, Flags<[CC1Option]>; def fno_sanitize_undefined_trap_on_error : Flag<["-"], "fno-sanitize-undefined-trap-on-error">, Group<f_clang_Group>; +def fsanitize_link_cxx_runtime : Flag<["-"], "fsanitize-link-c++-runtime">, + Group<f_clang_Group>; def funsafe_math_optimizations : Flag<["-"], "funsafe-math-optimizations">, Group<f_Group>; def fno_unsafe_math_optimizations : Flag<["-"], "fno-unsafe-math-optimizations">, @@ -561,6 +582,13 @@ def frewrite_includes : Flag<["-"], "frewrite-includes">, Group<f_Group>, Flags<[CC1Option]>; def fno_rewrite_includes : Flag<["-"], "fno-rewrite-includes">, Group<f_Group>; +def frewrite_map_file : Separate<["-"], "frewrite-map-file">, + Group<f_Group>, + Flags<[ DriverOption, CC1Option ]>; +def frewrite_map_file_EQ : Joined<["-"], "frewrite-map-file=">, + Group<f_Group>, + Flags<[DriverOption]>; + def ffreestanding : Flag<["-"], "ffreestanding">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Assert that the compilation takes place in a freestanding environment">; def fgnu_keywords : Flag<["-"], "fgnu-keywords">, Group<f_Group>, Flags<[CC1Option]>, @@ -576,11 +604,13 @@ def : Flag<["-"], "findirect-virtual-calls">, Alias<fapple_kext>; def finline_functions : Flag<["-"], "finline-functions">, Group<clang_ignored_gcc_optimization_f_Group>; def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>; def finput_charset_EQ : Joined<["-"], "finput-charset=">, Group<f_Group>; +def fexec_charset_EQ : Joined<["-"], "fexec-charset=">, Group<f_Group>; def finstrument_functions : Flag<["-"], "finstrument-functions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Generate calls to instrument function entry and exit">; def flat__namespace : Flag<["-"], "flat_namespace">; def flax_vector_conversions : Flag<["-"], "flax-vector-conversions">, Group<f_Group>; def flimited_precision_EQ : Joined<["-"], "flimited-precision=">, Group<f_Group>; +def flto_EQ : Joined<["-"], "flto=">, Group<clang_ignored_gcc_optimization_f_Group>; def flto : Flag<["-"], "flto">, Group<f_Group>; def fno_lto : Flag<["-"], "fno-lto">, Group<f_Group>; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, @@ -622,10 +652,13 @@ def fmodules_search_all : Flag <["-"], "fmodules-search-all">, Group<f_Group>, def fbuild_session_timestamp : Joined<["-"], "fbuild-session-timestamp=">, Group<i_Group>, Flags<[CC1Option]>, MetaVarName<"<time since Epoch in seconds>">, HelpText<"Time when the current build session started">; +def fbuild_session_file : Joined<["-"], "fbuild-session-file=">, + Group<i_Group>, MetaVarName<"<file>">, + HelpText<"Use the last modification time of <file> as the build session timestamp">; def fmodules_validate_once_per_build_session : Flag<["-"], "fmodules-validate-once-per-build-session">, Group<i_Group>, Flags<[CC1Option]>, HelpText<"Don't verify input files for the modules if the module has been " - "successfully validate or loaded during this build session">; + "successfully validated or loaded during this build session">; def fmodules_validate_system_headers : Flag<["-"], "fmodules-validate-system-headers">, Group<i_Group>, Flags<[CC1Option]>, HelpText<"Validate the system headers that a module depends on when loading the module">; @@ -638,9 +671,12 @@ def fmodule_maps : Flag <["-"], "fmodule-maps">, Group<f_Group>, def fmodule_name : JoinedOrSeparate<["-"], "fmodule-name=">, Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<name>">, HelpText<"Specify the name of the module to build">; -def fmodule_map_file : JoinedOrSeparate<["-"], "fmodule-map-file=">, +def fmodule_map_file : Joined<["-"], "fmodule-map-file=">, Group<f_Group>, Flags<[DriverOption,CC1Option]>, MetaVarName<"<file>">, HelpText<"Load this module map file">; +def fmodule_file : Joined<["-"], "fmodule-file=">, + Group<f_Group>, Flags<[DriverOption,CC1Option]>, + HelpText<"Load this precompiled module file">, MetaVarName<"<file>">; def fmodules_ignore_macro : Joined<["-"], "fmodules-ignore-macro=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Ignore the definition of the given macro when building and loading modules">; def fmodules_decluse : Flag <["-"], "fmodules-decluse">, Group<f_Group>, @@ -651,6 +687,12 @@ def fmodules_strict_decluse : Flag <["-"], "fmodules-strict-decluse">, Group<f_G HelpText<"Like -fmodules-decluse but requires all headers to be in modules">; def fno_modules_search_all : Flag <["-"], "fno-modules-search-all">, Group<f_Group>, Flags<[DriverOption, CC1Option]>; +def fmodules_implicit_maps : + Flag <["-"], "fmodules-implicit-maps">, + Group<f_Group>, Flags<[DriverOption, CC1Option]>; +def fno_modules_implicit_maps : + Flag <["-"], "fno-modules-implicit-maps">, + Group<f_Group>, Flags<[DriverOption, CC1Option]>; def fretain_comments_from_system_headers : Flag<["-"], "fretain-comments-from-system-headers">, Group<f_Group>, Flags<[CC1Option]>; def fmudflapth : Flag<["-"], "fmudflapth">, Group<f_Group>; @@ -793,11 +835,15 @@ def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Gr def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; def force__flat__namespace : Flag<["-"], "force_flat_namespace">; def force__load : Separate<["-"], "force_load">; +def force_addr : Joined<["-"], "fforce-addr">, Group<clang_ignored_f_Group>; def foutput_class_dir_EQ : Joined<["-"], "foutput-class-dir=">, Group<f_Group>; def fpack_struct : Flag<["-"], "fpack-struct">, Group<f_Group>; def fno_pack_struct : Flag<["-"], "fno-pack-struct">, Group<f_Group>; def fpack_struct_EQ : Joined<["-"], "fpack-struct=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Specify the default maximum struct packing alignment">; +def fmax_type_align_EQ : Joined<["-"], "fmax-type-align=">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Specify the maximum alignment to enforce on pointers lacking an explicit alignment">; +def fno_max_type_align : Flag<["-"], "fno-max-type-align">, Group<f_Group>; def fpascal_strings : Flag<["-"], "fpascal-strings">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Recognize and construct Pascal-style string literals">; def fpcc_struct_return : Flag<["-"], "fpcc-struct-return">, Group<f_Group>, Flags<[CC1Option]>, @@ -808,6 +854,7 @@ def fno_pic : Flag<["-"], "fno-pic">, Group<f_Group>; def fpie : Flag<["-"], "fpie">, Group<f_Group>; def fno_pie : Flag<["-"], "fno-pie">, Group<f_Group>; def fprofile_arcs : Flag<["-"], "fprofile-arcs">, Group<f_Group>; +def fno_profile_arcs : Flag<["-"], "fno-profile-arcs">, Group<f_Group>; def fprofile_generate : Flag<["-"], "fprofile-generate">, Group<f_Group>; def framework : Separate<["-"], "framework">, Flags<[LinkerInput]>; def frandom_seed_EQ : Joined<["-"], "frandom-seed=">, Group<clang_ignored_f_Group>; @@ -817,7 +864,6 @@ def frtti : Flag<["-"], "frtti">, Group<f_Group>; def : Flag<["-"], "fsched-interblock">, Group<clang_ignored_f_Group>; def fshort_enums : Flag<["-"], "fshort-enums">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Allocate to an enum type only as many bytes as it needs for the declared range of possible values">; -def : Flag<["-"], "freorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>; def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Force wchar_t to be a short unsigned int">; def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, Flags<[CC1Option]>, @@ -828,6 +874,7 @@ def fshow_overloads_EQ : Joined<["-"], "fshow-overloads=">, Group<f_Group>, Flag def fshow_column : Flag<["-"], "fshow-column">, Group<f_Group>, Flags<[CC1Option]>; def fshow_source_location : Flag<["-"], "fshow-source-location">, Group<f_Group>; def fspell_checking : Flag<["-"], "fspell-checking">, Group<f_Group>; +def fspell_checking_limit_EQ : Joined<["-"], "fspell-checking-limit=">, Group<f_Group>; def fsigned_bitfields : Flag<["-"], "fsigned-bitfields">, Group<f_Group>; def fsigned_char : Flag<["-"], "fsigned-char">, Group<f_Group>; def fno_signed_char : Flag<["-"], "fno-signed-char">, Flags<[CC1Option]>, @@ -905,6 +952,10 @@ def freroll_loops : Flag<["-"], "freroll-loops">, Group<f_Group>, HelpText<"Turn on loop reroller">, Flags<[CC1Option]>; def fno_reroll_loops : Flag<["-"], "fno-reroll-loops">, Group<f_Group>, HelpText<"Turn off loop reroller">; +def ftrigraphs : Flag<["-"], "ftrigraphs">, Group<f_Group>, + HelpText<"Process trigraph sequences">, Flags<[CC1Option]>; +def fno_trigraphs : Flag<["-"], "fno-trigraphs">, Group<f_Group>, + HelpText<"Do not process trigraph sequences">, Flags<[CC1Option]>; def funsigned_bitfields : Flag<["-"], "funsigned-bitfields">, Group<f_Group>; def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>; def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">, Group<clang_ignored_f_Group>; @@ -912,8 +963,7 @@ def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>; def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>; def fuse_init_array : Flag<["-"], "fuse-init-array">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use .init_array instead of .ctors">; -def fno_var_tracking : Flag<["-"], "fno-var-tracking">, - Group<clang_ignored_f_Group>; +def fno_var_tracking : Flag<["-"], "fno-var-tracking">, Group<clang_ignored_f_Group>; def fverbose_asm : Flag<["-"], "fverbose-asm">, Group<f_Group>; def fvisibility_EQ : Joined<["-"], "fvisibility=">, Group<f_Group>, HelpText<"Set the default symbol visibility for all global declarations">; @@ -1037,6 +1087,10 @@ def m3dnow : Flag<["-"], "m3dnow">, Group<m_x86_Features_Group>; def m64 : Flag<["-"], "m64">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def mx32 : Flag<["-"], "mx32">, Group<m_Group>, Flags<[DriverOption, CoreOption]>; def mabi_EQ : Joined<["-"], "mabi=">, Group<m_Group>; +def malign_functions_EQ : Joined<["-"], "malign-functions=">, Group<clang_ignored_m_Group>; +def malign_loops_EQ : Joined<["-"], "malign-loops=">, Group<clang_ignored_m_Group>; +def malign_jumps_EQ : Joined<["-"], "malign-jumps=">, Group<clang_ignored_m_Group>; +def mfancy_math_387 : Flag<["-"], "mfancy-math-387">, Group<clang_ignored_m_Group>; def march_EQ : Joined<["-"], "march=">, Group<m_Group>; def masm_EQ : Joined<["-"], "masm=">, Group<m_Group>, Flags<[DriverOption]>; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group<m_Group>; @@ -1054,20 +1108,25 @@ def mhwdiv_EQ : Joined<["-"], "mhwdiv=">, Group<m_Group>; def mglobal_merge : Flag<["-"], "mglobal-merge">, Group<m_Group>; def mhard_float : Flag<["-"], "mhard-float">, Group<m_Group>; def miphoneos_version_min_EQ : Joined<["-"], "miphoneos-version-min=">, Group<m_Group>; -def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, Alias<miphoneos_version_min_EQ>; -def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Group<m_Group>; +def mios_version_min_EQ : Joined<["-"], "mios-version-min=">, + Alias<miphoneos_version_min_EQ>, HelpText<"Set iOS deployment target">; +def mios_simulator_version_min_EQ : Joined<["-"], "mios-simulator-version-min=">, Alias<miphoneos_version_min_EQ>; def mkernel : Flag<["-"], "mkernel">, Group<m_Group>; def mlinker_version_EQ : Joined<["-"], "mlinker-version=">, Flags<[DriverOption]>; def mllvm : Separate<["-"], "mllvm">, Flags<[CC1Option,CC1AsOption,CoreOption]>, HelpText<"Additional arguments to forward to LLVM's option processing">; -def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">, Group<m_Group>; +def mmacosx_version_min_EQ : Joined<["-"], "mmacosx-version-min=">, + Group<m_Group>, HelpText<"Set Mac OS X deployment target">; def mms_bitfields : Flag<["-"], "mms-bitfields">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Set the default structure layout to be compatible with the Microsoft compiler standard">; def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Force realign the stack at entry to every function">; def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Set the stack alignment">; +def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"The thread model to use, e.g. posix, single (posix by default)">; + def mmmx : Flag<["-"], "mmmx">, Group<m_x86_Features_Group>; def mno_3dnowa : Flag<["-"], "mno-3dnowa">, Group<m_x86_Features_Group>; def mno_3dnow : Flag<["-"], "mno-3dnow">, Group<m_x86_Features_Group>; @@ -1097,9 +1156,13 @@ def mno_avx512f : Flag<["-"], "mno-avx512f">, Group<m_x86_Features_Group>; def mno_avx512cd : Flag<["-"], "mno-avx512cd">, Group<m_x86_Features_Group>; def mno_avx512er : Flag<["-"], "mno-avx512er">, Group<m_x86_Features_Group>; def mno_avx512pf : Flag<["-"], "mno-avx512pf">, Group<m_x86_Features_Group>; +def mno_avx512dq : Flag<["-"], "mno-avx512dq">, Group<m_x86_Features_Group>; +def mno_avx512bw : Flag<["-"], "mno-avx512bw">, Group<m_x86_Features_Group>; +def mno_avx512vl : Flag<["-"], "mno-avx512vl">, Group<m_x86_Features_Group>; def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>; def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>; def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>; +def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>; def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>; def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>; def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>; @@ -1111,6 +1174,7 @@ def mno_f16c : Flag<["-"], "mno-f16c">, Group<m_x86_Features_Group>; def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>; def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>; def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>; +def mno_adx : Flag<["-"], "mno-adx">, Group<m_x86_Features_Group>; def mno_sha : Flag<["-"], "mno-sha">, Group<m_x86_Features_Group>; def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>, @@ -1118,7 +1182,7 @@ def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_G def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>, HelpText<"Force all memory accesses to be aligned (AArch32/AArch64 only)">; def mstrict_align : Flag<["-"], "mstrict-align">, Alias<mno_unaligned_access>, Flags<[CC1Option,HelpHidden]>, - HelpText<"Force all memory accesses to be aligned (AArch64 only, same as mno-unaligned-access)">; + HelpText<"Force all memory accesses to be aligned (same as mno-unaligned-access)">; def mno_thumb : Flag<["-"], "mno-thumb">, Group<m_arm_Features_Group>; def mrestrict_it: Flag<["-"], "mrestrict-it">, Group<m_arm_Features_Group>, HelpText<"Disallow generation of deprecated IT blocks for ARMv8. It is on by default for ARMv8 Thumb mode.">; @@ -1139,10 +1203,23 @@ def mno_long_calls : Flag<["-"], "mno-long-calls">, Group<m_arm_Features_Group>, def mgeneral_regs_only : Flag<["-"], "mgeneral-regs-only">, Group<m_aarch64_Features_Group>, HelpText<"Generate code which only uses the general purpose registers (AArch64 only)">; +def mfix_cortex_a53_835769 : Flag<["-"], "mfix-cortex-a53-835769">, + Group<m_aarch64_Features_Group>, + HelpText<"Workaround Cortex-A53 erratum 835769 (AArch64 only)">; +def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">, + Group<m_aarch64_Features_Group>, + HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">; + def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>; def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>; +def mpower8_vector : Flag<["-"], "mpower8-vector">, + Group<m_ppc_Features_Group>; +def mno_power8_vector : Flag<["-"], "mno-power8-vector">, + Group<m_ppc_Features_Group>; def mfprnd : Flag<["-"], "mfprnd">, Group<m_ppc_Features_Group>; def mno_fprnd : Flag<["-"], "mno-fprnd">, Group<m_ppc_Features_Group>; +def mcmpb : Flag<["-"], "mcmpb">, Group<m_ppc_Features_Group>; +def mno_cmpb : Flag<["-"], "mno-cmpb">, Group<m_ppc_Features_Group>; def mmfcrf : Flag<["-"], "mmfcrf">, Group<m_ppc_Features_Group>; def mno_mfcrf : Flag<["-"], "mno-mfcrf">, Group<m_ppc_Features_Group>; def mpopcntd : Flag<["-"], "mpopcntd">, Group<m_ppc_Features_Group>; @@ -1191,9 +1268,13 @@ def mavx512f : Flag<["-"], "mavx512f">, Group<m_x86_Features_Group>; def mavx512cd : Flag<["-"], "mavx512cd">, Group<m_x86_Features_Group>; def mavx512er : Flag<["-"], "mavx512er">, Group<m_x86_Features_Group>; def mavx512pf : Flag<["-"], "mavx512pf">, Group<m_x86_Features_Group>; +def mavx512dq : Flag<["-"], "mavx512dq">, Group<m_x86_Features_Group>; +def mavx512bw : Flag<["-"], "mavx512bw">, Group<m_x86_Features_Group>; +def mavx512vl : Flag<["-"], "mavx512vl">, Group<m_x86_Features_Group>; def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>; def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>; def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>; +def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>; def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>; def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>; def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>; @@ -1205,6 +1286,7 @@ def mf16c : Flag<["-"], "mf16c">, Group<m_x86_Features_Group>; def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>; def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>; def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>; +def madx : Flag<["-"], "madx">, Group<m_x86_Features_Group>; def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>; def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>; def mips16 : Flag<["-"], "mips16">, Group<m_Group>; @@ -1233,6 +1315,10 @@ def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>, def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>, HelpText<"Use 32-bit floating point registers (MIPS only)">; def mnan_EQ : Joined<["-"], "mnan=">, Group<m_Group>; +def mabicalls : Flag<["-"], "mabicalls">, Group<m_Group>, + HelpText<"Enable SVR4-style position-independent code (Mips only)">; +def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_Group>, + HelpText<"Disable SVR4-style position-independent code (Mips only)">; def mips1 : Flag<["-"], "mips1">, Alias<march_EQ>, AliasArgs<["mips1"]>, HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>; @@ -1275,6 +1361,8 @@ def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_Group>, def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_Group>, HelpText<"Disable odd single-precision floating point registers">, Flags<[HelpHidden]>; +def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>; +def muclibc : Flag<["-"], "muclibc">, Group<m_libc_Group>, Flags<[HelpHidden]>; def module_file_info : Flag<["-"], "module-file-info">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>; def mthumb : Flag<["-"], "mthumb">, Group<m_Group>; def mtune_EQ : Joined<["-"], "mtune=">, Group<m_Group>; @@ -1403,7 +1491,7 @@ def time : Flag<["-"], "time">, def traditional_cpp : Flag<["-", "--"], "traditional-cpp">, Flags<[CC1Option]>, HelpText<"Enable some traditional CPP emulation">; def traditional : Flag<["-", "--"], "traditional">; -def trigraphs : Flag<["-", "--"], "trigraphs">, Flags<[CC1Option]>, +def trigraphs : Flag<["-", "--"], "trigraphs">, Alias<ftrigraphs>, HelpText<"Process trigraph sequences">; def twolevel__namespace__hints : Flag<["-"], "twolevel_namespace_hints">; def twolevel__namespace : Flag<["-"], "twolevel_namespace">; @@ -1455,7 +1543,7 @@ def _all_warnings : Flag<["--"], "all-warnings">, Alias<Wall>; def _analyze_auto : Flag<["--"], "analyze-auto">, Flags<[DriverOption]>; def _analyzer_no_default_checks : Flag<["--"], "analyzer-no-default-checks">, Flags<[DriverOption]>; def _analyzer_output : JoinedOrSeparate<["--"], "analyzer-output">, Flags<[DriverOption]>; -def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption]>, +def _analyze : Flag<["--"], "analyze">, Flags<[DriverOption, CoreOption]>, HelpText<"Run the static analyzer">; def _assemble : Flag<["--"], "assemble">, Alias<S>; def _assert_EQ : Joined<["--"], "assert=">, Alias<A>; @@ -1591,7 +1679,7 @@ multiclass BooleanFFlag<string name> { def _fno : Flag<["-"], "fno-"#name>; } -defm : BooleanFFlag<"no-keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>; +defm : BooleanFFlag<"keep-inline-functions">, Group<clang_ignored_gcc_optimization_f_Group>; def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<clang_ignored_gcc_optimization_f_Group>; @@ -1601,22 +1689,52 @@ def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>; defm align_functions : BooleanFFlag<"align-functions">, Group<clang_ignored_gcc_optimization_f_Group>; def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<clang_ignored_gcc_optimization_f_Group>; +defm align_labels : BooleanFFlag<"align-labels">, Group<clang_ignored_gcc_optimization_f_Group>; +def falign_labels_EQ : Joined<["-"], "falign-labels=">, Group<clang_ignored_gcc_optimization_f_Group>; +defm align_loops : BooleanFFlag<"align-loops">, Group<clang_ignored_gcc_optimization_f_Group>; +def falign_loops_EQ : Joined<["-"], "falign-loops=">, Group<clang_ignored_gcc_optimization_f_Group>; +defm align_jumps : BooleanFFlag<"align-jumps">, Group<clang_ignored_gcc_optimization_f_Group>; +def falign_jumps_EQ : Joined<["-"], "falign-jumps=">, Group<clang_ignored_gcc_optimization_f_Group>; // FIXME: This option should be supported and wired up to our diognostics, but // ignore it for now to avoid breaking builds that use it. def fdiagnostics_show_location_EQ : Joined<["-"], "fdiagnostics-show-location=">, Group<clang_ignored_f_Group>; +defm fcheck_new : BooleanFFlag<"check-new">, Group<clang_ignored_f_Group>; +defm caller_saves : BooleanFFlag<"caller-saves">, Group<clang_ignored_gcc_optimization_f_Group>; +defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_optimization_f_Group>; defm eliminate_unused_debug_types : BooleanFFlag<"eliminate-unused-debug-types">, Group<clang_ignored_f_Group>; +defm branch_count_reg : BooleanFFlag<"branch-count-reg">, Group<clang_ignored_gcc_optimization_f_Group>; +defm default_inline : BooleanFFlag<"default-inline">, Group<clang_ignored_gcc_optimization_f_Group>; +defm delete_null_pointer_checks : BooleanFFlag<"delete-null-pointer-checks">, + Group<clang_ignored_gcc_optimization_f_Group>; +defm fat_lto_objects : BooleanFFlag<"fat-lto-objects">, Group<clang_ignored_gcc_optimization_f_Group>; defm float_store : BooleanFFlag<"float-store">, Group<clang_ignored_gcc_optimization_f_Group>; +defm friend_injection : BooleanFFlag<"friend-injection">, Group<clang_ignored_f_Group>; defm function_attribute_list : BooleanFFlag<"function-attribute-list">, Group<clang_ignored_f_Group>; defm gcse : BooleanFFlag<"gcse">, Group<clang_ignored_gcc_optimization_f_Group>; +defm gcse_after_reload: BooleanFFlag<"gcse-after-reload">, Group<clang_ignored_gcc_optimization_f_Group>; +defm gcse_las: BooleanFFlag<"gcse-las">, Group<clang_ignored_gcc_optimization_f_Group>; +defm gcse_sm: BooleanFFlag<"gcse-sm">, Group<clang_ignored_gcc_optimization_f_Group>; defm gnu : BooleanFFlag<"gnu">, Group<clang_ignored_f_Group>; defm ident : BooleanFFlag<"ident">, Group<clang_ignored_f_Group>; defm implicit_templates : BooleanFFlag<"implicit-templates">, Group<clang_ignored_f_Group>; +defm implement_inlines : BooleanFFlag<"implement-inlines">, Group<clang_ignored_f_Group>; +defm merge_constants : BooleanFFlag<"merge-constants">, Group<clang_ignored_gcc_optimization_f_Group>; +defm modulo_sched : BooleanFFlag<"modulo-sched">, Group<clang_ignored_gcc_optimization_f_Group>; +defm modulo_sched_allow_regmoves : BooleanFFlag<"modulo-sched-allow-regmoves">, + Group<clang_ignored_gcc_optimization_f_Group>; +defm inline_functions_called_once : BooleanFFlag<"inline-functions-called-once">, + Group<clang_ignored_gcc_optimization_f_Group>; def finline_limit_EQ : Joined<["-"], "finline-limit=">, Group<clang_ignored_gcc_optimization_f_Group>; defm finline_limit : BooleanFFlag<"inline-limit">, Group<clang_ignored_gcc_optimization_f_Group>; +defm inline_small_functions : BooleanFFlag<"inline-small-functions">, + Group<clang_ignored_gcc_optimization_f_Group>; +defm ipa_cp : BooleanFFlag<"ipa-cp">, + Group<clang_ignored_gcc_optimization_f_Group>; defm ivopts : BooleanFFlag<"ivopts">, Group<clang_ignored_gcc_optimization_f_Group>; defm non_call_exceptions : BooleanFFlag<"non-call-exceptions">, Group<clang_ignored_f_Group>; +defm peel_loops : BooleanFFlag<"peel-loops">, Group<clang_ignored_gcc_optimization_f_Group>; defm permissive : BooleanFFlag<"permissive">, Group<clang_ignored_f_Group>; defm prefetch_loop_arrays : BooleanFFlag<"prefetch-loop-arrays">, Group<clang_ignored_gcc_optimization_f_Group>; defm printf : BooleanFFlag<"printf">, Group<clang_ignored_f_Group>; @@ -1626,21 +1744,42 @@ defm profile_generate_sampling : BooleanFFlag<"profile-generate-sampling">, Grou defm profile_reusedist : BooleanFFlag<"profile-reusedist">, Group<clang_ignored_f_Group>; defm profile_values : BooleanFFlag<"profile-values">, Group<clang_ignored_gcc_optimization_f_Group>; defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>; +defm rename_registers : BooleanFFlag<"rename-registers">, Group<clang_ignored_gcc_optimization_f_Group>; defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>; defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_gcc_optimization_f_Group>; defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_gcc_optimization_f_Group>; +defm schedule_insns2 : BooleanFFlag<"schedule-insns2">, Group<clang_ignored_gcc_optimization_f_Group>; defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>; defm signaling_nans : BooleanFFlag<"signaling-nans">, Group<clang_ignored_gcc_optimization_f_Group>; +defm single_precision_constant : BooleanFFlag<"single-precision-constant">, + Group<clang_ignored_gcc_optimization_f_Group>; defm spec_constr_count : BooleanFFlag<"spec-constr-count">, Group<clang_ignored_f_Group>; +defm stack_check : BooleanFFlag<"stack-check">, Group<clang_ignored_f_Group>; defm strength_reduce : BooleanFFlag<"strength-reduce">, Group<clang_ignored_gcc_optimization_f_Group>; defm tls_model : BooleanFFlag<"tls-model">, Group<clang_ignored_f_Group>; defm tracer : BooleanFFlag<"tracer">, Group<clang_ignored_gcc_optimization_f_Group>; +defm tree_dce : BooleanFFlag<"tree-dce">, Group<clang_ignored_gcc_optimization_f_Group>; +defm tree_loop_im : BooleanFFlag<"tree_loop_im">, Group<clang_ignored_gcc_optimization_f_Group>; +defm tree_loop_ivcanon : BooleanFFlag<"tree_loop_ivcanon">, Group<clang_ignored_gcc_optimization_f_Group>; +defm tree_loop_linear : BooleanFFlag<"tree_loop_linear">, Group<clang_ignored_gcc_optimization_f_Group>; defm tree_salias : BooleanFFlag<"tree-salias">, Group<clang_ignored_f_Group>; +defm tree_ter : BooleanFFlag<"tree-ter">, Group<clang_ignored_gcc_optimization_f_Group>; defm tree_vectorizer_verbose : BooleanFFlag<"tree-vectorizer-verbose">, Group<clang_ignored_f_Group>; +defm tree_vrp : BooleanFFlag<"tree-vrp">, Group<clang_ignored_gcc_optimization_f_Group>; defm unroll_all_loops : BooleanFFlag<"unroll-all-loops">, Group<clang_ignored_gcc_optimization_f_Group>; +defm unsafe_loop_optimizations : BooleanFFlag<"unsafe-loop-optimizations">, + Group<clang_ignored_gcc_optimization_f_Group>; defm unswitch_loops : BooleanFFlag<"unswitch-loops">, Group<clang_ignored_gcc_optimization_f_Group>; - +defm use_linker_plugin : BooleanFFlag<"use-linker-plugin">, Group<clang_ignored_gcc_optimization_f_Group>; +defm vect_cost_model : BooleanFFlag<"vect-cost-model">, Group<clang_ignored_gcc_optimization_f_Group>; +defm variable_expansion_in_unroller : BooleanFFlag<"variable-expansion-in-unroller">, + Group<clang_ignored_gcc_optimization_f_Group>; +defm web : BooleanFFlag<"web">, Group<clang_ignored_gcc_optimization_f_Group>; +defm whole_program : BooleanFFlag<"whole-program">, Group<clang_ignored_gcc_optimization_f_Group>; +defm devirtualize : BooleanFFlag<"devirtualize">, Group<clang_ignored_gcc_optimization_f_Group>; +defm devirtualize_speculatively : BooleanFFlag<"devirtualize-speculatively">, + Group<clang_ignored_gcc_optimization_f_Group>; // gfortran options that we recognize in the driver and pass along when // invoking GCC to compile Fortran code. diff --git a/include/clang/Driver/Phases.h b/include/clang/Driver/Phases.h index 4e0f40c17dff..cd6b5b5c9f05 100644 --- a/include/clang/Driver/Phases.h +++ b/include/clang/Driver/Phases.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_PHASES_H_ -#define CLANG_DRIVER_PHASES_H_ +#ifndef LLVM_CLANG_DRIVER_PHASES_H +#define LLVM_CLANG_DRIVER_PHASES_H namespace clang { namespace driver { @@ -19,6 +19,7 @@ namespace phases { Preprocess, Precompile, Compile, + Backend, Assemble, Link }; diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index c79c4714f4f9..3524da0e7ffe 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -6,9 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef CLANG_LIB_DRIVER_SANITIZERARGS_H_ -#define CLANG_LIB_DRIVER_SANITIZERARGS_H_ +#ifndef LLVM_CLANG_DRIVER_SANITIZERARGS_H +#define LLVM_CLANG_DRIVER_SANITIZERARGS_H +#include "clang/Basic/Sanitizers.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include <string> @@ -20,131 +21,46 @@ class Driver; class ToolChain; class SanitizerArgs { - /// Assign ordinals to sanitizer flags. We'll use the ordinal values as - /// bit positions within \c Kind. - enum SanitizeOrdinal { -#define SANITIZER(NAME, ID) SO_##ID, -#define SANITIZER_GROUP(NAME, ID, ALIAS) SO_##ID##Group, -#include "clang/Basic/Sanitizers.def" - SO_Count - }; - - /// Bugs to catch at runtime. - enum SanitizeKind { -#define SANITIZER(NAME, ID) ID = 1 << SO_##ID, -#define SANITIZER_GROUP(NAME, ID, ALIAS) \ - ID = ALIAS, ID##Group = 1 << SO_##ID##Group, -#include "clang/Basic/Sanitizers.def" - NeedsAsanRt = Address, - NeedsTsanRt = Thread, - NeedsMsanRt = Memory, - NeedsDfsanRt = DataFlow, - NeedsLeakDetection = Leak, - NeedsUbsanRt = Undefined | Integer, - NotAllowedWithTrap = Vptr, - HasZeroBaseShadow = Thread | Memory | DataFlow, - NeedsUnwindTables = Address | Thread | Memory | DataFlow - }; - unsigned Kind; + SanitizerSet Sanitizers; + SanitizerSet RecoverableSanitizers; std::string BlacklistFile; + int SanitizeCoverage; int MsanTrackOrigins; + int AsanFieldPadding; bool AsanZeroBaseShadow; bool UbsanTrapOnError; bool AsanSharedRuntime; + bool LinkCXXRuntimes; public: - SanitizerArgs(); /// Parses the sanitizer arguments from an argument list. SanitizerArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); - bool needsAsanRt() const { return Kind & NeedsAsanRt; } + bool needsAsanRt() const { return Sanitizers.has(SanitizerKind::Address); } bool needsSharedAsanRt() const { return AsanSharedRuntime; } - bool needsTsanRt() const { return Kind & NeedsTsanRt; } - bool needsMsanRt() const { return Kind & NeedsMsanRt; } - bool needsLeakDetection() const { return Kind & NeedsLeakDetection; } + bool needsTsanRt() const { return Sanitizers.has(SanitizerKind::Thread); } + bool needsMsanRt() const { return Sanitizers.has(SanitizerKind::Memory); } bool needsLsanRt() const { - return needsLeakDetection() && !needsAsanRt(); - } - bool needsUbsanRt() const { - return !UbsanTrapOnError && (Kind & NeedsUbsanRt); + return Sanitizers.has(SanitizerKind::Leak) && + !Sanitizers.has(SanitizerKind::Address); } - bool needsDfsanRt() const { return Kind & NeedsDfsanRt; } + bool needsUbsanRt() const; + bool needsDfsanRt() const { return Sanitizers.has(SanitizerKind::DataFlow); } - bool sanitizesVptr() const { return Kind & Vptr; } - bool notAllowedWithTrap() const { return Kind & NotAllowedWithTrap; } - bool hasZeroBaseShadow() const { - return (Kind & HasZeroBaseShadow) || AsanZeroBaseShadow; - } - bool needsUnwindTables() const { return Kind & NeedsUnwindTables; } + bool sanitizesVptr() const { return Sanitizers.has(SanitizerKind::Vptr); } + bool requiresPIE() const; + bool needsUnwindTables() const; + bool linkCXXRuntimes() const { return LinkCXXRuntimes; } void addArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; private: void clear(); - - /// Parse a single value from a -fsanitize= or -fno-sanitize= value list. - /// Returns OR of members of the \c SanitizeKind enumeration, or \c 0 - /// if \p Value is not known. - static unsigned parse(const char *Value); - - /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any - /// invalid components. - static unsigned parse(const Driver &D, const llvm::opt::Arg *A, - bool DiagnoseErrors); - - /// Parse a single flag of the form -f[no]sanitize=, or - /// -f*-sanitizer. Sets the masks defining required change of Kind value. - /// Returns true if the flag was parsed successfully. - static bool parse(const Driver &D, const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, unsigned &Add, unsigned &Remove, - bool DiagnoseErrors); - - /// Produce an argument string from ArgList \p Args, which shows how it - /// provides a sanitizer kind in \p Mask. For example, the argument list - /// "-fsanitize=thread,vptr -fsanitize=address" with mask \c NeedsUbsanRt - /// would produce "-fsanitize=vptr". - static std::string lastArgumentForKind(const Driver &D, - const llvm::opt::ArgList &Args, - unsigned Kind); - - /// Produce an argument string from argument \p A, which shows how it provides - /// a value in \p Mask. For instance, the argument - /// "-fsanitize=address,alignment" with mask \c NeedsUbsanRt would produce - /// "-fsanitize=alignment". - static std::string describeSanitizeArg(const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, - unsigned Mask); - - static bool getDefaultBlacklistForKind(const Driver &D, unsigned Kind, - std::string &BLPath); - - /// Return the smallest superset of sanitizer set \p Kinds such that each - /// member of each group whose flag is set in \p Kinds has its flag set in the - /// result. - static unsigned expandGroups(unsigned Kinds); - - /// Return the subset of \p Kinds supported by toolchain \p TC. If - /// \p DiagnoseErrors is true, produce an error diagnostic for each sanitizer - /// removed from \p Kinds. - static unsigned filterUnsupportedKinds(const ToolChain &TC, unsigned Kinds, - const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, - bool DiagnoseErrors, - unsigned &DiagnosedKinds); - - /// The flags in \p Mask are unsupported by \p TC. If present in \p Kinds, - /// remove them and produce an error diagnostic referring to \p A if - /// \p DiagnoseErrors is true. - static void filterUnsupportedMask(const ToolChain &TC, unsigned &Kinds, - unsigned Mask, - const llvm::opt::ArgList &Args, - const llvm::opt::Arg *A, - bool DiagnoseErrors, - unsigned &DiagnosedKinds); + bool getDefaultBlacklist(const Driver &D, std::string &BLPath); }; } // namespace driver } // namespace clang -#endif // CLANG_LIB_DRIVER_SANITIZERARGS_H_ +#endif diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 015dcf513e0a..b9eac1cad65d 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_TOOL_H_ -#define CLANG_DRIVER_TOOL_H_ +#ifndef LLVM_CLANG_DRIVER_TOOL_H +#define LLVM_CLANG_DRIVER_TOOL_H #include "clang/Basic/LLVM.h" +#include "llvm/Support/Program.h" namespace llvm { namespace opt { @@ -31,6 +32,24 @@ namespace driver { /// Tool - Information on a specific compilation tool. class Tool { +public: + // Documents the level of support for response files in this tool. + // Response files are necessary if the command line gets too large, + // requiring the arguments to be transfered to a file. + enum ResponseFileSupport { + // Provides full support for response files, which means we can transfer + // all tool input arguments to a file. E.g.: clang, gcc, binutils and MSVC + // tools. + RF_Full, + // Input file names can live in a file, but flags can't. E.g.: ld64 (Mac + // OS X linker). + RF_FileList, + // Does not support response files: all arguments must be passed via + // command line. + RF_None + }; + +private: /// The tool name (for debugging). const char *Name; @@ -40,9 +59,20 @@ class Tool { /// The tool chain this tool is a part of. const ToolChain &TheToolChain; + /// The level of support for response files seen in this tool + const ResponseFileSupport ResponseSupport; + + /// The encoding to use when writing response files for this tool on Windows + const llvm::sys::WindowsEncodingMethod ResponseEncoding; + + /// The flag used to pass a response file via command line to this tool + const char *const ResponseFlag; + public: - Tool(const char *Name, const char *ShortName, - const ToolChain &TC); + Tool(const char *Name, const char *ShortName, const ToolChain &TC, + ResponseFileSupport ResponseSupport = RF_None, + llvm::sys::WindowsEncodingMethod ResponseEncoding = llvm::sys::WEM_UTF8, + const char *ResponseFlag = "@"); public: virtual ~Tool(); @@ -54,9 +84,33 @@ public: const ToolChain &getToolChain() const { return TheToolChain; } virtual bool hasIntegratedAssembler() const { return false; } + virtual bool canEmitIR() const { return false; } virtual bool hasIntegratedCPP() const = 0; virtual bool isLinkJob() const { return false; } virtual bool isDsymutilJob() const { return false; } + /// \brief Returns the level of support for response files of this tool, + /// whether it accepts arguments to be passed via a file on disk. + ResponseFileSupport getResponseFilesSupport() const { + return ResponseSupport; + } + /// \brief Returns which encoding the response file should use. This is only + /// relevant on Windows platforms where there are different encodings being + /// accepted for different tools. On UNIX, UTF8 is universal. + /// + /// Windows use cases: - GCC and Binutils on mingw only accept ANSI response + /// files encoded with the system current code page. + /// - MSVC's CL.exe and LINK.exe accept UTF16 on Windows. + /// - Clang accepts both UTF8 and UTF16. + /// + /// FIXME: When GNU tools learn how to parse UTF16 on Windows, we should + /// always use UTF16 for Windows, which is the Windows official encoding for + /// international characters. + llvm::sys::WindowsEncodingMethod getResponseFileEncoding() const { + return ResponseEncoding; + } + /// \brief Returns which prefix to use when passing the name of a response + /// file as a parameter to this tool. + const char *getResponseFileFlag() const { return ResponseFlag; } /// \brief Does this tool have "good" standardized diagnostics, or should the /// driver add an additional "command failed" diagnostic on failures. diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 550e4dfc60c3..3092e81b95b5 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_TOOLCHAIN_H_ -#define CLANG_DRIVER_TOOLCHAIN_H_ +#ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H +#define LLVM_CLANG_DRIVER_TOOLCHAIN_H #include "clang/Driver/Action.h" #include "clang/Driver/Multilib.h" @@ -41,7 +41,7 @@ namespace driver { /// ToolChain - Access to tools for a single platform. class ToolChain { public: - typedef SmallVector<std::string, 4> path_list; + typedef SmallVector<std::string, 16> path_list; enum CXXStdlibType { CST_Libcxx, @@ -118,7 +118,7 @@ public: /// \brief Provide the default architecture name (as expected by -arch) for /// this toolchain. Note t - std::string getDefaultUniversalArchName() const; + StringRef getDefaultUniversalArchName() const; std::string getTripleString() const { return Triple.getTriple(); @@ -248,6 +248,12 @@ public: /// UseSjLjExceptions - Does this tool chain use SjLj exceptions. virtual bool UseSjLjExceptions() const { return false; } + /// getThreadModel() - Which thread model does this target use? + virtual std::string getThreadModel() const { return "posix"; } + + /// isThreadModelSupported() - Does this target support a thread model? + virtual bool isThreadModelSupported(const StringRef Model) const; + /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking /// command line arguments into account. virtual std::string diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index cca576a054aa..34442eb6379f 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_TYPES_H_ -#define CLANG_DRIVER_TYPES_H_ +#ifndef LLVM_CLANG_DRIVER_TYPES_H +#define LLVM_CLANG_DRIVER_TYPES_H #include "clang/Driver/Phases.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/clang/Driver/Util.h b/include/clang/Driver/Util.h index b24b9904f2b5..07495a18508c 100644 --- a/include/clang/Driver/Util.h +++ b/include/clang/Driver/Util.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_DRIVER_UTIL_H_ -#define CLANG_DRIVER_UTIL_H_ +#ifndef LLVM_CLANG_DRIVER_UTIL_H +#define LLVM_CLANG_DRIVER_UTIL_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index 45cccaacd569..60c54abd1a9b 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -15,8 +15,9 @@ #ifndef LLVM_CLANG_FORMAT_FORMAT_H #define LLVM_CLANG_FORMAT_FORMAT_H -#include "clang/Frontend/FrontendAction.h" -#include "clang/Tooling/Refactoring.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Tooling/Core/Replacement.h" +#include "llvm/ADT/ArrayRef.h" #include <system_error> namespace clang { @@ -47,6 +48,8 @@ struct FormatStyle { LK_None, /// Should be used for C, C++, ObjectiveC, ObjectiveC++. LK_Cpp, + /// Should be used for Java. + LK_Java, /// Should be used for JavaScript. LK_JavaScript, /// Should be used for Protocol Buffers @@ -150,10 +153,14 @@ struct FormatStyle { /// commonly have different usage patterns and a number of special cases. unsigned SpacesBeforeTrailingComments; - /// \brief If \c false, a function call's or function definition's parameters - /// will either all be on the same line or will have one line each. + /// \brief If \c false, a function declaration's or function definition's + /// parameters will either all be on the same line or will have one line each. bool BinPackParameters; + /// \brief If \c false, a function call's arguments will either be all on the + /// same line or will have one line each. + bool BinPackArguments; + /// \brief If \c true, clang-format detects whether function calls and /// definitions are formatted with one parameter per line. /// @@ -195,6 +202,9 @@ struct FormatStyle { /// single line. bool AllowShortLoopsOnASingleLine; + /// \brief If \c true, short case labels will be contracted to a single line. + bool AllowShortCaseLabelsOnASingleLine; + /// \brief Different styles for merging short functions containing at most one /// statement. enum ShortFunctionStyle { @@ -202,6 +212,8 @@ struct FormatStyle { SFS_None, /// \brief Only merge functions defined inside a class. SFS_Inline, + /// \brief Only merge empty functions. + SFS_Empty, /// \brief Merge all functions fitting on a single line. SFS_All, }; @@ -218,6 +230,20 @@ struct FormatStyle { /// <tt>Foo <Protocol></tt> instead of \c Foo<Protocol>. bool ObjCSpaceBeforeProtocolList; + /// \brief If \c true, horizontally aligns arguments after an open bracket. + /// + /// This applies to round brackets (parentheses), angle brackets and square + /// brackets. This will result in formattings like + /// \code + /// someLongFunction(argument1, + /// argument2); + /// \endcode + bool AlignAfterOpenBracket; + + /// \brief If \c true, horizontally align operands of binary and ternary + /// expressions. + bool AlignOperands; + /// \brief If \c true, aligns trailing comments. bool AlignTrailingComments; @@ -235,6 +261,16 @@ struct FormatStyle { /// initializer lists. unsigned ConstructorInitializerIndentWidth; + /// \brief The number of characters to use for indentation of ObjC blocks. + unsigned ObjCBlockIndentWidth; + + /// \brief If \c true, always break after function definition return types. + /// + /// More truthfully called 'break before the identifier following the type + /// in a function definition'. PenaltyReturnTypeOnItsOwnLine becomes + /// irrelevant. + bool AlwaysBreakAfterDefinitionReturnType; + /// \brief If \c true, always break after the <tt>template<...></tt> of a /// template declaration. bool AlwaysBreakTemplateDeclarations; @@ -256,8 +292,18 @@ struct FormatStyle { /// \brief The way to use tab characters in the resulting file. UseTabStyle UseTab; - /// \brief If \c true, binary operators will be placed after line breaks. - bool BreakBeforeBinaryOperators; + /// \brief The style of breaking before or after binary operators. + enum BinaryOperatorStyle { + /// Break after operators. + BOS_None, + /// Break before operators that aren't assignments. + BOS_NonAssignment, + /// Break before operators. + BOS_All, + }; + + /// \brief The way to wrap binary operators. + BinaryOperatorStyle BreakBeforeBinaryOperators; /// \brief If \c true, ternary operators will be placed after line breaks. bool BreakBeforeTernaryOperators; @@ -269,7 +315,7 @@ struct FormatStyle { /// Like \c Attach, but break before braces on function, namespace and /// class definitions. BS_Linux, - /// Like \c Attach, but break before function definitions. + /// Like \c Attach, but break before function definitions, and 'else'. BS_Stroustrup, /// Always break before braces. BS_Allman, @@ -304,6 +350,9 @@ struct FormatStyle { /// template argument lists bool SpacesInAngles; + /// \brief If \c true, spaces will be inserted after '[' and before ']'. + bool SpacesInSquareBrackets; + /// \brief If \c true, spaces may be inserted into '()'. bool SpaceInEmptyParentheses; @@ -314,6 +363,9 @@ struct FormatStyle { /// \brief If \c true, spaces may be inserted into C style casts. bool SpacesInCStyleCastParentheses; + /// \brief If \c true, a space may be inserted after C style casts. + bool SpaceAfterCStyleCast; + /// \brief Different ways to put a space before opening parentheses. enum SpaceBeforeParensOptions { /// Never put a space before opening parentheses. @@ -358,8 +410,8 @@ struct FormatStyle { bool operator==(const FormatStyle &R) const { return AccessModifierOffset == R.AccessModifierOffset && - ConstructorInitializerIndentWidth == - R.ConstructorInitializerIndentWidth && + AlignAfterOpenBracket == R.AlignAfterOpenBracket && + AlignOperands == R.AlignOperands && AlignEscapedNewlinesLeft == R.AlignEscapedNewlinesLeft && AlignTrailingComments == R.AlignTrailingComments && AllowAllParametersOfDeclarationOnNextLine == @@ -370,11 +422,14 @@ struct FormatStyle { AllowShortIfStatementsOnASingleLine == R.AllowShortIfStatementsOnASingleLine && AllowShortLoopsOnASingleLine == R.AllowShortLoopsOnASingleLine && + AlwaysBreakAfterDefinitionReturnType == + R.AlwaysBreakAfterDefinitionReturnType && AlwaysBreakTemplateDeclarations == R.AlwaysBreakTemplateDeclarations && AlwaysBreakBeforeMultilineStrings == R.AlwaysBreakBeforeMultilineStrings && BinPackParameters == R.BinPackParameters && + BinPackArguments == R.BinPackArguments && BreakBeforeBinaryOperators == R.BreakBeforeBinaryOperators && BreakBeforeTernaryOperators == R.BreakBeforeTernaryOperators && BreakBeforeBraces == R.BreakBeforeBraces && @@ -383,6 +438,8 @@ struct FormatStyle { ColumnLimit == R.ColumnLimit && ConstructorInitializerAllOnOneLineOrOnePerLine == R.ConstructorInitializerAllOnOneLineOrOnePerLine && + ConstructorInitializerIndentWidth == + R.ConstructorInitializerIndentWidth && DerivePointerAlignment == R.DerivePointerAlignment && ExperimentalAutoDetectBinPacking == R.ExperimentalAutoDetectBinPacking && @@ -393,6 +450,7 @@ struct FormatStyle { KeepEmptyLinesAtTheStartOfBlocks == R.KeepEmptyLinesAtTheStartOfBlocks && NamespaceIndentation == R.NamespaceIndentation && + ObjCBlockIndentWidth == R.ObjCBlockIndentWidth && ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty && ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList && PenaltyBreakComment == R.PenaltyBreakComment && @@ -405,10 +463,12 @@ struct FormatStyle { Cpp11BracedListStyle == R.Cpp11BracedListStyle && Standard == R.Standard && TabWidth == R.TabWidth && UseTab == R.UseTab && SpacesInParentheses == R.SpacesInParentheses && + SpacesInSquareBrackets == R.SpacesInSquareBrackets && SpacesInAngles == R.SpacesInAngles && SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && SpacesInContainerLiterals == R.SpacesInContainerLiterals && SpacesInCStyleCastParentheses == R.SpacesInCStyleCastParentheses && + SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && SpaceBeforeParens == R.SpaceBeforeParens && SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators && ContinuationIndentWidth == R.ContinuationIndentWidth && @@ -470,29 +530,34 @@ std::string configurationAsText(const FormatStyle &Style); /// \brief Reformats the given \p Ranges in the token stream coming out of /// \c Lex. /// +/// DEPRECATED: Do not use. +tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex, + SourceManager &SourceMgr, + ArrayRef<CharSourceRange> Ranges); + +/// \brief Reformats the given \p Ranges in the file \p ID. +/// /// Each range is extended on either end to its next bigger logic unit, i.e. /// everything that might influence its formatting or might be influenced by its /// formatting. /// /// Returns the \c Replacements necessary to make all \p Ranges comply with /// \p Style. -tooling::Replacements reformat(const FormatStyle &Style, Lexer &Lex, - SourceManager &SourceMgr, - std::vector<CharSourceRange> Ranges); +tooling::Replacements reformat(const FormatStyle &Style, + SourceManager &SourceMgr, FileID ID, + ArrayRef<CharSourceRange> Ranges); /// \brief Reformats the given \p Ranges in \p Code. /// /// Otherwise identical to the reformat() function consuming a \c Lexer. tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, - std::vector<tooling::Range> Ranges, + ArrayRef<tooling::Range> Ranges, StringRef FileName = "<stdin>"); /// \brief Returns the \c LangOpts that the formatter expects you to set. /// -/// \param Standard determines lexing mode: LC_Cpp11 and LS_Auto turn on C++11 -/// lexing mode, LS_Cpp03 - C++03 mode. -LangOptions getFormattingLangOpts( - FormatStyle::LanguageStandard Standard = FormatStyle::LS_Cpp11); +/// \param Style determines specific settings for lexing mode. +LangOptions getFormattingLangOpts(const FormatStyle &Style = getLLVMStyle()); /// \brief Description to be used for help text for a llvm::cl option for /// specifying format style. The description is closely related to the operation diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 366c499b67f5..757fcae988fc 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -#ifndef DRIVER_ASTCONSUMERS_H -#define DRIVER_ASTCONSUMERS_H +#ifndef LLVM_CLANG_FRONTEND_ASTCONSUMERS_H +#define LLVM_CLANG_FRONTEND_ASTCONSUMERS_H #include "clang/Basic/LLVM.h" +#include <memory> namespace clang { @@ -30,24 +31,27 @@ class TargetOptions; // original C code. The output is intended to be in a format such that // clang could re-parse the output back into the same AST, but the // implementation is still incomplete. -ASTConsumer *CreateASTPrinter(raw_ostream *OS, StringRef FilterString); +std::unique_ptr<ASTConsumer> CreateASTPrinter(raw_ostream *OS, + StringRef FilterString); // AST dumper: dumps the raw AST in human-readable form to stderr; this is // intended for debugging. -ASTConsumer *CreateASTDumper(StringRef FilterString, bool DumpLookups = false); +std::unique_ptr<ASTConsumer> CreateASTDumper(StringRef FilterString, + bool DumpDecls, + bool DumpLookups); // AST Decl node lister: prints qualified names of all filterable AST Decl // nodes. -ASTConsumer *CreateASTDeclNodeLister(); +std::unique_ptr<ASTConsumer> CreateASTDeclNodeLister(); // Graphical AST viewer: for each function definition, creates a graph of // the AST and displays it with the graph viewer "dotty". Also outputs // function declarations to stderr. -ASTConsumer *CreateASTViewer(); +std::unique_ptr<ASTConsumer> CreateASTViewer(); // DeclContext printer: prints out the DeclContext tree in human-readable form // to stderr; this is intended for debugging. -ASTConsumer *CreateDeclContextPrinter(); +std::unique_ptr<ASTConsumer> CreateDeclContextPrinter(); } // end clang namespace diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 42dc69ab4a15..634224d08bbf 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -272,12 +272,12 @@ private: /// \brief When non-NULL, this is the buffer used to store the contents of /// the main file when it has been padded for use with the precompiled /// preamble. - llvm::MemoryBuffer *SavedMainFileBuffer; + std::unique_ptr<llvm::MemoryBuffer> SavedMainFileBuffer; /// \brief When non-NULL, this is the buffer used to store the /// contents of the preamble when it has been padded to build the /// precompiled preamble. - llvm::MemoryBuffer *PreambleBuffer; + std::unique_ptr<llvm::MemoryBuffer> PreambleBuffer; /// \brief The number of warnings that occurred while parsing the preamble. /// @@ -305,8 +305,7 @@ private: /// \brief The language options used when we load an AST file. LangOptions ASTFileLangOpts; - static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> &Diags, - const char **ArgBegin, const char **ArgEnd, + static void ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTUnit &AST, bool CaptureDiagnostics); void TranslateStoredDiagnostics(FileManager &FileMgr, @@ -423,16 +422,28 @@ private: explicit ASTUnit(bool MainFileIsAST); void CleanTemporaryFiles(); - bool Parse(llvm::MemoryBuffer *OverrideMainBuffer); - - std::pair<llvm::MemoryBuffer *, std::pair<unsigned, bool> > - ComputePreamble(CompilerInvocation &Invocation, - unsigned MaxLines, bool &CreatedBuffer); - - llvm::MemoryBuffer *getMainBufferWithPrecompiledPreamble( - const CompilerInvocation &PreambleInvocationIn, - bool AllowRebuild = true, - unsigned MaxLines = 0); + bool Parse(std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer); + + struct ComputedPreamble { + llvm::MemoryBuffer *Buffer; + std::unique_ptr<llvm::MemoryBuffer> Owner; + unsigned Size; + bool PreambleEndsAtStartOfLine; + ComputedPreamble(llvm::MemoryBuffer *Buffer, + std::unique_ptr<llvm::MemoryBuffer> Owner, unsigned Size, + bool PreambleEndsAtStartOfLine) + : Buffer(Buffer), Owner(std::move(Owner)), Size(Size), + PreambleEndsAtStartOfLine(PreambleEndsAtStartOfLine) {} + ComputedPreamble(ComputedPreamble &&C) + : Buffer(C.Buffer), Owner(std::move(C.Owner)), Size(C.Size), + PreambleEndsAtStartOfLine(C.PreambleEndsAtStartOfLine) {} + }; + ComputedPreamble ComputePreamble(CompilerInvocation &Invocation, + unsigned MaxLines); + + std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble( + const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true, + unsigned MaxLines = 0); void RealizeTopLevelDeclsFromPreamble(); /// \brief Transfers ownership of the objects (like SourceManager) from @@ -684,8 +695,8 @@ public: /// module file. bool isModuleFile(); - llvm::MemoryBuffer *getBufferForFile(StringRef Filename, - std::string *ErrorStr = nullptr); + std::unique_ptr<llvm::MemoryBuffer> + getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr); /// \brief Determine what kind of translation unit this AST represents. TranslationUnitKind getTranslationUnitKind() const { return TUKind; } @@ -708,14 +719,12 @@ public: /// lifetime is expected to extend past that of the returned ASTUnit. /// /// \returns - The initialized ASTUnit or null if the AST failed to load. - static ASTUnit *LoadFromASTFile(const std::string &Filename, - IntrusiveRefCntPtr<DiagnosticsEngine> Diags, - const FileSystemOptions &FileSystemOpts, - bool OnlyLocalDecls = false, - ArrayRef<RemappedFile> RemappedFiles = None, - bool CaptureDiagnostics = false, - bool AllowPCHWithCompilerErrors = false, - bool UserFilesAreVolatile = false); + static std::unique_ptr<ASTUnit> LoadFromASTFile( + const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, + const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false, + ArrayRef<RemappedFile> RemappedFiles = None, + bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, + bool UserFilesAreVolatile = false); private: /// \brief Helper function for \c LoadFromCompilerInvocation() and diff --git a/include/clang/Frontend/ChainedDiagnosticConsumer.h b/include/clang/Frontend/ChainedDiagnosticConsumer.h index 11762a97cfc4..eb33273c2fb3 100644 --- a/include/clang/Frontend/ChainedDiagnosticConsumer.h +++ b/include/clang/Frontend/ChainedDiagnosticConsumer.h @@ -22,15 +22,20 @@ class LangOptions; /// diagnostics should be included in counts. class ChainedDiagnosticConsumer : public DiagnosticConsumer { virtual void anchor(); - std::unique_ptr<DiagnosticConsumer> Primary; + std::unique_ptr<DiagnosticConsumer> OwningPrimary; + DiagnosticConsumer *Primary; std::unique_ptr<DiagnosticConsumer> Secondary; public: - ChainedDiagnosticConsumer(DiagnosticConsumer *_Primary, - DiagnosticConsumer *_Secondary) { - Primary.reset(_Primary); - Secondary.reset(_Secondary); - } + ChainedDiagnosticConsumer(std::unique_ptr<DiagnosticConsumer> Primary, + std::unique_ptr<DiagnosticConsumer> Secondary) + : OwningPrimary(std::move(Primary)), Primary(OwningPrimary.get()), + Secondary(std::move(Secondary)) {} + + /// \brief Construct without taking ownership of \c Primary. + ChainedDiagnosticConsumer(DiagnosticConsumer *Primary, + std::unique_ptr<DiagnosticConsumer> Secondary) + : Primary(Primary), Secondary(std::move(Secondary)) {} void BeginSourceFile(const LangOptions &LO, const Preprocessor *PP) override { diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index 1d92efeda258..b44672d0f5f0 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -67,14 +67,18 @@ CODEGENOPT(InstrumentForProfiling , 1, 0) ///< Set when -pg is enabled. CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions to ///< be generated. CODEGENOPT(MergeAllConstants , 1, 1) ///< Merge identical constants. +CODEGENOPT(MergeFunctions , 1, 0) ///< Set when -fmerge-functions is enabled. CODEGENOPT(NoCommon , 1, 0) ///< Set when -fno-common or C++ is enabled. CODEGENOPT(NoDwarfDirectoryAsm , 1, 0) ///< Set when -fno-dwarf-directory-asm is ///< enabled. CODEGENOPT(NoExecStack , 1, 0) ///< Set when -Wa,--noexecstack is enabled. +CODEGENOPT(FatalWarnings , 1, 0) ///< Set when -Wa,--fatal-warnings is + ///< enabled. CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack is enabled. CODEGENOPT(NoGlobalMerge , 1, 0) ///< Set when -mno-global-merge is enabled. CODEGENOPT(NoImplicitFloat , 1, 0) ///< Set when -mno-implicit-float is enabled. CODEGENOPT(NoInfsFPMath , 1, 0) ///< Assume FP arguments, results not +-Inf. +CODEGENOPT(NoSignedZeros , 1, 0) ///< Allow ignoring the signedness of FP zero CODEGENOPT(NoInline , 1, 0) ///< Set when -fno-inline is enabled. ///< Disables use of the inline keyword. CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. @@ -83,11 +87,15 @@ CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss. ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy) CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is ///< enabled. -VALUE_CODEGENOPT(OptimizationLevel, 3, 0) ///< The -O[0-4] option specified. +VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. CODEGENOPT(ProfileInstrGenerate , 1, 0) ///< Instrument code to generate ///< execution counts to use with PGO. +CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to + ///< enable code coverage analysis. +CODEGENOPT(DumpCoverageMapping , 1, 0) ///< Dump the generated coverage mapping + ///< regions. /// If -fpcc-struct-return or -freg-struct-return is specified. ENUM_CODEGENOPT(StructReturnConvention, StructReturnConventionKind, 2, SRCK_Default) @@ -100,6 +108,7 @@ CODEGENOPT(SanitizeAddressZeroBaseShadow , 1, 0) ///< Map shadow memory at zero ///< offset in AddressSanitizer. CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in ///< MemorySanitizer +CODEGENOPT(SanitizeCoverage, 3, 0) ///< Enable sanitizer coverage instrumentation. CODEGENOPT(SanitizeUndefinedTrapOnError, 1, 0) ///< Set on /// -fsanitize-undefined-trap-on-error CODEGENOPT(SimplifyLibCalls , 1, 1) ///< Set when -fbuiltin is enabled. @@ -151,9 +160,6 @@ ENUM_CODEGENOPT(Inlining, InliningMethod, 2, NoInlining) /// The default TLS model to use. ENUM_CODEGENOPT(DefaultTLSModel, TLSModel, 2, GeneralDynamicTLSModel) -CODEGENOPT(SanitizeRecover, 1, 1) ///< Attempt to recover from sanitizer checks - ///< by continuing execution when possible - #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 3d532cea3431..819606429efb 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -14,9 +14,11 @@ #ifndef LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H #define LLVM_CLANG_FRONTEND_CODEGENOPTIONS_H +#include "clang/Basic/Sanitizers.h" +#include "llvm/Support/Regex.h" +#include <memory> #include <string> #include <vector> -#include "llvm/Support/Regex.h" namespace clang { @@ -134,8 +136,8 @@ public: /// The name of the relocation model to use. std::string RelocationModel; - /// Path to blacklist file for sanitizers. - std::string SanitizerBlacklistFile; + /// The thread model to use + std::string ThreadModel; /// If not an empty string, trap intrinsics are lowered to calls to this /// function instead of to trap instructions. @@ -175,6 +177,13 @@ public: /// flag. std::shared_ptr<llvm::Regex> OptimizationRemarkAnalysisPattern; + /// Set of files definining the rules for the symbol rewriting. + std::vector<std::string> RewriteMapFiles; + + /// Set of sanitizer checks that are non-fatal (i.e. execution should be + /// continued when possible). + SanitizerSet SanitizeRecover; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) @@ -183,15 +192,7 @@ public: void set##Name(Type Value) { Name = static_cast<unsigned>(Value); } #include "clang/Frontend/CodeGenOptions.def" - CodeGenOptions() { -#define CODEGENOPT(Name, Bits, Default) Name = Default; -#define ENUM_CODEGENOPT(Name, Type, Bits, Default) \ - set##Name(Default); -#include "clang/Frontend/CodeGenOptions.def" - - RelocationModel = "pic"; - memcpy(CoverageVersion, "402*", 4); - } + CodeGenOptions(); }; } // end namespace clang diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 44e91026acb5..0f49b346107b 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -10,6 +10,7 @@ #ifndef LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ +#include "clang/AST/ASTConsumer.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" @@ -116,7 +117,10 @@ class CompilerInstance : public ModuleLoader { /// \brief The set of top-level modules that has already been loaded, /// along with the module map llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules; - + + /// \brief Module names that have an override for the target file. + llvm::StringMap<std::string> ModuleFileOverrides; + /// \brief The location of the module-import keyword for the last module /// import. SourceLocation LastModuleImportLoc; @@ -246,6 +250,9 @@ public: return Invocation->getDiagnosticOpts(); } + FileSystemOptions &getFileSystemOpts() { + return Invocation->getFileSystemOpts(); + } const FileSystemOptions &getFileSystemOpts() const { return Invocation->getFileSystemOpts(); } @@ -443,11 +450,11 @@ public: /// takeASTConsumer - Remove the current AST consumer and give ownership to /// the caller. - ASTConsumer *takeASTConsumer() { return Consumer.release(); } + std::unique_ptr<ASTConsumer> takeASTConsumer() { return std::move(Consumer); } /// setASTConsumer - Replace the current AST consumer; the compiler instance /// takes ownership of \p Value. - void setASTConsumer(ASTConsumer *Value); + void setASTConsumer(std::unique_ptr<ASTConsumer> Value); /// } /// @name Semantic analysis @@ -459,8 +466,8 @@ public: return *TheSema; } - Sema *takeSema() { return TheSema.release(); } - void resetAndLeakSema() { BuryPointer(TheSema.release()); } + std::unique_ptr<Sema> takeSema(); + void resetAndLeakSema(); /// } /// @name Module Management @@ -485,12 +492,6 @@ public: return *CompletionConsumer; } - /// takeCodeCompletionConsumer - Remove the current code completion consumer - /// and give ownership to the caller. - CodeCompleteConsumer *takeCodeCompletionConsumer() { - return CompletionConsumer.release(); - } - /// setCodeCompletionConsumer - Replace the current code completion consumer; /// the compiler instance takes ownership of \p Value. void setCodeCompletionConsumer(CodeCompleteConsumer *Value); @@ -646,7 +647,7 @@ public: /// renamed to \p OutputPath in the end. /// /// \param OutputPath - If given, the path to the output file. - /// \param Error [out] - On failure, the error message. + /// \param Error [out] - On failure, the error. /// \param BaseInput - If \p OutputPath is empty, the input path name to use /// for deriving the output path. /// \param Extension - The extension to use for derived output names. @@ -663,13 +664,10 @@ public: /// \param TempPathName [out] - If given, the temporary file path name /// will be stored here on success. static llvm::raw_fd_ostream * - createOutputFile(StringRef OutputPath, std::string &Error, - bool Binary, bool RemoveFileOnSignal, - StringRef BaseInput, - StringRef Extension, - bool UseTemporary, - bool CreateMissingDirectories, - std::string *ResultPathName, + createOutputFile(StringRef OutputPath, std::error_code &Error, bool Binary, + bool RemoveFileOnSignal, StringRef BaseInput, + StringRef Extension, bool UseTemporary, + bool CreateMissingDirectories, std::string *ResultPathName, std::string *TempPathName); llvm::raw_null_ostream *createNullOutputFile(); @@ -699,6 +697,8 @@ public: // Create module manager. void createModuleManager(); + bool loadModuleFile(StringRef FileName); + ModuleLoadResult loadModule(SourceLocation ImportLoc, ModuleIdPath Path, Module::NameVisibilityKind Visibility, bool IsInclusionDirective) override; diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index ce1dc9046557..5becadf40eda 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ -#define LLVM_CLANG_FRONTEND_DIAGNOSTIC_RENDERER_H_ +#ifndef LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H +#define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 9ac9d2828f6a..c407ff80ac56 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -18,8 +18,10 @@ #ifndef LLVM_CLANG_FRONTEND_FRONTENDACTION_H #define LLVM_CLANG_FRONTEND_FRONTENDACTION_H +#include "clang/AST/ASTConsumer.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" +#include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/FrontendOptions.h" #include "llvm/ADT/StringRef.h" #include <memory> @@ -27,9 +29,7 @@ #include <vector> namespace clang { -class ASTConsumer; class ASTMergeAction; -class ASTUnit; class CompilerInstance; /// Abstract base class for actions which can be performed by the frontend. @@ -41,8 +41,8 @@ class FrontendAction { friend class WrapperFrontendAction; private: - ASTConsumer* CreateWrappedASTConsumer(CompilerInstance &CI, - StringRef InFile); + std::unique_ptr<ASTConsumer> CreateWrappedASTConsumer(CompilerInstance &CI, + StringRef InFile); protected: /// @name Implementation Action Interface @@ -61,8 +61,8 @@ protected: /// getCurrentFile(). /// /// \return The new AST consumer, or null on failure. - virtual ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) = 0; + virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) = 0; /// \brief Callback before starting processing a single input, giving the /// opportunity to modify the CompilerInvocation or do some other action @@ -146,15 +146,24 @@ public: return *CurrentASTUnit; } - ASTUnit *takeCurrentASTUnit() { return CurrentASTUnit.release(); } + std::unique_ptr<ASTUnit> takeCurrentASTUnit() { + return std::move(CurrentASTUnit); + } void setCurrentInput(const FrontendInputFile &CurrentInput, - ASTUnit *AST = nullptr); + std::unique_ptr<ASTUnit> AST = nullptr); /// @} /// @name Supported Modes /// @{ + /// \brief Is this action invoked on a model file? + /// + /// Model files are incomplete translation units that relies on type + /// information from another translation unit. Check ParseModelFileAction for + /// details. + virtual bool isModelParsingAction() const { return false; } + /// \brief Does this action only use the preprocessor? /// /// If so no AST context will be created and this action will be invalid @@ -222,16 +231,16 @@ protected: void ExecuteAction() override; public: + ASTFrontendAction() {} bool usesPreprocessorOnly() const override { return false; } }; class PluginASTAction : public ASTFrontendAction { virtual void anchor(); -protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override = 0; - public: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override = 0; + /// \brief Parse the given plugin command line arguments. /// /// \param CI - The compiler instance, for use in reporting diagnostics. @@ -247,8 +256,8 @@ class PreprocessorFrontendAction : public FrontendAction { protected: /// \brief Provide a default implementation which returns aborts; /// this method should never be called by FrontendAction clients. - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; public: bool usesPreprocessorOnly() const override { return true; } @@ -264,8 +273,8 @@ class WrapperFrontendAction : public FrontendAction { std::unique_ptr<FrontendAction> WrappedAction; protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; bool BeginInvocation(CompilerInstance &CI) override; bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override; void ExecuteAction() override; diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index 84cc82cfbe2f..850f87c073c5 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -26,8 +26,8 @@ class FileEntry; class InitOnlyAction : public FrontendAction { void ExecuteAction() override; - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; public: // Don't claim to only use the preprocessor, we want to follow the AST path, @@ -41,38 +41,38 @@ public: class ASTPrintAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class ASTDumpAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class ASTDeclListAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class ASTViewAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class DeclContextPrintAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class GeneratePCHAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; TranslationUnitKind getTranslationUnitKind() override { return TU_Prefix; @@ -98,8 +98,8 @@ class GenerateModuleAction : public ASTFrontendAction { bool IsSystem; protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; TranslationUnitKind getTranslationUnitKind() override { return TU_Module; @@ -128,8 +128,8 @@ public: class SyntaxOnlyAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; public: bool hasCodeCompletionSupport() const override { return true; } @@ -139,8 +139,8 @@ public: /// basic debugging and discovery. class DumpModuleInfoAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; void ExecuteAction() override; public: @@ -152,8 +152,8 @@ public: class VerifyPCHAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; void ExecuteAction() override; @@ -177,8 +177,8 @@ class ASTMergeAction : public FrontendAction { std::vector<std::string> ASTFiles; protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override; @@ -200,7 +200,8 @@ public: class PrintPreambleAction : public FrontendAction { protected: void ExecuteAction() override; - ASTConsumer *CreateASTConsumer(CompilerInstance &, StringRef) override { + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &, + StringRef) override { return nullptr; } diff --git a/include/clang/Frontend/FrontendDiagnostic.h b/include/clang/Frontend/FrontendDiagnostic.h index 312dbf14115b..0f37b7ece7e0 100644 --- a/include/clang/Frontend/FrontendDiagnostic.h +++ b/include/clang/Frontend/FrontendDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTENDDIAGNOSTIC_H -#define LLVM_CLANG_FRONTENDDIAGNOSTIC_H +#ifndef LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H +#define LLVM_CLANG_FRONTEND_FRONTENDDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index e87da8de1cfa..71c5aa47af99 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -142,6 +142,8 @@ public: ///< global module index if available. unsigned GenerateGlobalModuleIndex : 1; ///< Whether we can generate the ///< global module index if needed. + unsigned ASTDumpDecls : 1; ///< Whether we include declaration + ///< dumps in AST dumps. unsigned ASTDumpLookups : 1; ///< Whether we include lookup table ///< dumps in AST dumps. @@ -182,12 +184,15 @@ public: ObjCMT_NsAtomicIOSOnlyProperty = 0x400, /// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods. ObjCMT_DesignatedInitializer = 0x800, + /// \brief Enable converting setter/getter expressions to property-dot syntx. + ObjCMT_PropertyDotSyntax = 0x1000, ObjCMT_MigrateDecls = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty | ObjCMT_Annotation | ObjCMT_Instancetype | ObjCMT_NsMacros | ObjCMT_ProtocolConformance | ObjCMT_NsAtomicIOSOnlyProperty | ObjCMT_DesignatedInitializer), - ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | ObjCMT_MigrateDecls) + ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | + ObjCMT_MigrateDecls | ObjCMT_PropertyDotSyntax) }; unsigned ObjCMTAction; std::string ObjCMTWhiteListPath; @@ -228,6 +233,13 @@ public: /// The list of plugins to load. std::vector<std::string> Plugins; + /// \brief The list of module map files to load before processing the input. + std::vector<std::string> ModuleMapFiles; + + /// \brief The list of additional prebuilt module files to load before + /// processing the input. + std::vector<std::string> ModuleFiles; + /// \brief The list of AST files to merge. std::vector<std::string> ASTMergeFiles; @@ -246,7 +258,7 @@ public: FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), SkipFunctionBodies(false), UseGlobalModuleIndex(true), - GenerateGlobalModuleIndex(true), ASTDumpLookups(false), + GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false), ARCMTAction(ARCMT_None), ObjCMTAction(ObjCMT_None), ProgramAction(frontend::ParseSyntaxOnly) {} diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h index 49be495daa37..ecab630c1228 100644 --- a/include/clang/Frontend/FrontendPluginRegistry.h +++ b/include/clang/Frontend/FrontendPluginRegistry.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H -#define LLVM_CLANG_FRONTEND_PLUGINFRONTENDACTION_H +#ifndef LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H +#define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H #include "clang/Frontend/FrontendAction.h" #include "llvm/Support/Registry.h" diff --git a/include/clang/Frontend/LangStandard.h b/include/clang/Frontend/LangStandard.h index 9680e1f2e04c..8021d08942e5 100644 --- a/include/clang/Frontend/LangStandard.h +++ b/include/clang/Frontend/LangStandard.h @@ -24,7 +24,7 @@ enum LangFeatures { C11 = (1 << 3), CPlusPlus = (1 << 4), CPlusPlus11 = (1 << 5), - CPlusPlus1y = (1 << 6), + CPlusPlus14 = (1 << 6), CPlusPlus1z = (1 << 7), Digraphs = (1 << 8), GNUMode = (1 << 9), @@ -73,8 +73,8 @@ public: /// isCPlusPlus11 - Language is a C++11 variant (or later). bool isCPlusPlus11() const { return Flags & frontend::CPlusPlus11; } - /// isCPlusPlus1y - Language is a C++14 variant (or later). - bool isCPlusPlus1y() const { return Flags & frontend::CPlusPlus1y; } + /// isCPlusPlus14 - Language is a C++14 variant (or later). + bool isCPlusPlus14() const { return Flags & frontend::CPlusPlus14; } /// isCPlusPlus1z - Language is a C++17 variant (or later). bool isCPlusPlus1z() const { return Flags & frontend::CPlusPlus1z; } diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index 90a27b5b9982..cac9c3c4155f 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -109,26 +109,26 @@ LANGSTANDARD(gnucxx11, "gnu++11", LANGSTANDARD(cxx1y, "c++1y", "ISO C++ 2014 with amendments", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) LANGSTANDARD(cxx14, "c++14", "ISO C++ 2014 with amendments", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs) + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs) LANGSTANDARD(gnucxx1y, "gnu++1y", "ISO C++ 2014 with amendments and GNU extensions", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | GNUMode) LANGSTANDARD(gnucxx14, "gnu++14", "ISO C++ 2014 with amendments and GNU extensions", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | Digraphs | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | GNUMode) LANGSTANDARD(cxx1z, "c++1z", "Working draft for ISO C++ 2017", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | CPlusPlus1z | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z | Digraphs) LANGSTANDARD(gnucxx1z, "gnu++1z", "Working draft for ISO C++ 2017 with GNU extensions", - LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus1y | CPlusPlus1z | + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | CPlusPlus1z | Digraphs | GNUMode) // OpenCL @@ -141,6 +141,9 @@ LANGSTANDARD(opencl11, "CL1.1", LANGSTANDARD(opencl12, "CL1.2", "OpenCL 1.2", LineComment | C99 | Digraphs | HexFloat) +LANGSTANDARD(opencl20, "CL2.0", + "OpenCL 2.0", + LineComment | C99 | Digraphs | HexFloat) // CUDA LANGSTANDARD(cuda, "cuda", diff --git a/include/clang/Frontend/LogDiagnosticPrinter.h b/include/clang/Frontend/LogDiagnosticPrinter.h index 013031987045..98adf655fcf1 100644 --- a/include/clang/Frontend/LogDiagnosticPrinter.h +++ b/include/clang/Frontend/LogDiagnosticPrinter.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ -#define LLVM_CLANG_FRONTEND_LOG_DIAGNOSTIC_PRINTER_H_ +#ifndef LLVM_CLANG_FRONTEND_LOGDIAGNOSTICPRINTER_H +#define LLVM_CLANG_FRONTEND_LOGDIAGNOSTICPRINTER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" @@ -35,6 +35,9 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { /// The ID of the diagnostic. unsigned DiagnosticID; + + /// The Option Flag for the diagnostic + std::string WarningOption; /// The level of the diagnostic. DiagnosticsEngine::Level DiagnosticLevel; @@ -43,13 +46,16 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { void EmitDiagEntry(llvm::raw_ostream &OS, const LogDiagnosticPrinter::DiagEntry &DE); + // Conditional ownership (when StreamOwner is non-null, it's keeping OS + // alive). We might want to replace this with a wrapper for conditional + // ownership eventually - it seems to pop up often enough. raw_ostream &OS; + std::unique_ptr<raw_ostream> StreamOwner; const LangOptions *LangOpts; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; SourceLocation LastWarningLoc; FullSourceLoc LastLoc; - unsigned OwnsOutputStream : 1; SmallVector<DiagEntry, 8> Entries; @@ -58,8 +64,7 @@ class LogDiagnosticPrinter : public DiagnosticConsumer { public: LogDiagnosticPrinter(raw_ostream &OS, DiagnosticOptions *Diags, - bool OwnsOutputStream = false); - virtual ~LogDiagnosticPrinter(); + std::unique_ptr<raw_ostream> StreamOwner); void setDwarfDebugFlags(StringRef Value) { DwarfDebugFlags = Value; diff --git a/include/clang/Frontend/MigratorOptions.h b/include/clang/Frontend/MigratorOptions.h index f9554e4a61fd..8eb71b13f885 100644 --- a/include/clang/Frontend/MigratorOptions.h +++ b/include/clang/Frontend/MigratorOptions.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_MIGRATOROPTIONS -#define LLVM_CLANG_FRONTEND_MIGRATOROPTIONS +#ifndef LLVM_CLANG_FRONTEND_MIGRATOROPTIONS_H +#define LLVM_CLANG_FRONTEND_MIGRATOROPTIONS_H namespace clang { diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h index 4d31104cce18..c9122dacb8f1 100644 --- a/include/clang/Frontend/MultiplexConsumer.h +++ b/include/clang/Frontend/MultiplexConsumer.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_FRONTEND_MULTIPLEXCONSUMER_H -#define CLANG_FRONTEND_MULTIPLEXCONSUMER_H +#ifndef LLVM_CLANG_FRONTEND_MULTIPLEXCONSUMER_H +#define LLVM_CLANG_FRONTEND_MULTIPLEXCONSUMER_H #include "clang/Basic/LLVM.h" #include "clang/Sema/SemaConsumer.h" @@ -29,7 +29,7 @@ class MultiplexASTDeserializationListener; class MultiplexConsumer : public SemaConsumer { public: // Takes ownership of the pointers in C. - MultiplexConsumer(ArrayRef<ASTConsumer*> C); + MultiplexConsumer(std::vector<std::unique_ptr<ASTConsumer>> C); ~MultiplexConsumer(); // ASTConsumer @@ -59,7 +59,7 @@ public: void ForgetSema() override; private: - std::vector<ASTConsumer*> Consumers; // Owns these. + std::vector<std::unique_ptr<ASTConsumer>> Consumers; // Owns these. std::unique_ptr<MultiplexASTMutationListener> MutationListener; std::unique_ptr<MultiplexASTDeserializationListener> DeserializationListener; }; diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h index 4dda1fa4b655..4c57e9d404f0 100644 --- a/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTIC_PRINTER_H_ -#define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTIC_PRINTER_H_ +#ifndef LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICPRINTER_H +#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICPRINTER_H #include "clang/Basic/LLVM.h" +#include "clang/Frontend/SerializedDiagnostics.h" #include "llvm/Bitcode/BitstreamWriter.h" namespace llvm { @@ -23,41 +24,6 @@ class DiagnosticsEngine; class DiagnosticOptions; namespace serialized_diags { - -enum BlockIDs { - /// \brief A top-level block which represents any meta data associated - /// with the diagostics, including versioning of the format. - BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID, - - /// \brief The this block acts as a container for all the information - /// for a specific diagnostic. - BLOCK_DIAG -}; - -enum RecordIDs { - RECORD_VERSION = 1, - RECORD_DIAG, - RECORD_SOURCE_RANGE, - RECORD_DIAG_FLAG, - RECORD_CATEGORY, - RECORD_FILENAME, - RECORD_FIXIT, - RECORD_FIRST = RECORD_VERSION, - RECORD_LAST = RECORD_FIXIT -}; - -/// A stable version of DiagnosticIDs::Level. -/// -/// Do not change the order of values in this enum, and please increment the -/// serialized diagnostics version number when you add to it. -enum Level { - Ignored = 0, - Note, - Warning, - Error, - Fatal, - Remark -}; /// \brief Returns a DiagnosticConsumer that serializes diagnostics to /// a bitcode file. @@ -67,8 +33,9 @@ enum Level { /// This allows wrapper tools for Clang to get diagnostics from Clang /// (via libclang) without needing to parse Clang's command line output. /// -DiagnosticConsumer *create(raw_ostream *OS, - DiagnosticOptions *diags); +std::unique_ptr<DiagnosticConsumer> create(StringRef OutputFile, + DiagnosticOptions *Diags, + bool MergeChildRecords = false); } // end serialized_diags namespace } // end clang namespace diff --git a/include/clang/Frontend/SerializedDiagnosticReader.h b/include/clang/Frontend/SerializedDiagnosticReader.h new file mode 100644 index 000000000000..92e99d305da5 --- /dev/null +++ b/include/clang/Frontend/SerializedDiagnosticReader.h @@ -0,0 +1,131 @@ +//===--- SerializedDiagnosticReader.h - Reads diagnostics -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_ +#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_ + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/ErrorOr.h" + +namespace clang { +namespace serialized_diags { + +enum class SDError { + CouldNotLoad = 1, + InvalidSignature, + InvalidDiagnostics, + MalformedTopLevelBlock, + MalformedSubBlock, + MalformedBlockInfoBlock, + MalformedMetadataBlock, + MalformedDiagnosticBlock, + MalformedDiagnosticRecord, + MissingVersion, + VersionMismatch, + UnsupportedConstruct, + /// A generic error for subclass handlers that don't want or need to define + /// their own error_category. + HandlerFailed +}; + +const std::error_category &SDErrorCategory(); + +inline std::error_code make_error_code(SDError E) { + return std::error_code(static_cast<int>(E), SDErrorCategory()); +} + +/// \brief A location that is represented in the serialized diagnostics. +struct Location { + unsigned FileID; + unsigned Line; + unsigned Col; + unsigned Offset; + Location(unsigned FileID, unsigned Line, unsigned Col, unsigned Offset) + : FileID(FileID), Line(Line), Col(Col), Offset(Offset) {} +}; + +/// \brief A base class that handles reading serialized diagnostics from a file. +/// +/// Subclasses should override the visit* methods with their logic for handling +/// the various constructs that are found in serialized diagnostics. +class SerializedDiagnosticReader { +public: + SerializedDiagnosticReader() {} + virtual ~SerializedDiagnosticReader() {} + + /// \brief Read the diagnostics in \c File + std::error_code readDiagnostics(StringRef File); + +private: + enum class Cursor; + + /// \brief Read to the next record or block to process. + llvm::ErrorOr<Cursor> skipUntilRecordOrBlock(llvm::BitstreamCursor &Stream, + unsigned &BlockOrRecordId); + + /// \brief Read a metadata block from \c Stream. + std::error_code readMetaBlock(llvm::BitstreamCursor &Stream); + + /// \brief Read a diagnostic block from \c Stream. + std::error_code readDiagnosticBlock(llvm::BitstreamCursor &Stream); + +protected: + /// \brief Visit the start of a diagnostic block. + virtual std::error_code visitStartOfDiagnostic() { + return std::error_code(); + }; + /// \brief Visit the end of a diagnostic block. + virtual std::error_code visitEndOfDiagnostic() { return std::error_code(); }; + /// \brief Visit a category. This associates the category \c ID to a \c Name. + virtual std::error_code visitCategoryRecord(unsigned ID, StringRef Name) { + return std::error_code(); + }; + /// \brief Visit a flag. This associates the flag's \c ID to a \c Name. + virtual std::error_code visitDiagFlagRecord(unsigned ID, StringRef Name) { + return std::error_code(); + }; + /// \brief Visit a diagnostic. + virtual std::error_code + visitDiagnosticRecord(unsigned Severity, const Location &Location, + unsigned Category, unsigned Flag, StringRef Message) { + return std::error_code(); + }; + /// \brief Visit a filename. This associates the file's \c ID to a \c Name. + virtual std::error_code visitFilenameRecord(unsigned ID, unsigned Size, + unsigned Timestamp, + StringRef Name) { + return std::error_code(); + }; + /// \brief Visit a fixit hint. + virtual std::error_code + visitFixitRecord(const Location &Start, const Location &End, StringRef Text) { + return std::error_code(); + }; + /// \brief Visit a source range. + virtual std::error_code visitSourceRangeRecord(const Location &Start, + const Location &End) { + return std::error_code(); + }; + /// \brief Visit the version of the set of diagnostics. + virtual std::error_code visitVersionRecord(unsigned Version) { + return std::error_code(); + }; +}; + +} // end serialized_diags namespace +} // end clang namespace + +namespace std { +template <> +struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {}; +} + +#endif diff --git a/include/clang/Frontend/SerializedDiagnostics.h b/include/clang/Frontend/SerializedDiagnostics.h new file mode 100644 index 000000000000..2032cd3988db --- /dev/null +++ b/include/clang/Frontend/SerializedDiagnostics.h @@ -0,0 +1,59 @@ +//===--- SerializedDiagnostics.h - Common data for serialized diagnostics -===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_ +#define LLVM_CLANG_FRONTEND_SERIALIZE_DIAGNOSTICS_H_ + +#include "llvm/Bitcode/BitCodes.h" + +namespace clang { +namespace serialized_diags { + +enum BlockIDs { + /// \brief A top-level block which represents any meta data associated + /// with the diagostics, including versioning of the format. + BLOCK_META = llvm::bitc::FIRST_APPLICATION_BLOCKID, + + /// \brief The this block acts as a container for all the information + /// for a specific diagnostic. + BLOCK_DIAG +}; + +enum RecordIDs { + RECORD_VERSION = 1, + RECORD_DIAG, + RECORD_SOURCE_RANGE, + RECORD_DIAG_FLAG, + RECORD_CATEGORY, + RECORD_FILENAME, + RECORD_FIXIT, + RECORD_FIRST = RECORD_VERSION, + RECORD_LAST = RECORD_FIXIT +}; + +/// \brief A stable version of DiagnosticIDs::Level. +/// +/// Do not change the order of values in this enum, and please increment the +/// serialized diagnostics version number when you add to it. +enum Level { + Ignored = 0, + Note, + Warning, + Error, + Fatal, + Remark +}; + +/// \brief The serialized diagnostics version number. +enum { VersionNumber = 2 }; + +} // end serialized_diags namespace +} // end clang namespace + +#endif diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index acebb90b7076..42c78af1d2b0 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_H_ -#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_H_ +#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H +#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTIC_H #include "clang/Frontend/DiagnosticRenderer.h" diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h index fe5aa3e91d7f..3bcf824455e2 100644 --- a/include/clang/Frontend/TextDiagnosticBuffer.h +++ b/include/clang/Frontend/TextDiagnosticBuffer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_ -#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_BUFFER_H_ +#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H +#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H #include "clang/Basic/Diagnostic.h" #include <vector> diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 9f6d5ff9dd17..f8a71fe5e0f6 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ -#define LLVM_CLANG_FRONTEND_TEXT_DIAGNOSTIC_PRINTER_H_ +#ifndef LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H +#define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICPRINTER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 4c0a7b7a9c66..4cd93b994fe4 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -125,7 +125,7 @@ class ModuleDependencyCollector { public: StringRef getDest() { return DestDir; } - bool insertSeen(StringRef Filename) { return Seen.insert(Filename); } + bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; } void setHasErrors() { HasErrors = true; } void addFileMapping(StringRef VPath, StringRef RPath) { VFSWriter.addFileMapping(VPath, RPath); @@ -206,6 +206,9 @@ inline uint64_t getLastArgUInt64Value(const llvm::opt::ArgList &Args, // global objects, but we don't want LeakDetectors to complain, so we bury them // in a globally visible array. void BuryPointer(const void *Ptr); +template <typename T> void BuryPointer(std::unique_ptr<T> Ptr) { + BuryPointer(Ptr.release()); +} } // end namespace clang diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h index 9273fac50910..80e140bc5023 100644 --- a/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H -#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICSCLIENT_H +#ifndef LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H +#define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H #include "clang/Basic/Diagnostic.h" #include "clang/Lex/Preprocessor.h" @@ -145,9 +145,12 @@ public: /// class Directive { public: - static Directive *create(bool RegexKind, SourceLocation DirectiveLoc, - SourceLocation DiagnosticLoc, bool MatchAnyLine, - StringRef Text, unsigned Min, unsigned Max); + static std::unique_ptr<Directive> create(bool RegexKind, + SourceLocation DirectiveLoc, + SourceLocation DiagnosticLoc, + bool MatchAnyLine, StringRef Text, + unsigned Min, unsigned Max); + public: /// Constant representing n or more matches. static const unsigned MaxCount = UINT_MAX; @@ -181,7 +184,7 @@ public: void operator=(const Directive &) LLVM_DELETED_FUNCTION; }; - typedef std::vector<Directive*> DirectiveList; + typedef std::vector<std::unique_ptr<Directive>> DirectiveList; /// ExpectedData - owns directive objects and deletes on destructor. /// @@ -192,13 +195,11 @@ public: DirectiveList Notes; void Reset() { - llvm::DeleteContainerPointers(Errors); - llvm::DeleteContainerPointers(Warnings); - llvm::DeleteContainerPointers(Remarks); - llvm::DeleteContainerPointers(Notes); + Errors.clear(); + Warnings.clear(); + Remarks.clear(); + Notes.clear(); } - - ~ExpectedData() { Reset(); } }; enum DirectiveStatus { @@ -211,7 +212,7 @@ public: private: DiagnosticsEngine &Diags; DiagnosticConsumer *PrimaryClient; - bool OwnsPrimaryClient; + std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner; std::unique_ptr<TextDiagnosticBuffer> Buffer; const Preprocessor *CurrentPreprocessor; const LangOptions *LangOpts; diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index d9a4de4d9981..2f9231dc9f22 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -11,8 +11,8 @@ // construction of macro definitions from some external source. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H -#define LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H +#ifndef LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H +#define LLVM_CLANG_LEX_EXTERNALPREPROCESSORSOURCE_H namespace clang { @@ -36,4 +36,4 @@ public: } -#endif // LLVM_CLANG_LEX_EXTERNAL_PREPROCESSOR_SOURCE_H +#endif diff --git a/include/clang/Lex/HeaderMap.h b/include/clang/Lex/HeaderMap.h index 8e78b5ac9884..993c8612b0f8 100644 --- a/include/clang/Lex/HeaderMap.h +++ b/include/clang/Lex/HeaderMap.h @@ -16,6 +16,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/Support/Compiler.h" +#include <memory> namespace llvm { class MemoryBuffer; @@ -34,15 +35,12 @@ class HeaderMap { HeaderMap(const HeaderMap &) LLVM_DELETED_FUNCTION; void operator=(const HeaderMap &) LLVM_DELETED_FUNCTION; - const llvm::MemoryBuffer *FileBuffer; + std::unique_ptr<const llvm::MemoryBuffer> FileBuffer; bool NeedsBSwap; - HeaderMap(const llvm::MemoryBuffer *File, bool BSwap) - : FileBuffer(File), NeedsBSwap(BSwap) { - } + HeaderMap(std::unique_ptr<const llvm::MemoryBuffer> File, bool BSwap) + : FileBuffer(std::move(File)), NeedsBSwap(BSwap) {} public: - ~HeaderMap(); - /// HeaderMap::Create - This attempts to load the specified file as a header /// map. If it doesn't look like a HeaderMap, it gives up and returns null. static const HeaderMap *Create(const FileEntry *FE, FileManager &FM); diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 034262982770..158f67d40b49 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -231,7 +231,11 @@ class HeaderSearch { /// \brief Describes whether a given directory has a module map in it. llvm::DenseMap<const DirectoryEntry *, bool> DirectoryHasModuleMap; - + + /// \brief Set of module map files we've already loaded, and a flag indicating + /// whether they were valid or not. + llvm::DenseMap<const FileEntry *, bool> LoadedModuleMaps; + /// \brief Uniqued set of framework names, which is used to track which /// headers were included as framework headers. llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames; @@ -248,7 +252,7 @@ class HeaderSearch { unsigned NumMultiIncludeFileOptzn; unsigned NumFrameworkLookups, NumSubFrameworkLookups; - bool EnabledModules; + const LangOptions &LangOpts; // HeaderSearch doesn't support default or copy construction. HeaderSearch(const HeaderSearch&) LLVM_DELETED_FUNCTION; @@ -384,14 +388,12 @@ public: /// \param SuggestedModule If non-null, and the file found is semantically /// part of a known module, this will be set to the module that should /// be imported instead of preprocessing/parsing the file found. - const FileEntry *LookupFile(StringRef Filename, SourceLocation IncludeLoc, - bool isAngled, const DirectoryLookup *FromDir, - const DirectoryLookup *&CurDir, - ArrayRef<const FileEntry *> Includers, - SmallVectorImpl<char> *SearchPath, - SmallVectorImpl<char> *RelativePath, - ModuleMap::KnownHeader *SuggestedModule, - bool SkipCache = false); + const FileEntry *LookupFile( + StringRef Filename, SourceLocation IncludeLoc, bool isAngled, + const DirectoryLookup *FromDir, const DirectoryLookup *&CurDir, + ArrayRef<std::pair<const FileEntry *, const DirectoryEntry *>> Includers, + SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, + ModuleMap::KnownHeader *SuggestedModule, bool SkipCache = false); /// \brief Look up a subframework for the specified \#include file. /// @@ -409,7 +411,7 @@ public: /// \brief Look up the specified framework name in our framework cache. /// \returns The DirectoryEntry it is in if we know, null otherwise. FrameworkCacheEntry &LookupFrameworkCache(StringRef FWName) { - return FrameworkMap.GetOrCreateValue(FWName).getValue(); + return FrameworkMap[FWName]; } /// \brief Mark the specified file as a target of of a \#include, @@ -477,7 +479,7 @@ public: const HeaderMap *CreateHeaderMap(const FileEntry *FE); /// Returns true if modules are enabled. - bool enabledModules() const { return EnabledModules; } + bool enabledModules() const { return LangOpts.Modules; } /// \brief Retrieve the name of the module file that should be used to /// load the given module. @@ -638,7 +640,8 @@ private: }; LoadModuleMapResult loadModuleMapFileImpl(const FileEntry *File, - bool IsSystem); + bool IsSystem, + const DirectoryEntry *Dir); /// \brief Try to load the module map file in the given directory. /// diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index 06024b2e90f2..775943de8169 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -101,6 +101,15 @@ public: /// \brief Interpret module maps. This option is implied by full modules. unsigned ModuleMaps : 1; + /// \brief Set the 'home directory' of a module map file to the current + /// working directory (or the home directory of the module map file that + /// contained the 'extern module' directive importing this module map file + /// if any) rather than the directory containing the module map file. + // + /// The home directory is where we look for files named in the module map + /// file. + unsigned ModuleMapFileHomeIsCwd : 1; + /// \brief The interval (in seconds) between pruning operations. /// /// This operation is expensive, because it requires Clang to walk through @@ -129,9 +138,6 @@ public: /// of computing the module hash. llvm::SetVector<std::string> ModulesIgnoreMacros; - /// \brief The set of user-provided module-map-files. - llvm::SetVector<std::string> ModuleMapFiles; - /// \brief The set of user-provided virtual filesystem overlay files. std::vector<std::string> VFSOverlayFiles; @@ -161,6 +167,7 @@ public: public: HeaderSearchOptions(StringRef _Sysroot = "/") : Sysroot(_Sysroot), DisableModuleHash(0), ModuleMaps(0), + ModuleMapFileHomeIsCwd(0), ModuleCachePruneInterval(7*24*60*60), ModuleCachePruneAfter(31*24*60*60), BuildSessionTimestamp(0), diff --git a/include/clang/Lex/LexDiagnostic.h b/include/clang/Lex/LexDiagnostic.h index 85424aa8a10f..5d724c0de879 100644 --- a/include/clang/Lex/LexDiagnostic.h +++ b/include/clang/Lex/LexDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICLEX_H -#define LLVM_CLANG_DIAGNOSTICLEX_H +#ifndef LLVM_CLANG_LEX_LEXDIAGNOSTIC_H +#define LLVM_CLANG_LEX_LEXDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index edcf883eced3..c1f968be5584 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LEXER_H -#define LLVM_CLANG_LEXER_H +#ifndef LLVM_CLANG_LEX_LEXER_H +#define LLVM_CLANG_LEX_LEXER_H #include "clang/Basic/LangOptions.h" #include "clang/Lex/PreprocessorLexer.h" @@ -405,9 +405,9 @@ public: /// \returns The offset into the file where the preamble ends and the rest /// of the file begins along with a boolean value indicating whether /// the preamble ends at the beginning of a new line. - static std::pair<unsigned, bool> - ComputePreamble(const llvm::MemoryBuffer *Buffer, const LangOptions &LangOpts, - unsigned MaxLines = 0); + static std::pair<unsigned, bool> ComputePreamble(StringRef Buffer, + const LangOptions &LangOpts, + unsigned MaxLines = 0); /// \brief Checks that the given token is the first token that occurs after /// the given location (this excludes comments and whitespace). Returns the diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index b7fcc5d34de6..f60a152a0aa9 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_LITERALSUPPORT_H -#define CLANG_LITERALSUPPORT_H +#ifndef LLVM_CLANG_LEX_LITERALSUPPORT_H +#define LLVM_CLANG_LEX_LITERALSUPPORT_H #include "clang/Basic/CharInfo.h" #include "clang/Basic/LLVM.h" diff --git a/include/clang/Lex/MacroArgs.h b/include/clang/Lex/MacroArgs.h index 4c0120c77f04..d858ec2b4292 100644 --- a/include/clang/Lex/MacroArgs.h +++ b/include/clang/Lex/MacroArgs.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_MACROARGS_H -#define LLVM_CLANG_MACROARGS_H +#ifndef LLVM_CLANG_LEX_MACROARGS_H +#define LLVM_CLANG_LEX_MACROARGS_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index e9a66e857dbc..ca5d49704877 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -12,10 +12,11 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_MACROINFO_H -#define LLVM_CLANG_MACROINFO_H +#ifndef LLVM_CLANG_LEX_MACROINFO_H +#define LLVM_CLANG_LEX_MACROINFO_H #include "clang/Lex/Token.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Allocator.h" #include <cassert> @@ -45,7 +46,7 @@ class MacroInfo { /// \see ArgumentList unsigned NumArguments; - + /// \brief This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; @@ -78,8 +79,7 @@ class MacroInfo { /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__" bool HasCommaPasting : 1; - -private: + //===--------------------------------------------------------------------===// // State that changes as the macro is used. @@ -107,28 +107,11 @@ private: /// \brief Whether this macro was used as header guard. bool UsedForHeaderGuard : 1; - ~MacroInfo() { - assert(!ArgumentList && "Didn't call destroy before dtor!"); - } - -public: + // Only the Preprocessor gets to create and destroy these. MacroInfo(SourceLocation DefLoc); - - /// \brief Free the argument list of the macro. - /// - /// This restores this MacroInfo to a state where it can be reused for other - /// devious purposes. - void FreeArgumentList() { - ArgumentList = nullptr; - NumArguments = 0; - } - - /// \brief Destroy this MacroInfo object. - void Destroy() { - FreeArgumentList(); - this->~MacroInfo(); - } + ~MacroInfo() {} +public: /// \brief Return the location that the macro was defined at. SourceLocation getDefinitionLoc() const { return Location; } @@ -350,9 +333,6 @@ protected: // Used by DefMacroDirective -----------------------------------------------// - /// \brief True if this macro was imported from a module. - bool IsImported : 1; - /// \brief Whether the definition of this macro is ambiguous, due to /// multiple definitions coming in from multiple modules. bool IsAmbiguous : 1; @@ -363,11 +343,35 @@ protected: /// module). bool IsPublic : 1; - MacroDirective(Kind K, SourceLocation Loc) - : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false), - IsImported(false), IsAmbiguous(false), - IsPublic(true) { - } + // Used by DefMacroDirective and UndefMacroDirective -----------------------// + + /// \brief True if this macro was imported from a module. + bool IsImported : 1; + + /// \brief For an imported directive, the number of modules whose macros are + /// overridden by this directive. Only used if IsImported. + unsigned NumOverrides : 26; + + unsigned *getModuleDataStart(); + const unsigned *getModuleDataStart() const { + return const_cast<MacroDirective*>(this)->getModuleDataStart(); + } + + MacroDirective(Kind K, SourceLocation Loc, + unsigned ImportedFromModuleID = 0, + ArrayRef<unsigned> Overrides = None) + : Previous(nullptr), Loc(Loc), MDKind(K), IsFromPCH(false), + IsAmbiguous(false), IsPublic(true), IsImported(ImportedFromModuleID), + NumOverrides(Overrides.size()) { + assert(NumOverrides == Overrides.size() && "too many overrides"); + assert((IsImported || !NumOverrides) && "overrides for non-module macro"); + + if (IsImported) { + unsigned *Extra = getModuleDataStart(); + *Extra++ = ImportedFromModuleID; + std::copy(Overrides.begin(), Overrides.end(), Extra); + } + } public: Kind getKind() const { return Kind(MDKind); } @@ -390,6 +394,27 @@ public: void setIsFromPCH() { IsFromPCH = true; } + /// \brief True if this macro was imported from a module. + /// Note that this is never the case for a VisibilityMacroDirective. + bool isImported() const { return IsImported; } + + /// \brief If this directive was imported from a module, get the submodule + /// whose directive this is. Note that this may be different from the module + /// that owns the MacroInfo for a DefMacroDirective due to #pragma pop_macro + /// and similar effects. + unsigned getOwningModuleID() const { + if (isImported()) + return *getModuleDataStart(); + return 0; + } + + /// \brief Get the module IDs of modules whose macros are overridden by this + /// directive. Only valid if this is an imported directive. + ArrayRef<unsigned> getOverriddenModules() const { + assert(IsImported && "can only get overridden modules for imported macro"); + return llvm::makeArrayRef(getModuleDataStart() + 1, NumOverrides); + } + class DefInfo { DefMacroDirective *DefDirective; SourceLocation UndefLoc; @@ -463,23 +488,22 @@ class DefMacroDirective : public MacroDirective { public: explicit DefMacroDirective(MacroInfo *MI) - : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) { + : MacroDirective(MD_Define, MI->getDefinitionLoc()), Info(MI) { assert(MI && "MacroInfo is null"); } - DefMacroDirective(MacroInfo *MI, SourceLocation Loc, bool isImported) - : MacroDirective(MD_Define, Loc), Info(MI) { + DefMacroDirective(MacroInfo *MI, SourceLocation Loc, + unsigned ImportedFromModuleID = 0, + ArrayRef<unsigned> Overrides = None) + : MacroDirective(MD_Define, Loc, ImportedFromModuleID, Overrides), + Info(MI) { assert(MI && "MacroInfo is null"); - IsImported = isImported; } /// \brief The data for the macro definition. const MacroInfo *getInfo() const { return Info; } MacroInfo *getInfo() { return Info; } - /// \brief True if this macro was imported from a module. - bool isImported() const { return IsImported; } - /// \brief Determine whether this macro definition is ambiguous with /// other macro definitions. bool isAmbiguous() const { return IsAmbiguous; } @@ -496,9 +520,11 @@ public: /// \brief A directive for an undefined macro. class UndefMacroDirective : public MacroDirective { public: - explicit UndefMacroDirective(SourceLocation UndefLoc) - : MacroDirective(MD_Undefine, UndefLoc) { - assert(UndefLoc.isValid() && "Invalid UndefLoc!"); + explicit UndefMacroDirective(SourceLocation UndefLoc, + unsigned ImportedFromModuleID = 0, + ArrayRef<unsigned> Overrides = None) + : MacroDirective(MD_Undefine, UndefLoc, ImportedFromModuleID, Overrides) { + assert((UndefLoc.isValid() || ImportedFromModuleID) && "Invalid UndefLoc!"); } static bool classof(const MacroDirective *MD) { @@ -525,6 +551,13 @@ public: static bool classof(const VisibilityMacroDirective *) { return true; } }; +inline unsigned *MacroDirective::getModuleDataStart() { + if (auto *Def = dyn_cast<DefMacroDirective>(this)) + return reinterpret_cast<unsigned*>(Def + 1); + else + return reinterpret_cast<unsigned*>(cast<UndefMacroDirective>(this) + 1); +} + inline SourceLocation MacroDirective::DefInfo::getLocation() const { if (isInvalid()) return SourceLocation(); diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 7869799c2c54..36605c9c18c6 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -11,8 +11,8 @@ // loading named modules. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_LEX_MODULE_LOADER_H -#define LLVM_CLANG_LEX_MODULE_LOADER_H +#ifndef LLVM_CLANG_LEX_MODULELOADER_H +#define LLVM_CLANG_LEX_MODULELOADER_H #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index a86a92749959..ed885a7410d5 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -65,19 +65,21 @@ private: llvm::StringMap<Module *> Modules; public: - /// \brief Describes the role of a module header. + /// \brief Flags describing the role of a module header. enum ModuleHeaderRole { /// \brief This header is normally included in the module. - NormalHeader, + NormalHeader = 0x0, /// \brief This header is included but private. - PrivateHeader, - /// \brief This header is explicitly excluded from the module. - ExcludedHeader + PrivateHeader = 0x1, + /// \brief This header is part of the module (for layering purposes) but + /// should be textually included. + TextualHeader = 0x2, // Caution: Adding an enumerator needs other changes. // Adjust the number of bits for KnownHeader::Storage. // Adjust the bitfield HeaderFileInfo::HeaderRole size. // Adjust the HeaderFileInfoTrait::ReadData streaming. // Adjust the HeaderFileInfoTrait::EmitData streaming. + // Adjust ModuleMap::addHeader. }; /// \brief A header that is known to reside within a given module, @@ -96,8 +98,8 @@ public: ModuleHeaderRole getRole() const { return Storage.getInt(); } /// \brief Whether this header is available in the module. - bool isAvailable() const { - return getRole() != ExcludedHeader && getModule()->isAvailable(); + bool isAvailable() const { + return getModule()->isAvailable(); } // \brief Whether this known header is valid (i.e., it has an @@ -107,6 +109,8 @@ public: } }; + typedef llvm::SmallPtrSet<const FileEntry *, 1> AdditionalModMapsSet; + private: typedef llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1> > HeadersMap; @@ -123,15 +127,29 @@ private: /// header. llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs; + /// \brief The set of attributes that can be attached to a module. + struct Attributes { + Attributes() : IsSystem(), IsExternC(), IsExhaustive() {} + + /// \brief Whether this is a system module. + unsigned IsSystem : 1; + + /// \brief Whether this is an extern "C" module. + unsigned IsExternC : 1; + + /// \brief Whether this is an exhaustive set of configuration macros. + unsigned IsExhaustive : 1; + }; + /// \brief A directory for which framework modules can be inferred. struct InferredDirectory { - InferredDirectory() : InferModules(), InferSystemModules() { } + InferredDirectory() : InferModules() {} /// \brief Whether to infer modules from this directory. unsigned InferModules : 1; - /// \brief Whether the modules we infer are [system] modules. - unsigned InferSystemModules : 1; + /// \brief The attributes to use for inferred modules. + Attributes Attrs; /// \brief If \c InferModules is non-zero, the module map file that allowed /// inferred modules. Otherwise, nullptr. @@ -146,6 +164,12 @@ private: /// framework modules from within those directories. llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories; + /// A mapping from an inferred module to the module map that allowed the + /// inference. + llvm::DenseMap<const Module *, const FileEntry *> InferredModuleAllowedBy; + + llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps; + /// \brief Describes whether we haved parsed a particular file as a module /// map. llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap; @@ -204,6 +228,10 @@ private: return static_cast<bool>(findHeaderInUmbrellaDirs(File, IntermediateDirs)); } + Module *inferFrameworkModule(StringRef ModuleName, + const DirectoryEntry *FrameworkDir, + Attributes Attrs, Module *Parent); + public: /// \brief Construct a new module map. /// @@ -241,11 +269,16 @@ public: /// used from. Used to disambiguate if a header is present in multiple /// modules. /// + /// \param IncludeTextualHeaders If \c true, also find textual headers. By + /// default, these are treated like excluded headers and result in no known + /// header being found. + /// /// \returns The module KnownHeader, which provides the module that owns the /// given header file. The KnownHeader is default constructed to indicate /// that no module owns this header file. KnownHeader findModuleForHeader(const FileEntry *File, - Module *RequestingModule = nullptr); + Module *RequestingModule = nullptr, + bool IncludeTextualHeaders = false); /// \brief Reports errors if a module must not include a specific file. /// @@ -306,9 +339,6 @@ public: /// \param Parent The module that will act as the parent of this submodule, /// or NULL to indicate that this is a top-level module. /// - /// \param ModuleMap The module map that defines or allows the inference of - /// this module. - /// /// \param IsFramework Whether this is a framework module. /// /// \param IsExplicit Whether this is an explicit submodule. @@ -316,26 +346,9 @@ public: /// \returns The found or newly-created module, along with a boolean value /// that will be true if the module is newly-created. std::pair<Module *, bool> findOrCreateModule(StringRef Name, Module *Parent, - const FileEntry *ModuleMap, bool IsFramework, bool IsExplicit); - /// \brief Determine whether we can infer a framework module a framework - /// with the given name in the given - /// - /// \param ParentDir The directory that is the parent of the framework - /// directory. - /// - /// \param Name The name of the module. - /// - /// \param IsSystem Will be set to 'true' if the inferred module must be a - /// system module. - /// - /// \returns true if we are allowed to infer a framework module, and false - /// otherwise. - bool canInferFrameworkModule(const DirectoryEntry *ParentDir, - StringRef Name, bool &IsSystem) const; - /// \brief Infer the contents of a framework module map from the given /// framework directory. Module *inferFrameworkModule(StringRef ModuleName, @@ -349,7 +362,35 @@ public: /// /// \returns The file entry for the module map file containing the given /// module, or NULL if the module definition was inferred. - const FileEntry *getContainingModuleMapFile(Module *Module) const; + const FileEntry *getContainingModuleMapFile(const Module *Module) const; + + /// \brief Get the module map file that (along with the module name) uniquely + /// identifies this module. + /// + /// The particular module that \c Name refers to may depend on how the module + /// was found in header search. However, the combination of \c Name and + /// this module map will be globally unique for top-level modules. In the case + /// of inferred modules, returns the module map that allowed the inference + /// (e.g. contained 'module *'). Otherwise, returns + /// getContainingModuleMapFile(). + const FileEntry *getModuleMapFileForUniquing(const Module *M) const; + + void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap); + + /// \brief Get any module map files other than getModuleMapFileForUniquing(M) + /// that define submodules of a top-level module \p M. This is cheaper than + /// getting the module map file for each submodule individually, since the + /// expected number of results is very small. + AdditionalModMapsSet *getAdditionalModuleMapFiles(const Module *M) { + auto I = AdditionalModMaps.find(M); + if (I == AdditionalModMaps.end()) + return nullptr; + return &I->second; + } + + void addAdditionalModuleMapFile(const Module *M, const FileEntry *ModuleMap) { + AdditionalModMaps[M].insert(ModuleMap); + } /// \brief Resolve all of the unresolved exports in the given module. /// @@ -401,9 +442,12 @@ public: /// \brief Adds this header to the given module. /// \param Role The role of the header wrt the module. - void addHeader(Module *Mod, const FileEntry *Header, + void addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role); + /// \brief Marks this header as being excluded from the given module. + void excludeHeader(Module *Mod, Module::Header Header); + /// \brief Parse the given module map file, and record any modules we /// encounter. /// @@ -412,8 +456,12 @@ public: /// \param IsSystem Whether this module map file is in a system header /// directory, and therefore should be considered a system module. /// + /// \param HomeDir The directory in which relative paths within this module + /// map file will be resolved. + /// /// \returns true if an error occurred, false otherwise. - bool parseModuleMapFile(const FileEntry *File, bool IsSystem); + bool parseModuleMapFile(const FileEntry *File, bool IsSystem, + const DirectoryEntry *HomeDir); /// \brief Dump the contents of the module map, for debugging purposes. void dump(); diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h index e3c6de555b35..83e6f99078df 100644 --- a/include/clang/Lex/MultipleIncludeOpt.h +++ b/include/clang/Lex/MultipleIncludeOpt.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_MULTIPLEINCLUDEOPT_H -#define LLVM_CLANG_MULTIPLEINCLUDEOPT_H +#ifndef LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H +#define LLVM_CLANG_LEX_MULTIPLEINCLUDEOPT_H #include "clang/Basic/SourceLocation.h" diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 7f1ea34a460e..056c58aa3348 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -322,15 +322,12 @@ public: /// \brief Simple wrapper class for chaining callbacks. class PPChainedCallbacks : public PPCallbacks { virtual void anchor(); - PPCallbacks *First, *Second; + std::unique_ptr<PPCallbacks> First, Second; public: - PPChainedCallbacks(PPCallbacks *_First, PPCallbacks *_Second) - : First(_First), Second(_Second) {} - ~PPChainedCallbacks() { - delete Second; - delete First; - } + PPChainedCallbacks(std::unique_ptr<PPCallbacks> _First, + std::unique_ptr<PPCallbacks> _Second) + : First(std::move(_First)), Second(std::move(_Second)) {} void FileChanged(SourceLocation Loc, FileChangeReason Reason, SrcMgr::CharacteristicKind FileType, diff --git a/include/clang/Lex/PTHLexer.h b/include/clang/Lex/PTHLexer.h index 2352ccea1853..54c91f6b0860 100644 --- a/include/clang/Lex/PTHLexer.h +++ b/include/clang/Lex/PTHLexer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PTHLEXER_H -#define LLVM_CLANG_PTHLEXER_H +#ifndef LLVM_CLANG_LEX_PTHLEXER_H +#define LLVM_CLANG_LEX_PTHLEXER_H #include "clang/Lex/PreprocessorLexer.h" diff --git a/include/clang/Lex/PTHManager.h b/include/clang/Lex/PTHManager.h index 11b5ceaad1de..64ecf5f575f3 100644 --- a/include/clang/Lex/PTHManager.h +++ b/include/clang/Lex/PTHManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PTHMANAGER_H -#define LLVM_CLANG_PTHMANAGER_H +#ifndef LLVM_CLANG_LEX_PTHMANAGER_H +#define LLVM_CLANG_LEX_PTHMANAGER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/IdentifierTable.h" @@ -20,6 +20,7 @@ #include "clang/Lex/PTHLexer.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/OnDiskHashTable.h" #include <string> namespace llvm { @@ -36,19 +37,26 @@ class FileSystemStatCache; class PTHManager : public IdentifierInfoLookup { friend class PTHLexer; + friend class PTHStatCache; + + class PTHStringLookupTrait; + class PTHFileLookupTrait; + typedef llvm::OnDiskChainedHashTable<PTHStringLookupTrait> PTHStringIdLookup; + typedef llvm::OnDiskChainedHashTable<PTHFileLookupTrait> PTHFileLookup; + /// The memory mapped PTH file. - const llvm::MemoryBuffer* Buf; + std::unique_ptr<const llvm::MemoryBuffer> Buf; /// Alloc - Allocator used for IdentifierInfo objects. llvm::BumpPtrAllocator Alloc; /// IdMap - A lazily generated cache mapping from persistent identifiers to /// IdentifierInfo*. - IdentifierInfo** PerIDCache; + std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> PerIDCache; /// FileLookup - Abstract data structure used for mapping between files /// and token data in the PTH file. - void* FileLookup; + std::unique_ptr<PTHFileLookup> FileLookup; /// IdDataTable - Array representing the mapping from persistent IDs to the /// data offset within the PTH file containing the information to @@ -57,7 +65,7 @@ class PTHManager : public IdentifierInfoLookup { /// SortedIdTable - Abstract data structure mapping from strings to /// persistent IDs. This is used by get(). - void* StringIdLookup; + std::unique_ptr<PTHStringIdLookup> StringIdLookup; /// NumIds - The number of identifiers in the PTH file. const unsigned NumIds; @@ -76,10 +84,12 @@ class PTHManager : public IdentifierInfoLookup { /// This constructor is intended to only be called by the static 'Create' /// method. - PTHManager(const llvm::MemoryBuffer* buf, void* fileLookup, - const unsigned char* idDataTable, IdentifierInfo** perIDCache, - void* stringIdLookup, unsigned numIds, - const unsigned char* spellingBase, const char *originalSourceFile); + PTHManager(std::unique_ptr<const llvm::MemoryBuffer> buf, + std::unique_ptr<PTHFileLookup> fileLookup, + const unsigned char *idDataTable, + std::unique_ptr<IdentifierInfo *[], llvm::FreeDeleter> perIDCache, + std::unique_ptr<PTHStringIdLookup> stringIdLookup, unsigned numIds, + const unsigned char *spellingBase, const char *originalSourceFile); PTHManager(const PTHManager &) LLVM_DELETED_FUNCTION; void operator=(const PTHManager &) LLVM_DELETED_FUNCTION; @@ -131,7 +141,7 @@ public: /// FileManager objects. These objects use the PTH data to speed up /// calls to stat by memoizing their results from when the PTH file /// was generated. - FileSystemStatCache *createStatCache(); + std::unique_ptr<FileSystemStatCache> createStatCache(); }; } // end namespace clang diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index 4a695a0e901c..4123bae2ea3a 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PRAGMA_H -#define LLVM_CLANG_PRAGMA_H +#ifndef LLVM_CLANG_LEX_PRAGMA_H +#define LLVM_CLANG_LEX_PRAGMA_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index d4b4ba246961..326f519e914e 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -79,6 +79,13 @@ public: } }; +/// \brief Context in which macro name is used. +enum MacroUse { + MU_Other = 0, // other than #define or #undef + MU_Define = 1, // macro name specified in #define + MU_Undef = 2 // macro name specified in #undef +}; + /// \brief Engages in a tight little dance with the lexer to efficiently /// preprocess tokens. /// @@ -92,7 +99,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { const TargetInfo *Target; FileManager &FileMgr; SourceManager &SourceMgr; - ScratchBuffer *ScratchBuf; + std::unique_ptr<ScratchBuffer> ScratchBuf; HeaderSearch &HeaderInfo; ModuleLoader &TheModuleLoader; @@ -128,6 +135,8 @@ class Preprocessor : public RefCountedBase<Preprocessor> { IdentifierInfo *Ident__is_identifier; // __is_identifier IdentifierInfo *Ident__building_module; // __building_module IdentifierInfo *Ident__MODULE__; // __MODULE__ + IdentifierInfo *Ident__has_cpp_attribute; // __has_cpp_attribute + IdentifierInfo *Ident__has_declspec; // __has_declspec_attribute SourceLocation DATELoc, TIMELoc; unsigned CounterValue; // Next __COUNTER__ value. @@ -192,7 +201,11 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief Tracks all of the pragmas that the client registered /// with this preprocessor. - PragmaNamespace *PragmaHandlers; + std::unique_ptr<PragmaNamespace> PragmaHandlers; + + /// \brief Pragma handlers of the original source is stored here during the + /// parsing of a model file. + std::unique_ptr<PragmaNamespace> PragmaHandlersBackup; /// \brief Tracks all of the comment handlers that the client registered /// with this preprocessor. @@ -245,12 +258,17 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief True if we hit the code-completion point. bool CodeCompletionReached; + /// \brief The directory that the main file should be considered to occupy, + /// if it does not correspond to a real file (as happens when building a + /// module). + const DirectoryEntry *MainFileDir; + /// \brief The number of bytes that we will initially skip when entering the /// main file, along with a flag that indicates whether skipping this number /// of bytes will place the lexer at the start of a line. /// /// This is used when loading a precompiled preamble. - std::pair<unsigned, bool> SkipMainFilePreamble; + std::pair<int, bool> SkipMainFilePreamble; /// \brief The current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. @@ -334,7 +352,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief Actions invoked when some preprocessor activity is /// encountered (e.g. a file is \#included, etc). - PPCallbacks *Callbacks; + std::unique_ptr<PPCallbacks> Callbacks; struct MacroExpandsInfo { Token Tok; @@ -391,7 +409,7 @@ class Preprocessor : public RefCountedBase<Preprocessor> { /// \brief Cache of macro expanders to reduce malloc traffic. enum { TokenLexerCacheSize = 8 }; unsigned NumCachedTokenLexers; - TokenLexer *TokenLexerCache[TokenLexerCacheSize]; + std::unique_ptr<TokenLexer> TokenLexerCache[TokenLexerCacheSize]; /// \} /// \brief Keeps macro expanded tokens for TokenLexers. @@ -433,17 +451,12 @@ private: // Cached tokens state. struct MacroInfoChain { MacroInfo MI; MacroInfoChain *Next; - MacroInfoChain *Prev; }; /// MacroInfos are managed as a chain for easy disposal. This is the head /// of that list. MacroInfoChain *MIChainHead; - /// A "freelist" of MacroInfo objects that can be reused for quick - /// allocation. - MacroInfoChain *MICache; - struct DeserializedMacroInfoChain { MacroInfo MI; unsigned OwningModuleID; // MUST be immediately after the MacroInfo object @@ -469,6 +482,17 @@ public: /// lifetime of the preprocessor. void Initialize(const TargetInfo &Target); + /// \brief Initialize the preprocessor to parse a model file + /// + /// To parse model files the preprocessor of the original source is reused to + /// preserver the identifier table. However to avoid some duplicate + /// information in the preprocessor some cleanup is needed before it is used + /// to parse model files. This method does that cleanup. + void InitializeForModelFile(); + + /// \brief Cleanup after model file parsing + void FinalizeForModelFile(); + /// \brief Retrieve the preprocessor options used to initialize this /// preprocessor. PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; } @@ -557,6 +581,9 @@ public: /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; + /// \brief Return the submodule owning the file being lexed. + Module *getCurrentSubmodule() const { return CurSubmodule; } + /// \brief Returns the FileID for the preprocessor predefines. FileID getPredefinesFileID() const { return PredefinesFileID; } @@ -565,11 +592,12 @@ public: /// /// Note that this class takes ownership of any PPCallbacks object given to /// it. - PPCallbacks *getPPCallbacks() const { return Callbacks; } - void addPPCallbacks(PPCallbacks *C) { + PPCallbacks *getPPCallbacks() const { return Callbacks.get(); } + void addPPCallbacks(std::unique_ptr<PPCallbacks> C) { if (Callbacks) - C = new PPChainedCallbacks(C, Callbacks); - Callbacks = C; + C = llvm::make_unique<PPChainedCallbacks>(std::move(C), + std::move(Callbacks)); + Callbacks = std::move(C); } /// \} @@ -605,13 +633,15 @@ public: void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD); DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc, - bool isImported) { - DefMacroDirective *MD = AllocateDefMacroDirective(MI, Loc, isImported); + unsigned ImportedFromModuleID, + ArrayRef<unsigned> Overrides) { + DefMacroDirective *MD = + AllocateDefMacroDirective(MI, Loc, ImportedFromModuleID, Overrides); appendMacroDirective(II, MD); return MD; } DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI){ - return appendDefMacroDirective(II, MI, MI->getDefinitionLoc(), false); + return appendDefMacroDirective(II, MI, MI->getDefinitionLoc(), 0, None); } /// \brief Set a MacroDirective that was loaded from a PCH file. void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *MD); @@ -990,6 +1020,12 @@ public: PragmaARCCFCodeAuditedLoc = Loc; } + /// \brief Set the directory in which the main file should be considered + /// to have been found, if it is not a real file. + void setMainFileDir(const DirectoryEntry *Dir) { + MainFileDir = Dir; + } + /// \brief Instruct the preprocessor to skip part of the main source file. /// /// \param Bytes The number of bytes in the preamble to skip. @@ -1307,6 +1343,7 @@ public: /// reference is for system \#include's or not (i.e. using <> instead of ""). const FileEntry *LookupFile(SourceLocation FilenameLoc, StringRef Filename, bool isAngled, const DirectoryLookup *FromDir, + const FileEntry *FromFile, const DirectoryLookup *&CurDir, SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, @@ -1343,11 +1380,13 @@ public: /// followed by EOD. Return true if the token is not a valid on-off-switch. bool LexOnOffSwitch(tok::OnOffSwitch &OOS); - bool CheckMacroName(Token &MacroNameTok, char isDefineUndef); + bool CheckMacroName(Token &MacroNameTok, MacroUse isDefineUndef, + bool *ShadowFlag = nullptr); private: void PushIncludeMacroStack() { + assert(CurLexerKind != CLK_CachingLexer && "cannot push a caching lexer"); IncludeMacroStack.push_back(IncludeStackInfo( CurLexerKind, CurSubmodule, std::move(CurLexer), std::move(CurPTHLexer), CurPPLexer, std::move(CurTokenLexer), CurDirLookup)); @@ -1370,24 +1409,29 @@ private: /// \brief Allocate a new MacroInfo object. MacroInfo *AllocateMacroInfo(); - DefMacroDirective *AllocateDefMacroDirective(MacroInfo *MI, - SourceLocation Loc, - bool isImported); - UndefMacroDirective *AllocateUndefMacroDirective(SourceLocation UndefLoc); + DefMacroDirective * + AllocateDefMacroDirective(MacroInfo *MI, SourceLocation Loc, + unsigned ImportedFromModuleID = 0, + ArrayRef<unsigned> Overrides = None); + UndefMacroDirective * + AllocateUndefMacroDirective(SourceLocation UndefLoc, + unsigned ImportedFromModuleID = 0, + ArrayRef<unsigned> Overrides = None); VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc, bool isPublic); - /// \brief Release the specified MacroInfo for re-use. - /// - /// This memory will be reused for allocating new MacroInfo objects. - void ReleaseMacroInfo(MacroInfo* MI); - /// \brief Lex and validate a macro name, which occurs after a - /// \#define or \#undef. + /// \#define or \#undef. + /// + /// \param MacroNameTok Token that represents the name defined or undefined. + /// \param IsDefineUndef Kind if preprocessor directive. + /// \param ShadowFlag Points to flag that is set if macro name shadows + /// a keyword. /// /// This emits a diagnostic, sets the token kind to eod, /// and discards the rest of the macro line if the macro name is invalid. - void ReadMacroName(Token &MacroNameTok, char isDefineUndef = 0); + void ReadMacroName(Token &MacroNameTok, MacroUse IsDefineUndef = MU_Other, + bool *ShadowFlag = nullptr); /// The ( starting an argument list of a macro definition has just been read. /// Lex the rest of the arguments and the closing ), updating \p MI with @@ -1521,6 +1565,7 @@ private: void HandleIncludeDirective(SourceLocation HashLoc, Token &Tok, const DirectoryLookup *LookupFrom = nullptr, + const FileEntry *LookupFromFile = nullptr, bool isImport = false); void HandleIncludeNextDirective(SourceLocation HashLoc, Token &Tok); void HandleIncludeMacrosDirective(SourceLocation HashLoc, Token &Tok); diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index ed226ae9a3f6..3a91fa72f2e5 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -12,8 +12,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PreprocessorLexer_H -#define LLVM_CLANG_PreprocessorLexer_H +#ifndef LLVM_CLANG_LEX_PREPROCESSORLEXER_H +#define LLVM_CLANG_LEX_PREPROCESSORLEXER_H #include "clang/Lex/MultipleIncludeOpt.h" #include "clang/Lex/Token.h" diff --git a/include/clang/Lex/ScratchBuffer.h b/include/clang/Lex/ScratchBuffer.h index f03515ffc142..a3d6096821e7 100644 --- a/include/clang/Lex/ScratchBuffer.h +++ b/include/clang/Lex/ScratchBuffer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SCRATCHBUFFER_H -#define LLVM_CLANG_SCRATCHBUFFER_H +#ifndef LLVM_CLANG_LEX_SCRATCHBUFFER_H +#define LLVM_CLANG_LEX_SCRATCHBUFFER_H #include "clang/Basic/SourceLocation.h" diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index c8b77d11747e..4a53c9c1bb19 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOKEN_H -#define LLVM_CLANG_TOKEN_H +#ifndef LLVM_CLANG_LEX_TOKEN_H +#define LLVM_CLANG_LEX_TOKEN_H #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/SourceLocation.h" @@ -58,6 +58,8 @@ class Token { /// may be dirty (have trigraphs / escaped newlines). /// Annotations (resolved type names, C++ scopes, etc): isAnnotation(). /// This is a pointer to sema-specific data for the annotation token. + /// Eof: + // This is a pointer to a Decl. /// Other: /// This is null. void *PtrData; @@ -66,7 +68,7 @@ class Token { tok::TokenKind Kind; /// Flags - Bits we track about this token, members of the TokenFlags enum. - unsigned char Flags; + unsigned short Flags; public: // Various flags set per token: @@ -80,7 +82,9 @@ public: LeadingEmptyMacro = 0x10, // Empty macro exists before this token. HasUDSuffix = 0x20, // This string or character literal has a ud-suffix. HasUCN = 0x40, // This identifier contains a UCN. - IgnoredComma = 0x80 // This comma is not a macro argument separator (MS). + IgnoredComma = 0x80, // This comma is not a macro argument separator (MS). + StringifiedInMacro = 0x100, // This string or character literal is formed by + // macro stringizing or charizing operator. }; tok::TokenKind getKind() const { return Kind; } @@ -162,12 +166,23 @@ public: assert(!isAnnotation() && "getIdentifierInfo() on an annotation token!"); if (isLiteral()) return nullptr; + if (is(tok::eof)) return nullptr; return (IdentifierInfo*) PtrData; } void setIdentifierInfo(IdentifierInfo *II) { PtrData = (void*) II; } + const void *getEofData() const { + assert(is(tok::eof)); + return reinterpret_cast<const void *>(PtrData); + } + void setEofData(const void *D) { + assert(is(tok::eof)); + assert(!PtrData); + PtrData = const_cast<void *>(D); + } + /// getRawIdentifier - For a raw identifier token (i.e., an identifier /// lexed in raw mode), returns a reference to the text substring in the /// buffer if known. @@ -262,6 +277,12 @@ public: /// Returns true if this token contains a universal character name. bool hasUCN() const { return (Flags & HasUCN) ? true : false; } + + /// Returns true if this token is formed by macro by stringizing or charizing + /// operator. + bool stringifiedInMacro() const { + return (Flags & StringifiedInMacro) ? true : false; + } }; /// \brief Information about the conditional stack (\#if directives) diff --git a/include/clang/Lex/TokenConcatenation.h b/include/clang/Lex/TokenConcatenation.h index 551300f402c2..a2d98b0d473a 100644 --- a/include/clang/Lex/TokenConcatenation.h +++ b/include/clang/Lex/TokenConcatenation.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_LEX_TOKEN_CONCATENATION_H -#define CLANG_LEX_TOKEN_CONCATENATION_H +#ifndef LLVM_CLANG_LEX_TOKENCONCATENATION_H +#define LLVM_CLANG_LEX_TOKENCONCATENATION_H #include "clang/Basic/TokenKinds.h" diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index a873a2e27508..306f98e2609a 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOKENLEXER_H -#define LLVM_CLANG_TOKENLEXER_H +#ifndef LLVM_CLANG_LEX_TOKENLEXER_H +#define LLVM_CLANG_LEX_TOKENLEXER_H #include "clang/Basic/SourceLocation.h" diff --git a/include/clang/Parse/ParseDiagnostic.h b/include/clang/Parse/ParseDiagnostic.h index b593806ff391..f3a7f3b7a8d7 100644 --- a/include/clang/Parse/ParseDiagnostic.h +++ b/include/clang/Parse/ParseDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICPARSE_H -#define LLVM_CLANG_DIAGNOSTICPARSE_H +#ifndef LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H +#define LLVM_CLANG_PARSE_PARSEDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index c58c41a44c58..f12bec6929e1 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -135,10 +135,9 @@ class Parser : public CodeCompletionHandler { mutable IdentifierInfo *Ident_final; mutable IdentifierInfo *Ident_override; - // Some token kinds such as C++ type traits can be reverted to identifiers and - // still get used as keywords depending on context. - llvm::SmallDenseMap<const IdentifierInfo *, tok::TokenKind> - ContextualKeywords; + // C++ type trait keywords that can be reverted to identifiers and still be + // used as type traits. + llvm::SmallDenseMap<IdentifierInfo *, tok::TokenKind> RevertibleTypeTraits; std::unique_ptr<PragmaHandler> AlignHandler; std::unique_ptr<PragmaHandler> GCCVisibilityHandler; @@ -164,6 +163,7 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> OptimizeHandler; std::unique_ptr<PragmaHandler> LoopHintHandler; std::unique_ptr<PragmaHandler> UnrollHintHandler; + std::unique_ptr<PragmaHandler> NoUnrollHintHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; @@ -258,24 +258,8 @@ public: typedef SmallVector<TemplateParameterList *, 4> TemplateParameterLists; - typedef clang::ExprResult ExprResult; - typedef clang::StmtResult StmtResult; - typedef clang::BaseResult BaseResult; - typedef clang::MemInitResult MemInitResult; - typedef clang::TypeResult TypeResult; - - typedef Expr *ExprArg; - typedef MutableArrayRef<Stmt*> MultiStmtArg; typedef Sema::FullExprArg FullExprArg; - ExprResult ExprError() { return ExprResult(true); } - StmtResult StmtError() { return StmtResult(true); } - - ExprResult ExprError(const DiagnosticBuilder &) { return ExprError(); } - StmtResult StmtError(const DiagnosticBuilder &) { return StmtError(); } - - ExprResult ExprEmpty() { return ExprResult(false); } - // Parsing methods. /// Initialize - Warm up the parser. @@ -350,6 +334,15 @@ private: /// For typos, give a fixit to '=' bool isTokenEqualOrEqualTypo(); + /// \brief Return the current token to the token stream and make the given + /// token the current token. + void UnconsumeToken(Token &Consumed) { + Token Next = Tok; + PP.EnterToken(Consumed); + PP.Lex(Tok); + PP.EnterToken(Next); + } + /// ConsumeAnyToken - Dispatch to the right Consume* method based on the /// current token type. This should only be used in cases where the type of /// the token really isn't known, e.g. in error recovery. @@ -524,7 +517,7 @@ private: /// \brief Handle the annotation token produced for /// #pragma clang loop and #pragma unroll. - LoopHint HandlePragmaLoopHint(); + bool HandlePragmaLoopHint(LoopHint &Hint); /// GetLookAheadToken - This peeks ahead N tokens and returns that token /// without consuming any tokens. LookAhead(0) returns 'Tok', LookAhead(1) @@ -591,8 +584,9 @@ private: /// Annotation was successful. ANK_Success }; - AnnotatedNameKind TryAnnotateName(bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = nullptr); + AnnotatedNameKind + TryAnnotateName(bool IsAddressOfOperand, + std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr); /// Push a tok::annot_cxxscope token onto the token stream. void AnnotateScopeToken(CXXScopeSpec &SS, bool IsNewAnnotation); @@ -633,12 +627,6 @@ private: /// otherwise emits a diagnostic and returns true. bool TryKeywordIdentFallback(bool DisableKeyword); - /// TryIdentKeywordUpgrade - Convert the current identifier token back to - /// its original kind and return true if it was disabled by - /// TryKeywordIdentFallback(), otherwise return false. Use this to - /// contextually enable keywords. - bool TryIdentKeywordUpgrade(); - /// \brief Get the TemplateIdAnnotation from the token. TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok); @@ -1161,6 +1149,7 @@ private: void ParseLateTemplatedFuncDef(LateParsedTemplate &LPT); static void LateTemplateParserCallback(void *P, LateParsedTemplate &LPT); + static void LateTemplateParserCleanupCallback(void *P); Sema::ParsingClassState PushParsingClass(Decl *TagOrTemplate, bool TopLevelClass, bool IsInterface); @@ -1412,8 +1401,12 @@ private: ExprResult ParseObjCBoolLiteral(); + ExprResult ParseFoldExpression(ExprResult LHS, BalancedDelimiterTracker &T); + //===--------------------------------------------------------------------===// // C++ Expressions + ExprResult tryParseCXXIdExpression(CXXScopeSpec &SS, bool isAddressOfOperand, + Token &Replacement); ExprResult ParseCXXIdExpression(bool isAddressOfOperand = false); bool areTokensAdjacent(const Token &A, const Token &B); @@ -1457,7 +1450,7 @@ private: //===--------------------------------------------------------------------===// // C++ 5.2.4: C++ Pseudo-Destructor Expressions - ExprResult ParseCXXPseudoDestructor(ExprArg Base, SourceLocation OpLoc, + ExprResult ParseCXXPseudoDestructor(Expr *Base, SourceLocation OpLoc, tok::TokenKind OpKind, CXXScopeSpec &SS, ParsedType ObjectType); @@ -1471,10 +1464,12 @@ private: ExprResult ParseThrowExpression(); ExceptionSpecificationType tryParseExceptionSpecification( + bool Delayed, SourceRange &SpecificationRange, SmallVectorImpl<ParsedType> &DynamicExceptions, SmallVectorImpl<SourceRange> &DynamicExceptionRanges, - ExprResult &NoexceptExpr); + ExprResult &NoexceptExpr, + CachedTokens *&ExceptionSpecTokens); // EndLoc is filled with the location of the last token of the specification. ExceptionSpecificationType ParseDynamicExceptionSpecification( @@ -1557,10 +1552,10 @@ private: ExprResult ParseObjCMessageExpressionBody(SourceLocation LBracloc, SourceLocation SuperLoc, ParsedType ReceiverType, - ExprArg ReceiverExpr); + Expr *ReceiverExpr); ExprResult ParseAssignmentExprWithObjCMessageExprStart( SourceLocation LBracloc, SourceLocation SuperLoc, - ParsedType ReceiverType, ExprArg ReceiverExpr); + ParsedType ReceiverType, Expr *ReceiverExpr); bool ParseObjCXXMessageReceiver(bool &IsExpr, void *&TypeOrExpr); //===--------------------------------------------------------------------===// @@ -1724,18 +1719,15 @@ private: bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); } }; - DeclGroupPtrTy ParseDeclaration(StmtVector &Stmts, - unsigned Context, SourceLocation &DeclEnd, + DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs); - DeclGroupPtrTy ParseSimpleDeclaration(StmtVector &Stmts, - unsigned Context, + DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs, bool RequireSemi, ForRangeInit *FRI = nullptr); bool MightBeDeclarator(unsigned Context); DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, - bool AllowFunctionDefinitions, SourceLocation *DeclEnd = nullptr, ForRangeInit *FRI = nullptr); Decl *ParseDeclarationAfterDeclarator(Declarator &D, @@ -1781,16 +1773,9 @@ private: void ParseStructUnionBody(SourceLocation StartLoc, unsigned TagType, Decl *TagDecl); - struct FieldCallback { - virtual void invoke(ParsingFieldDeclarator &Field) = 0; - virtual ~FieldCallback() {} - - private: - virtual void _anchor(); - }; - struct ObjCPropertyCallback; - - void ParseStructDeclaration(ParsingDeclSpec &DS, FieldCallback &Callback); + void ParseStructDeclaration( + ParsingDeclSpec &DS, + llvm::function_ref<void(ParsingFieldDeclarator &)> FieldsCallback); bool isDeclarationSpecifier(bool DisambiguatingWithExpression = false); bool isTypeSpecifierQualifier(); @@ -2108,6 +2093,8 @@ private: SourceLocation AttrNameLoc, ParsedAttributes &Attrs); void ParseMicrosoftTypeAttributes(ParsedAttributes &attrs); + void DiagnoseAndSkipExtendedMicrosoftTypeAttributes(); + SourceLocation SkipExtendedMicrosoftTypeAttributes(); void ParseMicrosoftInheritanceClassAttributes(ParsedAttributes &attrs); void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLAttributes(ParsedAttributes &attrs); @@ -2163,7 +2150,8 @@ private: VirtSpecifiers::Specifier isCXX11VirtSpecifier() const { return isCXX11VirtSpecifier(Tok); } - void ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface); + void ParseOptionalCXX11VirtSpecifierSeq(VirtSpecifiers &VS, bool IsInterface, + SourceLocation FriendLoc); bool isCXX11FinalKeyword() const; @@ -2207,8 +2195,21 @@ private: void ParseDeclaratorInternal(Declarator &D, DirectDeclParseFunction DirectDeclParser); - void ParseTypeQualifierListOpt(DeclSpec &DS, bool GNUAttributesAllowed = true, - bool CXX11AttributesAllowed = true, + enum AttrRequirements { + AR_NoAttributesParsed = 0, ///< No attributes are diagnosed. + AR_GNUAttributesParsedAndRejected = 1 << 0, ///< Diagnose GNU attributes. + AR_GNUAttributesParsed = 1 << 1, + AR_CXX11AttributesParsed = 1 << 2, + AR_DeclspecAttributesParsed = 1 << 3, + AR_AllAttributesParsed = AR_GNUAttributesParsed | + AR_CXX11AttributesParsed | + AR_DeclspecAttributesParsed, + AR_VendorAttributesParsed = AR_GNUAttributesParsed | + AR_DeclspecAttributesParsed + }; + + void ParseTypeQualifierListOpt(DeclSpec &DS, + unsigned AttrReqs = AR_AllAttributesParsed, bool AtomicAllowed = true, bool IdentifierRequired = false); void ParseDirectDeclarator(Declarator &D); diff --git a/include/clang/Rewrite/Core/DeltaTree.h b/include/clang/Rewrite/Core/DeltaTree.h index a6109bf90157..248f2a07eac1 100644 --- a/include/clang/Rewrite/Core/DeltaTree.h +++ b/include/clang/Rewrite/Core/DeltaTree.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef CLANG_REWRITE_DELTATREE_H -#define CLANG_REWRITE_DELTATREE_H +#ifndef LLVM_CLANG_REWRITE_CORE_DELTATREE_H +#define LLVM_CLANG_REWRITE_CORE_DELTATREE_H #include "llvm/Support/Compiler.h" diff --git a/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h index ec061dc7dba8..dafdf51ce63b 100644 --- a/include/clang/Rewrite/Core/HTMLRewrite.h +++ b/include/clang/Rewrite/Core/HTMLRewrite.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_HTMLREWRITER_H -#define LLVM_CLANG_HTMLREWRITER_H +#ifndef LLVM_CLANG_REWRITE_CORE_HTMLREWRITE_H +#define LLVM_CLANG_REWRITE_CORE_HTMLREWRITE_H #include "clang/Basic/SourceLocation.h" #include <string> diff --git a/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h index f312aedc082a..1c6f3eb952dd 100644 --- a/include/clang/Rewrite/Core/RewriteRope.h +++ b/include/clang/Rewrite/Core/RewriteRope.h @@ -11,9 +11,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITEROPE_H -#define LLVM_CLANG_REWRITEROPE_H +#ifndef LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H +#define LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Compiler.h" #include <cassert> @@ -34,11 +35,10 @@ namespace clang { unsigned RefCount; char Data[1]; // Variable sized. - void addRef() { - ++RefCount; - } + void Retain() { ++RefCount; } - void dropRef() { + void Release() { + assert(RefCount > 0 && "Reference count is already zero."); if (--RefCount == 0) delete [] (char*)this; } @@ -57,39 +57,15 @@ namespace clang { /// that both refer to the same underlying RopeRefCountString (just with /// different offsets) which is a nice constant time operation. struct RopePiece { - RopeRefCountString *StrData; + llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData; unsigned StartOffs; unsigned EndOffs; RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {} - RopePiece(RopeRefCountString *Str, unsigned Start, unsigned End) - : StrData(Str), StartOffs(Start), EndOffs(End) { - if (StrData) - StrData->addRef(); - } - RopePiece(const RopePiece &RP) - : StrData(RP.StrData), StartOffs(RP.StartOffs), EndOffs(RP.EndOffs) { - if (StrData) - StrData->addRef(); - } - - ~RopePiece() { - if (StrData) - StrData->dropRef(); - } - - void operator=(const RopePiece &RHS) { - if (StrData != RHS.StrData) { - if (StrData) - StrData->dropRef(); - StrData = RHS.StrData; - if (StrData) - StrData->addRef(); - } - StartOffs = RHS.StartOffs; - EndOffs = RHS.EndOffs; - } + RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start, + unsigned End) + : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {} const char &operator[](unsigned Offset) const { return StrData->Data[Offset+StartOffs]; @@ -191,7 +167,7 @@ class RewriteRope { /// We allocate space for string data out of a buffer of size AllocChunkSize. /// This keeps track of how much space is left. - RopeRefCountString *AllocBuffer; + llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer; unsigned AllocOffs; enum { AllocChunkSize = 4080 }; @@ -201,12 +177,6 @@ public: : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) { } - ~RewriteRope() { - // If we had an allocation buffer, drop our reference to it. - if (AllocBuffer) - AllocBuffer->dropRef(); - } - typedef RopePieceBTree::iterator iterator; typedef RopePieceBTree::iterator const_iterator; iterator begin() const { return Chunks.begin(); } diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h index 7b22fb49bc2c..1ab7be6c5317 100644 --- a/include/clang/Rewrite/Core/Rewriter.h +++ b/include/clang/Rewrite/Core/Rewriter.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITER_H -#define LLVM_CLANG_REWRITER_H +#ifndef LLVM_CLANG_REWRITE_CORE_REWRITER_H +#define LLVM_CLANG_REWRITE_CORE_REWRITER_H #include "clang/Basic/SourceLocation.h" #include "clang/Rewrite/Core/DeltaTree.h" @@ -27,7 +27,6 @@ namespace clang { class LangOptions; class Rewriter; class SourceManager; - class Stmt; /// RewriteBuffer - As code is rewritten, SourceBuffer's from the original /// input with modifications get a new RewriteBuffer associated with them. The @@ -245,11 +244,6 @@ public: /// operation. bool ReplaceText(SourceRange range, SourceRange replacementRange); - /// ReplaceStmt - This replaces a Stmt/Expr with another, using the pretty - /// printer to generate the replacement code. This returns true if the input - /// could not be rewritten, or false if successful. - bool ReplaceStmt(Stmt *From, Stmt *To); - /// \brief Increase indentation for the lines between the given source range. /// To determine what the indentation should be, 'parentIndent' is used /// that should be at a source location with an indentation one degree @@ -260,10 +254,6 @@ public: parentIndent); } - /// ConvertToString converts statement 'From' to a string using the - /// pretty printer. - std::string ConvertToString(Stmt *From); - /// getEditBuffer - This is like getRewriteBufferFor, but always returns a /// buffer, and allows you to write on it directly. This is useful if you /// want efficient low-level access to apis for scribbling on one specific diff --git a/include/clang/Rewrite/Core/TokenRewriter.h b/include/clang/Rewrite/Core/TokenRewriter.h index c313b453d984..598477f318fc 100644 --- a/include/clang/Rewrite/Core/TokenRewriter.h +++ b/include/clang/Rewrite/Core/TokenRewriter.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOKENREWRITER_H -#define LLVM_CLANG_TOKENREWRITER_H +#ifndef LLVM_CLANG_REWRITE_CORE_TOKENREWRITER_H +#define LLVM_CLANG_REWRITE_CORE_TOKENREWRITER_H #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Token.h" diff --git a/include/clang/Rewrite/Frontend/ASTConsumers.h b/include/clang/Rewrite/Frontend/ASTConsumers.h index 584af3fa18b0..c9df8895041d 100644 --- a/include/clang/Rewrite/Frontend/ASTConsumers.h +++ b/include/clang/Rewrite/Frontend/ASTConsumers.h @@ -11,10 +11,11 @@ // //===----------------------------------------------------------------------===// -#ifndef REWRITE_ASTCONSUMERS_H -#define REWRITE_ASTCONSUMERS_H +#ifndef LLVM_CLANG_REWRITE_FRONTEND_ASTCONSUMERS_H +#define LLVM_CLANG_REWRITE_FRONTEND_ASTCONSUMERS_H #include "clang/Basic/LLVM.h" +#include <memory> #include <string> namespace clang { @@ -26,23 +27,21 @@ class Preprocessor; // ObjC rewriter: attempts to rewrite ObjC constructs into pure C code. // This is considered experimental, and only works with Apple's ObjC runtime. -ASTConsumer *CreateObjCRewriter(const std::string &InFile, - raw_ostream *OS, - DiagnosticsEngine &Diags, - const LangOptions &LOpts, - bool SilenceRewriteMacroWarning); -ASTConsumer *CreateModernObjCRewriter(const std::string &InFile, - raw_ostream *OS, - DiagnosticsEngine &Diags, - const LangOptions &LOpts, - bool SilenceRewriteMacroWarning, - bool LineInfo); +std::unique_ptr<ASTConsumer> +CreateObjCRewriter(const std::string &InFile, raw_ostream *OS, + DiagnosticsEngine &Diags, const LangOptions &LOpts, + bool SilenceRewriteMacroWarning); +std::unique_ptr<ASTConsumer> +CreateModernObjCRewriter(const std::string &InFile, raw_ostream *OS, + DiagnosticsEngine &Diags, const LangOptions &LOpts, + bool SilenceRewriteMacroWarning, bool LineInfo); /// CreateHTMLPrinter - Create an AST consumer which rewrites source code to /// HTML with syntax highlighting suitable for viewing in a web-browser. -ASTConsumer *CreateHTMLPrinter(raw_ostream *OS, Preprocessor &PP, - bool SyntaxHighlight = true, - bool HighlightMacros = true); +std::unique_ptr<ASTConsumer> CreateHTMLPrinter(raw_ostream *OS, + Preprocessor &PP, + bool SyntaxHighlight = true, + bool HighlightMacros = true); } // end clang namespace diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h index 3ad8f408af6e..599417235464 100644 --- a/include/clang/Rewrite/Frontend/FixItRewriter.h +++ b/include/clang/Rewrite/Frontend/FixItRewriter.h @@ -12,8 +12,8 @@ // then forwards any diagnostics to the adapted diagnostic client. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H -#define LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H +#ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H +#define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceLocation.h" @@ -66,7 +66,7 @@ class FixItRewriter : public DiagnosticConsumer { /// \brief The diagnostic client that performs the actual formatting /// of error messages. DiagnosticConsumer *Client; - bool OwnsClient; + std::unique_ptr<DiagnosticConsumer> Owner; /// \brief Turn an input path into an output path. NULL implies overwriting /// the original. @@ -125,4 +125,4 @@ public: } -#endif // LLVM_CLANG_REWRITE_FIX_IT_REWRITER_H +#endif diff --git a/include/clang/Rewrite/Frontend/FrontendActions.h b/include/clang/Rewrite/Frontend/FrontendActions.h index fc792707487d..c8ea8b2dd878 100644 --- a/include/clang/Rewrite/Frontend/FrontendActions.h +++ b/include/clang/Rewrite/Frontend/FrontendActions.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITE_FRONTENDACTIONS_H -#define LLVM_CLANG_REWRITE_FRONTENDACTIONS_H +#ifndef LLVM_CLANG_REWRITE_FRONTEND_FRONTENDACTIONS_H +#define LLVM_CLANG_REWRITE_FRONTEND_FRONTENDACTIONS_H #include "clang/Frontend/FrontendAction.h" @@ -22,8 +22,8 @@ class FixItOptions; class HTMLPrintAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class FixItAction : public ASTFrontendAction { @@ -31,8 +31,8 @@ protected: std::unique_ptr<FixItRewriter> Rewriter; std::unique_ptr<FixItOptions> FixItOpts; - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; bool BeginSourceFileAction(CompilerInstance &CI, StringRef Filename) override; @@ -59,8 +59,8 @@ protected: class RewriteObjCAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; }; class RewriteMacrosAction : public PreprocessorFrontendAction { diff --git a/include/clang/Rewrite/Frontend/Rewriters.h b/include/clang/Rewrite/Frontend/Rewriters.h index f5ade5ad35d3..3ad76dff824f 100644 --- a/include/clang/Rewrite/Frontend/Rewriters.h +++ b/include/clang/Rewrite/Frontend/Rewriters.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_REWRITE_REWRITERS_H -#define LLVM_CLANG_REWRITE_REWRITERS_H +#ifndef LLVM_CLANG_REWRITE_FRONTEND_REWRITERS_H +#define LLVM_CLANG_REWRITE_FRONTEND_REWRITERS_H #include "clang/Basic/LLVM.h" diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h index 432c4e23a993..64dd2d36bef8 100644 --- a/include/clang/Sema/AnalysisBasedWarnings.h +++ b/include/clang/Sema/AnalysisBasedWarnings.h @@ -11,8 +11,8 @@ // that issues warnings based on dataflow-analysis. //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H -#define LLVM_CLANG_SEMA_ANALYSIS_WARNINGS_H +#ifndef LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H +#define LLVM_CLANG_SEMA_ANALYSISBASEDWARNINGS_H #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/AttributeList.h index c21c19fd55c9..dc85f5d2084c 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/AttributeList.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_ATTRLIST_H -#define LLVM_CLANG_SEMA_ATTRLIST_H +#ifndef LLVM_CLANG_SEMA_ATTRIBUTELIST_H +#define LLVM_CLANG_SEMA_ATTRIBUTELIST_H #include "clang/Basic/SourceLocation.h" #include "clang/Basic/VersionTuple.h" @@ -94,10 +94,10 @@ private: /// The number of expression arguments this attribute has. /// The expressions themselves are stored after the object. - unsigned NumArgs : 16; + unsigned NumArgs : 15; /// Corresponds to the Syntax enum. - unsigned SyntaxUsed : 2; + unsigned SyntaxUsed : 3; /// True if already diagnosed as invalid. mutable unsigned Invalid : 1; @@ -455,6 +455,7 @@ public: bool hasCustomParsing() const; unsigned getMinArgs() const; unsigned getMaxArgs() const; + bool hasVariadicArg() const; bool diagnoseAppertainsTo(class Sema &S, const Decl *D) const; bool diagnoseLangOpts(class Sema &S) const; bool existsInTarget(const llvm::Triple &T) const; @@ -821,12 +822,13 @@ enum AttributeDeclKind { ExpectedFunctionMethodOrClass, ExpectedFunctionMethodOrParameter, ExpectedClass, + ExpectedEnum, ExpectedVariable, ExpectedMethod, ExpectedVariableFunctionOrLabel, ExpectedFieldOrGlobalVar, ExpectedStruct, - ExpectedVariableFunctionOrTag, + ExpectedVariableOrTypedef, ExpectedTLSVar, ExpectedVariableOrField, ExpectedVariableFieldOrTag, @@ -842,7 +844,8 @@ enum AttributeDeclKind { ExpectedObjectiveCProtocol, ExpectedFunctionGlobalVarMethodOrProperty, ExpectedStructOrTypedef, - ExpectedObjectiveCInterfaceOrProtocol + ExpectedObjectiveCInterfaceOrProtocol, + ExpectedKernelFunction }; } // end namespace clang diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 8364dfc4b0bb..d36882660298 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -37,6 +37,7 @@ namespace clang { class ASTContext; + class CXXRecordDecl; class TypeLoc; class LangOptions; class DiagnosticsEngine; @@ -141,6 +142,22 @@ public: /// nested-name-specifier '::'. void MakeGlobal(ASTContext &Context, SourceLocation ColonColonLoc); + /// \brief Turns this (empty) nested-name-specifier into '__super' + /// nested-name-specifier. + /// + /// \param Context The AST context in which this nested-name-specifier + /// resides. + /// + /// \param RD The declaration of the class in which nested-name-specifier + /// appeared. + /// + /// \param SuperLoc The location of the '__super' keyword. + /// name. + /// + /// \param ColonColonLoc The location of the trailing '::'. + void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, + SourceLocation SuperLoc, SourceLocation ColonColonLoc); + /// \brief Make a new nested-name-specifier from incomplete source-location /// information. /// @@ -1053,6 +1070,12 @@ struct DeclaratorChunk { /// EndLoc - If valid, the place where this chunck ends. SourceLocation EndLoc; + SourceRange getSourceRange() const { + if (EndLoc.isInvalid()) + return SourceRange(Loc, Loc); + return SourceRange(Loc, EndLoc); + } + struct TypeInfoCommon { AttributeList *AttrList; }; @@ -1159,7 +1182,7 @@ struct DeclaratorChunk { unsigned TypeQuals : 3; /// ExceptionSpecType - An ExceptionSpecificationType value. - unsigned ExceptionSpecType : 3; + unsigned ExceptionSpecType : 4; /// DeleteParams - If this is true, we need to delete[] Params. unsigned DeleteParams : 1; @@ -1200,6 +1223,11 @@ struct DeclaratorChunk { /// If this is an invalid location, there is no volatile-qualifier. unsigned VolatileQualifierLoc; + /// \brief The location of the restrict-qualifier, if any. + /// + /// If this is an invalid location, there is no restrict-qualifier. + unsigned RestrictQualifierLoc; + /// \brief The location of the 'mutable' qualifer in a lambda-declarator, if /// any. unsigned MutableLoc; @@ -1221,6 +1249,10 @@ struct DeclaratorChunk { /// \brief Pointer to the expression in the noexcept-specifier of this /// function, if it has one. Expr *NoexceptExpr; + + /// \brief Pointer to the cached tokens for an exception-specification + /// that has not yet been parsed. + CachedTokens *ExceptionSpecTokens; }; /// \brief If HasTrailingReturnType is true, this is the trailing return @@ -1247,6 +1279,8 @@ struct DeclaratorChunk { delete[] Params; if (getExceptionSpecType() == EST_Dynamic) delete[] Exceptions; + else if (getExceptionSpecType() == EST_Unparsed) + delete ExceptionSpecTokens; } /// isKNRPrototype - Return true if this is a K&R style identifier list, @@ -1275,16 +1309,21 @@ struct DeclaratorChunk { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } - /// \brief Retrieve the location of the ref-qualifier, if any. + /// \brief Retrieve the location of the 'const' qualifier, if any. SourceLocation getConstQualifierLoc() const { return SourceLocation::getFromRawEncoding(ConstQualifierLoc); } - /// \brief Retrieve the location of the ref-qualifier, if any. + /// \brief Retrieve the location of the 'volatile' qualifier, if any. SourceLocation getVolatileQualifierLoc() const { return SourceLocation::getFromRawEncoding(VolatileQualifierLoc); } + /// \brief Retrieve the location of the 'restrict' qualifier, if any. + SourceLocation getRestrictQualifierLoc() const { + return SourceLocation::getFromRawEncoding(RestrictQualifierLoc); + } + /// \brief Retrieve the location of the 'mutable' qualifier, if any. SourceLocation getMutableLoc() const { return SourceLocation::getFromRawEncoding(MutableLoc); @@ -1429,6 +1468,7 @@ struct DeclaratorChunk { SourceLocation RefQualifierLoc, SourceLocation ConstQualifierLoc, SourceLocation VolatileQualifierLoc, + SourceLocation RestrictQualifierLoc, SourceLocation MutableLoc, ExceptionSpecificationType ESpecType, SourceLocation ESpecLoc, @@ -1436,6 +1476,7 @@ struct DeclaratorChunk { SourceRange *ExceptionRanges, unsigned NumExceptions, Expr *NoexceptExpr, + CachedTokens *ExceptionSpecTokens, SourceLocation LocalRangeBegin, SourceLocation LocalRangeEnd, Declarator &TheDeclarator, @@ -1458,7 +1499,8 @@ struct DeclaratorChunk { SourceLocation Loc) { DeclaratorChunk I; I.Kind = MemberPointer; - I.Loc = Loc; + I.Loc = SS.getBeginLoc(); + I.EndLoc = Loc; I.Mem.TypeQuals = TypeQuals; I.Mem.AttrList = nullptr; new (I.Mem.ScopeMem.Mem) CXXScopeSpec(SS); @@ -1881,6 +1923,14 @@ public: return DeclTypeInfo[i]; } + typedef SmallVectorImpl<DeclaratorChunk>::const_iterator type_object_iterator; + typedef llvm::iterator_range<type_object_iterator> type_object_range; + + /// Returns the range of type objects, from the identifier outwards. + type_object_range type_objects() const { + return type_object_range(DeclTypeInfo.begin(), DeclTypeInfo.end()); + } + void DropFirstTypeObject() { assert(!DeclTypeInfo.empty() && "No type chunks to drop."); DeclTypeInfo.front().destroy(); diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index 85551f8db036..7fd6779f344d 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -19,8 +19,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H -#define LLVM_CLANG_SEMA_DELAYED_DIAGNOSTIC_H +#ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H +#define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H #include "clang/Sema/Sema.h" diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index 325abdf8e517..c0ef7121a6ee 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -10,8 +10,8 @@ // This file defines the ExternalSemaSource interface. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H -#define LLVM_CLANG_SEMA_EXTERNAL_SEMA_SOURCE_H +#ifndef LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H +#define LLVM_CLANG_SEMA_EXTERNALSEMASOURCE_H #include "clang/AST/ExternalASTSource.h" #include "clang/AST/Type.h" @@ -20,6 +20,10 @@ #include "llvm/ADT/MapVector.h" #include <utility> +namespace llvm { +template <class T, unsigned n> class SmallSetVector; +} + namespace clang { class CXXConstructorDecl; @@ -132,6 +136,15 @@ public: /// introduce the same declarations repeatedly. virtual void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) {} + /// \brief Read the set of potentially unused typedefs known to the source. + /// + /// The external source should append its own potentially unused local + /// typedefs to the given vector of declarations. Note that this routine may + /// be invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + virtual void ReadUnusedLocalTypedefNameCandidates( + llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {}; + /// \brief Read the set of locally-scoped external declarations known to the /// external Sema source. /// diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h index b2404bc14b93..a07834f95629 100644 --- a/include/clang/Sema/IdentifierResolver.h +++ b/include/clang/Sema/IdentifierResolver.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H -#define LLVM_CLANG_AST_SEMA_IDENTIFIERRESOLVER_H +#ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H +#define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H #include "clang/Basic/IdentifierTable.h" #include "llvm/ADT/SmallVector.h" diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index 00cc164d964c..1c6c7bbbd997 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -132,7 +132,7 @@ public: : ResultKind(NotFound), Paths(nullptr), NamingClass(nullptr), - SemaRef(SemaRef), + SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind), IDNS(0), @@ -154,7 +154,7 @@ public: : ResultKind(NotFound), Paths(nullptr), NamingClass(nullptr), - SemaRef(SemaRef), + SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind), IDNS(0), @@ -174,7 +174,7 @@ public: : ResultKind(NotFound), Paths(nullptr), NamingClass(nullptr), - SemaRef(Other.SemaRef), + SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo), LookupKind(Other.LookupKind), IDNS(Other.IDNS), @@ -305,7 +305,7 @@ public: if (!D->isInIdentifierNamespace(IDNS)) return nullptr; - if (isHiddenDeclarationVisible() || isVisible(SemaRef, D)) + if (isHiddenDeclarationVisible() || isVisible(getSema(), D)) return D; return getAcceptableDeclSlow(D); @@ -424,13 +424,20 @@ public: Paths = nullptr; } } else { - AmbiguityKind SavedAK = Ambiguity; + AmbiguityKind SavedAK; + bool WasAmbiguous = false; + if (ResultKind == Ambiguous) { + SavedAK = Ambiguity; + WasAmbiguous = true; + } ResultKind = Found; resolveKind(); // If we didn't make the lookup unambiguous, restore the old // ambiguity kind. if (ResultKind == Ambiguous) { + (void)WasAmbiguous; + assert(WasAmbiguous); Ambiguity = SavedAK; } else if (Paths) { deletePaths(Paths); @@ -544,7 +551,7 @@ public: /// \brief Get the Sema object that this lookup result is searching /// with. - Sema &getSema() const { return SemaRef; } + Sema &getSema() const { return *SemaPtr; } /// A class for iterating through a result set and possibly /// filtering out results. The results returned are possibly @@ -623,9 +630,9 @@ public: private: void diagnose() { if (isAmbiguous()) - SemaRef.DiagnoseAmbiguousLookup(*this); - else if (isClassLookup() && SemaRef.getLangOpts().AccessControl) - SemaRef.CheckLookupAccess(*this); + getSema().DiagnoseAmbiguousLookup(*this); + else if (isClassLookup() && getSema().getLangOpts().AccessControl) + getSema().CheckLookupAccess(*this); } void setAmbiguous(AmbiguityKind AK) { @@ -657,7 +664,7 @@ private: QualType BaseObjectType; // Parameters. - Sema &SemaRef; + Sema *SemaPtr; DeclarationNameInfo NameInfo; SourceRange NameContextRange; Sema::LookupNameKind LookupKind; diff --git a/include/clang/Sema/LoopHint.h b/include/clang/Sema/LoopHint.h index d4b985df544c..c8b2ee845e59 100644 --- a/include/clang/Sema/LoopHint.h +++ b/include/clang/Sema/LoopHint.h @@ -26,13 +26,18 @@ struct LoopHint { // hints. IdentifierLoc *PragmaNameLoc; // Name of the loop hint. Examples: "unroll", "vectorize". In the - // "#pragma unroll" case, this is identical to PragmaNameLoc. + // "#pragma unroll" and "#pragma nounroll" cases, this is identical to + // PragmaNameLoc. IdentifierLoc *OptionLoc; - // Identifier for the hint argument. If null, then the hint has no argument - // such as for "#pragma unroll". - IdentifierLoc *ValueLoc; + // Identifier for the hint state argument. If null, then the state is + // default value such as for "#pragma unroll". + IdentifierLoc *StateLoc; // Expression for the hint argument if it exists, null otherwise. Expr *ValueExpr; + + LoopHint() + : PragmaNameLoc(nullptr), OptionLoc(nullptr), StateLoc(nullptr), + ValueExpr(nullptr) {} }; } // end namespace clang diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 7860b6da06a0..f06d19629a30 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -10,8 +10,8 @@ // This file defines ExternalSemaSource interface, dispatching to all clients // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H -#define LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H +#ifndef LLVM_CLANG_SEMA_MULTIPLEXEXTERNALSEMASOURCE_H +#define LLVM_CLANG_SEMA_MULTIPLEXEXTERNALSEMASOURCE_H #include "clang/Sema/ExternalSemaSource.h" #include "clang/Sema/Weak.h" @@ -282,6 +282,15 @@ public: /// introduce the same declarations repeatedly. void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl*> &Decls) override; + /// \brief Read the set of potentially unused typedefs known to the source. + /// + /// The external source should append its own potentially unused local + /// typedefs to the given vector of declarations. Note that this routine may + /// be invoked multiple times; the external source should take care not to + /// introduce the same declarations repeatedly. + void ReadUnusedLocalTypedefNameCandidates( + llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override; + /// \brief Read the set of locally-scoped extern "C" declarations known to the /// external Sema source. /// @@ -368,4 +377,4 @@ public: } // end namespace clang -#endif // LLVM_CLANG_SEMA_MULTIPLEX_EXTERNAL_SEMA_SOURCE_H +#endif diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h index 20033567dff9..b618e38f88cd 100644 --- a/include/clang/Sema/ObjCMethodList.h +++ b/include/clang/Sema/ObjCMethodList.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H -#define LLVM_CLANG_SEMA_OBJC_METHOD_LIST_H +#ifndef LLVM_CLANG_SEMA_OBJCMETHODLIST_H +#define LLVM_CLANG_SEMA_OBJCMETHODLIST_H #include "llvm/ADT/PointerIntPair.h" @@ -20,20 +20,37 @@ namespace clang { class ObjCMethodDecl; -/// ObjCMethodList - a linked list of methods with different signatures. +/// \brief a linked list of methods with the same selector name but different +/// signatures. struct ObjCMethodList { - ObjCMethodDecl *Method; + // NOTE: If you add any members to this struct, make sure to serialize them. + /// \brief If there is more than one decl with this signature. + llvm::PointerIntPair<ObjCMethodDecl *, 1> MethodAndHasMoreThanOneDecl; /// \brief The next list object and 2 bits for extra info. llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits; - ObjCMethodList() : Method(nullptr) { } - ObjCMethodList(ObjCMethodDecl *M, ObjCMethodList *C) - : Method(M), NextAndExtraBits(C, 0) { } + ObjCMethodList() { } + ObjCMethodList(ObjCMethodDecl *M) + : MethodAndHasMoreThanOneDecl(M, 0) {} ObjCMethodList *getNext() const { return NextAndExtraBits.getPointer(); } unsigned getBits() const { return NextAndExtraBits.getInt(); } void setNext(ObjCMethodList *L) { NextAndExtraBits.setPointer(L); } void setBits(unsigned B) { NextAndExtraBits.setInt(B); } + + ObjCMethodDecl *getMethod() const { + return MethodAndHasMoreThanOneDecl.getPointer(); + } + void setMethod(ObjCMethodDecl *M) { + return MethodAndHasMoreThanOneDecl.setPointer(M); + } + + bool hasMoreThanOneDecl() const { + return MethodAndHasMoreThanOneDecl.getInt(); + } + void setHasMoreThanOneDecl(bool B) { + return MethodAndHasMoreThanOneDecl.setInt(B); + } }; } diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 7c221a2336ce..4447db2b3ef0 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -25,6 +25,7 @@ #include "clang/Sema/TemplateDeduction.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" namespace clang { @@ -85,21 +86,6 @@ namespace clang { ICK_Num_Conversion_Kinds ///< The number of conversion kinds }; - /// ImplicitConversionCategory - The category of an implicit - /// conversion kind. The enumerator values match with Table 9 of - /// (C++ 13.3.3.1.1) and are listed such that better conversion - /// categories have smaller values. - enum ImplicitConversionCategory { - ICC_Identity = 0, ///< Identity - ICC_Lvalue_Transformation, ///< Lvalue transformation - ICC_Qualification_Adjustment, ///< Qualification adjustment - ICC_Promotion, ///< Promotion - ICC_Conversion ///< Conversion - }; - - ImplicitConversionCategory - GetConversionCategory(ImplicitConversionKind Kind); - /// ImplicitConversionRank - The rank of an implicit conversion /// kind. The enumerator values match with Table 9 of (C++ /// 13.3.3.1.1) and are listed such that better conversion ranks @@ -567,6 +553,17 @@ namespace clang { /// conversion. ovl_fail_trivial_conversion, + /// This conversion candidate was not considered because it is + /// an illegal instantiation of a constructor temploid: it is + /// callable with one argument, we only have one argument, and + /// its first parameter type is exactly the type of the class. + /// + /// Defining such a constructor directly is illegal, and + /// template-argument deduction is supposed to ignore such + /// instantiations, but we can still get one with the right + /// kind of implicit instantiation. + ovl_fail_illegal_constructor, + /// This conversion candidate is not viable because its result /// type is not implicitly convertible to the desired type. ovl_fail_bad_final_conversion, @@ -718,7 +715,8 @@ namespace clang { CandidateSetKind Kind; unsigned NumInlineSequences; - char InlineSpace[16 * sizeof(ImplicitConversionSequence)]; + llvm::AlignedCharArray<llvm::AlignOf<ImplicitConversionSequence>::Alignment, + 16 * sizeof(ImplicitConversionSequence)> InlineSpace; OverloadCandidateSet(const OverloadCandidateSet &) LLVM_DELETED_FUNCTION; void operator=(const OverloadCandidateSet &) LLVM_DELETED_FUNCTION; @@ -735,8 +733,8 @@ namespace clang { /// \brief Determine when this overload candidate will be new to the /// overload set. - bool isNewCandidate(Decl *F) { - return Functions.insert(F->getCanonicalDecl()); + bool isNewCandidate(Decl *F) { + return Functions.insert(F->getCanonicalDecl()).second; } /// \brief Clear out all of the candidates. @@ -759,7 +757,7 @@ namespace clang { // available. if (NumConversions + NumInlineSequences <= 16) { ImplicitConversionSequence *I = - (ImplicitConversionSequence*)InlineSpace; + (ImplicitConversionSequence *)InlineSpace.buffer; C.Conversions = &I[NumInlineSequences]; NumInlineSequences += NumConversions; } else { diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/Sema/PrettyDeclStackTrace.h index c0c772dc5983..ca22e640deb4 100644 --- a/include/clang/Sema/PrettyDeclStackTrace.h +++ b/include/clang/Sema/PrettyDeclStackTrace.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H -#define LLVM_CLANG_SEMA_PRETTY_DECL_STACK_TRACE_H +#ifndef LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H +#define LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H #include "clang/Basic/SourceLocation.h" #include "llvm/Support/PrettyStackTrace.h" diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index 8e4e2ef4be21..97e447d1fd67 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -135,14 +135,6 @@ private: /// scopes seen as a component. unsigned short MSLocalManglingNumber; - /// \brief SEH __try blocks get uniquely numbered within a function. This - /// variable holds the index for an SEH try block. - short SEHTryIndex; - - /// \brief SEH __try blocks get uniquely numbered within a function. This - /// variable holds the next free index at a function's scope. - short SEHTryIndexPool; - /// PrototypeDepth - This is the number of function prototype scopes /// enclosing this scope, including this scope. unsigned short PrototypeDepth; @@ -155,7 +147,6 @@ private: /// pointer is non-null and points to it. This is used for label processing. Scope *FnParent; Scope *MSLocalManglingParent; - Scope *SEHTryParent; /// BreakParent/ContinueParent - This is a direct link to the innermost /// BreakScope/ContinueScope which contains the contents of this scope @@ -294,14 +285,6 @@ public: return 1; } - int getSEHTryIndex() { - return SEHTryIndex; - } - - int getSEHTryParentIndex() const { - return SEHTryParent ? SEHTryParent->SEHTryIndex : -1; - } - /// isDeclScope - Return true if this is the scope that the specified decl is /// declared in. bool isDeclScope(Decl *D) { @@ -317,6 +300,9 @@ public: return ErrorTrap.hasUnrecoverableErrorOccurred(); } + /// isFunctionScope() - Return true if this scope is a function scope. + bool isFunctionScope() const { return (getFlags() & Scope::FnScope); } + /// isClassScope - Return true if this scope is a class/struct/union scope. bool isClassScope() const { return (getFlags() & Scope::ClassScope); diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index 63427aaa4a75..d63b734a8dbf 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -12,9 +12,10 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_SCOPE_INFO_H -#define LLVM_CLANG_SEMA_SCOPE_INFO_H +#ifndef LLVM_CLANG_SEMA_SCOPEINFO_H +#define LLVM_CLANG_SEMA_SCOPEINFO_H +#include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/CapturedStmt.h" #include "clang/Basic/PartialDiagnostic.h" @@ -41,8 +42,6 @@ class SwitchStmt; class TemplateTypeParmDecl; class TemplateParameterList; class VarDecl; -class DeclRefExpr; -class MemberExpr; class ObjCIvarRefExpr; class ObjCPropertyRefExpr; class ObjCMessageExpr; @@ -145,6 +144,10 @@ public: /// current function scope. These diagnostics are vetted for reachability /// prior to being emitted. SmallVector<PossiblyUnreachableDiag, 4> PossiblyUnreachableDiags; + + /// \brief A list of parameters which have the nonnull attribute and are + /// modified in the function. + llvm::SmallPtrSet<const ParmVarDecl*, 8> ModifiedNonNullParams; public: /// Represents a simple identification of a weak object. @@ -187,8 +190,6 @@ public: /// Used to find the proper base profile for a given base expression. static BaseInfoTy getBaseInfo(const Expr *BaseE); - // For use in DenseMap. - friend class DenseMapInfo; inline WeakObjectProfileTy(); static inline WeakObjectProfileTy getSentinel(); @@ -381,7 +382,7 @@ public: /// capture (if this is a capture and not an init-capture). The expression /// is only required if we are capturing ByVal and the variable's type has /// a non-trivial copy constructor. - llvm::PointerIntPair<Expr*, 2, CaptureKind> InitExprAndCaptureKind; + llvm::PointerIntPair<void *, 2, CaptureKind> InitExprAndCaptureKind; /// \brief The source location at which the first capture occurred. SourceLocation Loc; @@ -413,10 +414,11 @@ public: return InitExprAndCaptureKind.getInt() == Cap_This; } bool isVariableCapture() const { - return InitExprAndCaptureKind.getInt() != Cap_This; + return InitExprAndCaptureKind.getInt() != Cap_This && !isVLATypeCapture(); } bool isCopyCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_ByCopy; + return InitExprAndCaptureKind.getInt() == Cap_ByCopy && + !isVLATypeCapture(); } bool isReferenceCapture() const { return InitExprAndCaptureKind.getInt() == Cap_ByRef; @@ -424,7 +426,11 @@ public: bool isBlockCapture() const { return InitExprAndCaptureKind.getInt() == Cap_Block; } - bool isNested() { return VarAndNested.getInt(); } + bool isVLATypeCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_ByCopy && + getVariable() == nullptr; + } + bool isNested() const { return VarAndNested.getInt(); } VarDecl *getVariable() const { return VarAndNested.getPointer(); @@ -443,7 +449,8 @@ public: QualType getCaptureType() const { return CaptureType; } Expr *getInitExpr() const { - return InitExprAndCaptureKind.getPointer(); + assert(!isVLATypeCapture() && "no init expression for type capture"); + return static_cast<Expr *>(InitExprAndCaptureKind.getPointer()); } }; @@ -478,6 +485,13 @@ public: CaptureMap[Var] = Captures.size(); } + void addVLATypeCapture(SourceLocation Loc, QualType CaptureType) { + Captures.push_back(Capture(/*Var*/ nullptr, /*isBlock*/ false, + /*isByref*/ false, /*isNested*/ false, Loc, + /*EllipsisLoc*/ SourceLocation(), CaptureType, + /*Cpy*/ nullptr)); + } + void addThisCapture(bool isNested, SourceLocation Loc, QualType CaptureType, Expr *Cpy); @@ -494,7 +508,10 @@ public: bool isCaptured(VarDecl *Var) const { return CaptureMap.count(Var); } - + + /// \brief Determine whether the given variable-array type has been captured. + bool isVLATypeCaptured(const VariableArrayType *VAT) const; + /// \brief Retrieve the capture of the given variable, if it has been /// captured already. Capture &getCapture(VarDecl *Var) { diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index e254afdbadaa..74efa60c9366 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -129,7 +129,6 @@ namespace clang { class ModuleLoader; class MultiLevelTemplateArgumentList; class NamedDecl; - class NonNullAttr; class ObjCCategoryDecl; class ObjCCategoryImplDecl; class ObjCCompatibleAliasDecl; @@ -169,6 +168,7 @@ namespace clang { class TypedefDecl; class TypedefNameDecl; class TypeLoc; + class TypoCorrectionConsumer; class UnqualifiedId; class UnresolvedLookupExpr; class UnresolvedMemberExpr; @@ -390,6 +390,10 @@ public: /// \brief Set containing all declared private fields that are not used. NamedDeclSetType UnusedPrivateFields; + /// \brief Set containing all typedefs that are likely unused. + llvm::SmallSetVector<const TypedefNameDecl *, 4> + UnusedLocalTypedefNameCandidates; + typedef llvm::SmallPtrSet<const CXXRecordDecl*, 8> RecordDeclSetTy; /// PureVirtualClassDiagSet - a set of class declarations which we have @@ -454,12 +458,11 @@ public: /// cycle detection at the end of the TU. DelegatingCtorDeclsType DelegatingCtorDecls; - /// \brief All the overriding destructors seen during a class definition - /// (there could be multiple due to nested classes) that had their exception - /// spec checks delayed, plus the overridden destructor. - SmallVector<std::pair<const CXXDestructorDecl*, - const CXXDestructorDecl*>, 2> - DelayedDestructorExceptionSpecChecks; + /// \brief All the overriding functions seen during a class definition + /// that had their exception spec checks delayed, plus the overridden + /// function. + SmallVector<std::pair<const CXXMethodDecl*, const CXXMethodDecl*>, 2> + DelayedExceptionSpecChecks; /// \brief All the members seen during a class definition which were both /// explicitly defaulted and had explicitly-specified exception @@ -477,11 +480,16 @@ public: /// \brief Callback to the parser to parse templated functions when needed. typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT); + typedef void LateTemplateParserCleanupCB(void *P); LateTemplateParserCB *LateTemplateParser; + LateTemplateParserCleanupCB *LateTemplateParserCleanup; void *OpaqueParser; - void SetLateTemplateParser(LateTemplateParserCB *LTP, void *P) { + void SetLateTemplateParser(LateTemplateParserCB *LTP, + LateTemplateParserCleanupCB *LTPCleanup, + void *P) { LateTemplateParser = LTP; + LateTemplateParserCleanup = LTPCleanup; OpaqueParser = P; } @@ -684,7 +692,10 @@ public: /// \brief will hold 'respondsToSelector:' Selector RespondsToSelectorSel; - + + /// \brief counter for internal MS Asm label names. + unsigned MSAsmLabelNameCounter; + /// A flag to remember whether the implicit forms of operator new and delete /// have been declared. bool GlobalNewDeleteDeclared; @@ -745,6 +756,10 @@ public: /// this expression evaluation context. unsigned NumCleanupObjects; + /// \brief The number of typos encountered during this expression evaluation + /// context (i.e. the number of TypoExprs created). + unsigned NumTypos; + llvm::SmallPtrSet<Expr*, 2> SavedMaybeODRUseExprs; /// \brief The lambdas that are present within this context, if it @@ -778,6 +793,7 @@ public: bool IsDecltype) : Context(Context), ParentNeedsCleanups(ParentNeedsCleanups), IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), + NumTypos(0), ManglingContextDecl(ManglingContextDecl), MangleNumbering() { } /// \brief Retrieve the mangling numbering context, used to consistently @@ -1037,6 +1053,8 @@ public: /// \brief Retrieve the module loader associated with the preprocessor. ModuleLoader &getModuleLoader() const; + void emitAndClearUnusedLocalTypedefWarnings(); + void ActOnEndOfTranslationUnit(); void CheckDelegatingCtorCycles(); @@ -1181,7 +1199,7 @@ public: const FunctionProtoType *ResolveExceptionSpec(SourceLocation Loc, const FunctionProtoType *FPT); void UpdateExceptionSpec(FunctionDecl *FD, - const FunctionProtoType::ExtProtoInfo &EPI); + const FunctionProtoType::ExceptionSpecInfo &ESI); bool CheckSpecifiedExceptionType(QualType &T, const SourceRange &Range); bool CheckDistantExceptionSpec(QualType T); bool CheckEquivalentExceptionSpec(FunctionDecl *Old, FunctionDecl *New); @@ -1233,7 +1251,7 @@ public: static QualType getPrintable(QualType T) { return T; } static SourceRange getPrintable(SourceRange R) { return R; } static SourceRange getPrintable(SourceLocation L) { return L; } - static SourceRange getPrintable(Expr *E) { return E->getSourceRange(); } + static SourceRange getPrintable(const Expr *E) { return E->getSourceRange(); } static SourceRange getPrintable(TypeLoc TL) { return TL.getSourceRange();} template<typename T1> @@ -1381,7 +1399,10 @@ public: const CXXScopeSpec &SS, QualType T); QualType BuildTypeofExprType(Expr *E, SourceLocation Loc); - QualType BuildDecltypeType(Expr *E, SourceLocation Loc); + /// If AsUnevaluated is false, E is treated as though it were an evaluated + /// context, such as when building a type for decltype(auto). + QualType BuildDecltypeType(Expr *E, SourceLocation Loc, + bool AsUnevaluated = true); QualType BuildUnaryTransformType(QualType BaseType, UnaryTransformType::UTTKind UKind, SourceLocation Loc); @@ -1543,13 +1564,11 @@ public: /// expression. /// /// \param CCC The correction callback, if typo correction is desired. - NameClassification ClassifyName(Scope *S, - CXXScopeSpec &SS, - IdentifierInfo *&Name, - SourceLocation NameLoc, - const Token &NextToken, - bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = nullptr); + NameClassification + ClassifyName(Scope *S, CXXScopeSpec &SS, IdentifierInfo *&Name, + SourceLocation NameLoc, const Token &NextToken, + bool IsAddressOfOperand, + std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr); Decl *ActOnDeclarator(Scope *S, Declarator &D); @@ -1989,6 +2008,13 @@ public: int FirstArg, unsigned AttrSpellingListIndex); SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name, unsigned AttrSpellingListIndex); + AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range, + IdentifierInfo *Ident, + unsigned AttrSpellingListIndex); + MinSizeAttr *mergeMinSizeAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); + OptimizeNoneAttr *mergeOptimizeNoneAttr(Decl *D, SourceRange Range, + unsigned AttrSpellingListIndex); /// \brief Describes the kind of merge to perform for availability /// attributes (including "deprecated", "unavailable", and "availability"). @@ -2132,6 +2158,8 @@ public: }; ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, llvm::APSInt &Value, CCEKind CCE); + ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, + APValue &Value, CCEKind CCE); /// \brief Abstract base class used to perform a contextual implicit /// conversion from an expression to any type passing a filter. @@ -2562,9 +2590,30 @@ public: bool ConstThis, bool VolatileThis); + typedef std::function<void(const TypoCorrection &)> TypoDiagnosticGenerator; + typedef std::function<ExprResult(Sema &, TypoExpr *, TypoCorrection)> + TypoRecoveryCallback; + private: bool CppLookupName(LookupResult &R, Scope *S); + struct TypoExprState { + std::unique_ptr<TypoCorrectionConsumer> Consumer; + TypoDiagnosticGenerator DiagHandler; + TypoRecoveryCallback RecoveryHandler; + TypoExprState(); + TypoExprState(TypoExprState&& other) LLVM_NOEXCEPT; + TypoExprState& operator=(TypoExprState&& other) LLVM_NOEXCEPT; + }; + + /// \brief The set of unhandled TypoExprs and their associated state. + llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos; + + /// \brief Creates a new TypoExpr AST node. + TypoExpr *createDelayedTypo(std::unique_ptr<TypoCorrectionConsumer> TCC, + TypoDiagnosticGenerator TDG, + TypoRecoveryCallback TRC); + // \brief The set of known/encountered (unique, canonicalized) NamespaceDecls. // // The boolean value will be true to indicate that the namespace was loaded @@ -2575,7 +2624,24 @@ private: /// source. bool LoadedExternalKnownNamespaces; + /// \brief Helper for CorrectTypo and CorrectTypoDelayed used to create and + /// populate a new TypoCorrectionConsumer. Returns nullptr if typo correction + /// should be skipped entirely. + std::unique_ptr<TypoCorrectionConsumer> + makeTypoCorrectionConsumer(const DeclarationNameInfo &Typo, + Sema::LookupNameKind LookupKind, Scope *S, + CXXScopeSpec *SS, + std::unique_ptr<CorrectionCandidateCallback> CCC, + DeclContext *MemberContext, bool EnteringContext, + const ObjCObjectPointerType *OPT, + bool ErrorRecovery); + public: + const TypoExprState &getTypoExprState(TypoExpr *TE) const; + + /// \brief Clears the state of the given TypoExpr. + void clearDelayedTypo(TypoExpr *TE); + /// \brief Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. /// @@ -2590,12 +2656,15 @@ public: bool AllowBuiltinCreation = false); bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, bool InUnqualifiedLookup = false); + bool LookupQualifiedName(LookupResult &R, DeclContext *LookupCtx, + CXXScopeSpec &SS); bool LookupParsedName(LookupResult &R, Scope *S, CXXScopeSpec *SS, bool AllowBuiltinCreation = false, bool EnteringContext = false); ObjCProtocolDecl *LookupProtocol(IdentifierInfo *II, SourceLocation IdLoc, RedeclarationKind Redecl = NotForRedeclaration); + bool LookupInSuper(LookupResult &R, CXXRecordDecl *Class); void LookupOverloadedOperatorName(OverloadedOperatorKind Op, Scope *S, QualType T1, QualType T2, @@ -2645,13 +2714,35 @@ public: TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, Sema::LookupNameKind LookupKind, Scope *S, CXXScopeSpec *SS, - CorrectionCandidateCallback &CCC, + std::unique_ptr<CorrectionCandidateCallback> CCC, CorrectTypoKind Mode, DeclContext *MemberContext = nullptr, bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr, bool RecordFailure = true); + TypoExpr *CorrectTypoDelayed(const DeclarationNameInfo &Typo, + Sema::LookupNameKind LookupKind, Scope *S, + CXXScopeSpec *SS, + std::unique_ptr<CorrectionCandidateCallback> CCC, + TypoDiagnosticGenerator TDG, + TypoRecoveryCallback TRC, CorrectTypoKind Mode, + DeclContext *MemberContext = nullptr, + bool EnteringContext = false, + const ObjCObjectPointerType *OPT = nullptr); + + ExprResult + CorrectDelayedTyposInExpr(Expr *E, + llvm::function_ref<ExprResult(Expr *)> Filter = + [](Expr *E) -> ExprResult { return E; }); + + ExprResult + CorrectDelayedTyposInExpr(ExprResult ER, + llvm::function_ref<ExprResult(Expr *)> Filter = + [](Expr *E) -> ExprResult { return E; }) { + return ER.isInvalid() ? ER : CorrectDelayedTyposInExpr(ER.get(), Filter); + } + void diagnoseTypo(const TypoCorrection &Correction, const PartialDiagnostic &TypoDiag, bool ErrorRecovery = true); @@ -2694,6 +2785,12 @@ public: void checkUnusedDeclAttributes(Declarator &D); + /// Determine if type T is a valid subject for a nonnull and similar + /// attributes. By default, we look through references (the behavior used by + /// nonnull), but if the second parameter is true, then we treat a reference + /// type as valid. + bool isValidPointerAttrType(QualType T, bool RefOkay = false); + bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, const FunctionDecl *FD = nullptr); @@ -2872,12 +2969,27 @@ private: bool receiverIdOrClass, bool warn, bool instance); +public: + /// \brief - Returns instance or factory methods in global method pool for + /// given selector. If no such method or only one method found, function returns + /// false; otherwise, it returns true + bool CollectMultipleMethodsInGlobalPool(Selector Sel, + SmallVectorImpl<ObjCMethodDecl*>& Methods, + bool instance); + + bool AreMultipleMethodsInGlobalPool(Selector Sel, + bool instance); + +private: + /// \brief - Returns a selector which best matches given argument list or + /// nullptr if none could be found + ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args, + bool IsInstance); + + /// \brief Record the typo correction failure and return an empty correction. TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc, - bool RecordFailure = true, - bool IsUnqualifiedLookup = false) { - if (IsUnqualifiedLookup) - (void)UnqualifiedTyposCorrected[Typo]; + bool RecordFailure = true) { if (RecordFailure) TypoCorrectionFailures[Typo].insert(TypoLoc); return TypoCorrection(); @@ -2937,11 +3049,6 @@ public: public: FullExprArg(Sema &actions) : E(nullptr) { } - // FIXME: The const_cast here is ugly. RValue references would make this - // much nicer (or we could duplicate a bunch of the move semantics - // emulation code from Ownership.h). - FullExprArg(const FullExprArg& Other) : E(Other.E) {} - ExprResult release() { return E; } @@ -3001,6 +3108,18 @@ public: Sema &S; }; + /// An RAII helper that pops function a function scope on exit. + struct FunctionScopeRAII { + Sema &S; + bool Active; + FunctionScopeRAII(Sema &S) : S(S), Active(true) {} + ~FunctionScopeRAII() { + if (Active) + S.PopFunctionScopeInfo(); + } + void disable() { Active = false; } + }; + StmtResult ActOnDeclStmt(DeclGroupPtrTy Decl, SourceLocation StartLoc, SourceLocation EndLoc); @@ -3128,6 +3247,9 @@ public: ArrayRef<StringRef> Clobbers, ArrayRef<Expr*> Exprs, SourceLocation EndLoc); + LabelDecl *GetOrCreateMSAsmLabel(StringRef ExternalLabelName, + SourceLocation Location, + bool AlwaysCreate); VarDecl *BuildObjCExceptionDecl(TypeSourceInfo *TInfo, QualType ExceptionType, SourceLocation StartLoc, @@ -3169,9 +3291,9 @@ public: StmtResult ActOnSEHTryBlock(bool IsCXXTry, // try (true) or __try (false) ? SourceLocation TryLoc, Stmt *TryBlock, - Stmt *Handler, int HandlerIndex, - int HandlerParentIndex); - StmtResult ActOnSEHExceptBlock(SourceLocation Loc, Expr *FilterExpr, + Stmt *Handler); + StmtResult ActOnSEHExceptBlock(SourceLocation Loc, + Expr *FilterExpr, Stmt *Block); StmtResult ActOnSEHFinallyBlock(SourceLocation Loc, Stmt *Block); StmtResult ActOnSEHLeaveStmt(SourceLocation Loc, Scope *CurScope); @@ -3187,6 +3309,7 @@ public: /// DiagnoseUnusedExprResult - If the statement passed in is an expression /// whose result is unused, warn. void DiagnoseUnusedExprResult(const Stmt *S); + void DiagnoseUnusedNestedTypedefs(const RecordDecl *D); void DiagnoseUnusedDecl(const NamedDecl *ND); /// Emit \p DiagID if statement located on \p StmtLoc has a suspicious null @@ -3204,6 +3327,10 @@ public: void DiagnoseEmptyLoopBody(const Stmt *S, const Stmt *PossibleBody); + /// Warn if a value is moved to itself. + void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, + SourceLocation OpLoc); + ParsingDeclState PushParsingDeclaration(sema::DelayedDiagnosticPool &pool) { return DelayedDiagnostics.push(pool); } @@ -3228,8 +3355,6 @@ public: const ObjCPropertyDecl *ObjCProperty, bool ObjCPropertyAccess); - void HandleDelayedAvailabilityCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); - bool makeUnavailableInSystemHeader(SourceLocation loc, StringRef message); @@ -3271,7 +3396,8 @@ public: // needs to be delayed for some constant variables when we build one of the // named expressions. void MarkAnyDeclReferenced(SourceLocation Loc, Decl *D, bool OdrUse); - void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func); + void MarkFunctionReferenced(SourceLocation Loc, FunctionDecl *Func, + bool OdrUse = true); void MarkVariableReferenced(SourceLocation Loc, VarDecl *Var); void MarkDeclRefReferenced(DeclRefExpr *E); void MarkMemberReferenced(MemberExpr *E); @@ -3327,6 +3453,9 @@ public: TryCaptureKind Kind = TryCapture_Implicit, SourceLocation EllipsisLoc = SourceLocation()); + /// \brief Checks if the variable must be captured. + bool NeedToCaptureVariable(VarDecl *Var, SourceLocation Loc); + /// \brief Given a variable, determine the type that a reference to that /// variable will have in the given scope. QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); @@ -3359,12 +3488,11 @@ public: // Primary Expressions. SourceRange getExprRange(Expr *E) const; - ExprResult ActOnIdExpression(Scope *S, CXXScopeSpec &SS, - SourceLocation TemplateKWLoc, - UnqualifiedId &Id, - bool HasTrailingLParen, bool IsAddressOfOperand, - CorrectionCandidateCallback *CCC = nullptr, - bool IsInlineAsmIdentifier = false); + ExprResult ActOnIdExpression( + Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, + UnqualifiedId &Id, bool HasTrailingLParen, bool IsAddressOfOperand, + std::unique_ptr<CorrectionCandidateCallback> CCC = nullptr, + bool IsInlineAsmIdentifier = false, Token *KeywordReplacement = nullptr); void DecomposeUnqualifiedId(const UnqualifiedId &Id, TemplateArgumentListInfo &Buffer, @@ -3373,9 +3501,9 @@ public: bool DiagnoseEmptyLookup(Scope *S, CXXScopeSpec &SS, LookupResult &R, - CorrectionCandidateCallback &CCC, + std::unique_ptr<CorrectionCandidateCallback> CCC, TemplateArgumentListInfo *ExplicitTemplateArgs = nullptr, - ArrayRef<Expr *> Args = None); + ArrayRef<Expr *> Args = None, TypoExpr **Out = nullptr); ExprResult LookupInObjCMethod(LookupResult &LookUp, Scope *S, IdentifierInfo *II, @@ -3430,11 +3558,13 @@ public: ExprResult BuildDeclarationNameExpr(const CXXScopeSpec &SS, LookupResult &R, - bool NeedsADL); + bool NeedsADL, + bool AcceptInvalidDecl = false); ExprResult BuildDeclarationNameExpr( const CXXScopeSpec &SS, const DeclarationNameInfo &NameInfo, NamedDecl *D, NamedDecl *FoundD = nullptr, - const TemplateArgumentListInfo *TemplateArgs = nullptr); + const TemplateArgumentListInfo *TemplateArgs = nullptr, + bool AcceptInvalidDecl = false); ExprResult BuildLiteralOperatorCall(LookupResult &R, DeclarationNameInfo &SuffixInfo, @@ -3446,6 +3576,9 @@ public: PredefinedExpr::IdentType IT); ExprResult ActOnPredefinedExpr(SourceLocation Loc, tok::TokenKind Kind); ExprResult ActOnIntegerConstant(SourceLocation Loc, uint64_t Val); + + bool CheckLoopHintExpr(Expr *E, SourceLocation Loc); + ExprResult ActOnNumericConstant(const Token &Tok, Scope *UDLScope = nullptr); ExprResult ActOnCharacterConstant(const Token &Tok, Scope *UDLScope = nullptr); @@ -3629,6 +3762,10 @@ public: bool GNUSyntax, ExprResult Init); +private: + static BinaryOperatorKind ConvertTokenKindToBinaryOpcode(tok::TokenKind Kind); + +public: ExprResult ActOnBinOp(Scope *S, SourceLocation TokLoc, tok::TokenKind Kind, Expr *LHSExpr, Expr *RHSExpr); ExprResult BuildBinOp(Scope *S, SourceLocation OpLoc, @@ -3876,6 +4013,8 @@ public: bool IsStdInitListInitialization, bool RequiresZeroInit, unsigned ConstructKind, SourceRange ParenRange); + ExprResult BuildCXXDefaultInitExpr(SourceLocation Loc, FieldDecl *Field); + /// BuildCXXDefaultArgExpr - Creates a CXXDefaultArgExpr, instantiating /// the default expr if needed. ExprResult BuildCXXDefaultArgExpr(SourceLocation CallLoc, @@ -3934,24 +4073,20 @@ public: /// \brief Overwrite an EPI's exception specification with this /// computed exception specification. - void getEPI(FunctionProtoType::ExtProtoInfo &EPI) const { - EPI.ExceptionSpecType = getExceptionSpecType(); - if (EPI.ExceptionSpecType == EST_Dynamic) { - EPI.NumExceptions = size(); - EPI.Exceptions = data(); - } else if (EPI.ExceptionSpecType == EST_None) { + FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const { + FunctionProtoType::ExceptionSpecInfo ESI; + ESI.Type = getExceptionSpecType(); + if (ESI.Type == EST_Dynamic) { + ESI.Exceptions = Exceptions; + } else if (ESI.Type == EST_None) { /// C++11 [except.spec]p14: /// The exception-specification is noexcept(false) if the set of /// potential exceptions of the special member function contains "any" - EPI.ExceptionSpecType = EST_ComputedNoexcept; - EPI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), + ESI.Type = EST_ComputedNoexcept; + ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), tok::kw_false).get(); } - } - FunctionProtoType::ExtProtoInfo getEPI() const { - FunctionProtoType::ExtProtoInfo EPI; - getEPI(EPI); - return EPI; + return ESI; } }; @@ -3998,13 +4133,28 @@ public: void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD); /// \brief Check the given exception-specification and update the - /// extended prototype information with the results. - void checkExceptionSpecification(ExceptionSpecificationType EST, + /// exception specification information with the results. + void checkExceptionSpecification(bool IsTopLevel, + ExceptionSpecificationType EST, ArrayRef<ParsedType> DynamicExceptions, ArrayRef<SourceRange> DynamicExceptionRanges, Expr *NoexceptExpr, SmallVectorImpl<QualType> &Exceptions, - FunctionProtoType::ExtProtoInfo &EPI); + FunctionProtoType::ExceptionSpecInfo &ESI); + + /// \brief Determine if we're in a case where we need to (incorrectly) eagerly + /// parse an exception specification to work around a libstdc++ bug. + bool isLibstdcxxEagerExceptionSpecHack(const Declarator &D); + + /// \brief Add an exception-specification to the given member function + /// (or member function template). The exception-specification was parsed + /// after the method itself was declared. + void actOnDelayedExceptionSpecification(Decl *Method, + ExceptionSpecificationType EST, + SourceRange SpecificationRange, + ArrayRef<ParsedType> DynamicExceptions, + ArrayRef<SourceRange> DynamicExceptionRanges, + Expr *NoexceptExpr); /// \brief Determine if a special member function should have a deleted /// definition when it is defaulted. @@ -4206,6 +4356,17 @@ public: void *TyOrExpr, SourceLocation RParenLoc); + /// \brief Handle a C++1z fold-expression: ( expr op ... op expr ). + ExprResult ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, + tok::TokenKind Operator, + SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc); + ExprResult BuildCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, + BinaryOperatorKind Operator, + SourceLocation EllipsisLoc, Expr *RHS, + SourceLocation RParenLoc); + ExprResult BuildEmptyCXXFoldExpr(SourceLocation EllipsisLoc, + BinaryOperatorKind Operator); //// ActOnCXXThis - Parse 'this' pointer. ExprResult ActOnCXXThis(SourceLocation loc); @@ -4450,16 +4611,26 @@ public: /// \brief The parser has parsed a global nested-name-specifier '::'. /// - /// \param S The scope in which this nested-name-specifier occurs. - /// /// \param CCLoc The location of the '::'. /// /// \param SS The nested-name-specifier, which will be updated in-place /// to reflect the parsed nested-name-specifier. /// /// \returns true if an error occurred, false otherwise. - bool ActOnCXXGlobalScopeSpecifier(Scope *S, SourceLocation CCLoc, - CXXScopeSpec &SS); + bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS); + + /// \brief The parser has parsed a '__super' nested-name-specifier. + /// + /// \param SuperLoc The location of the '__super' keyword. + /// + /// \param ColonColonLoc The location of the '::'. + /// + /// \param SS The nested-name-specifier, which will be updated in-place + /// to reflect the parsed nested-name-specifier. + /// + /// \returns true if an error occurred, false otherwise. + bool ActOnSuperScopeSpecifier(SourceLocation SuperLoc, + SourceLocation ColonColonLoc, CXXScopeSpec &SS); bool isAcceptableNestedNameSpecifier(const NamedDecl *SD); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); @@ -5038,6 +5209,10 @@ public: /// CheckOverrideControl - Check C++11 override control semantics. void CheckOverrideControl(NamedDecl *D); + + /// DiagnoseAbsenceOfOverrideControl - Diagnose if 'override' keyword was + /// not used in the declaration of an overriding method. + void DiagnoseAbsenceOfOverrideControl(NamedDecl *D); /// CheckForFunctionMarkedFinal - Checks whether a virtual member function /// overrides a virtual member function marked 'final', according to @@ -5582,6 +5757,10 @@ public: // C++ Variadic Templates (C++0x [temp.variadic]) //===--------------------------------------------------------------------===// + /// Determine whether an unexpanded parameter pack might be permitted in this + /// location. Useful for error recovery. + bool isUnexpandedParameterPackPermitted(); + /// \brief The context in which an unexpanded parameter pack is /// being diagnosed. /// @@ -6053,6 +6232,8 @@ public: bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); + TypeLoc getReturnTypeLoc(FunctionDecl *FD) const; + bool DeduceFunctionTypeFromReturnExpr(FunctionDecl *FD, SourceLocation ReturnLoc, Expr *&RetExpr, AutoType *AT); @@ -6512,17 +6693,6 @@ public: /// \brief The number of typos corrected by CorrectTypo. unsigned TyposCorrected; - typedef llvm::DenseMap<IdentifierInfo *, TypoCorrection> - UnqualifiedTyposCorrectedMap; - - /// \brief A cache containing the results of typo correction for unqualified - /// name lookup. - /// - /// The string is the string that we corrected to (which may be empty, if - /// there was no correction), while the boolean will be true when the - /// string represents a keyword. - UnqualifiedTyposCorrectedMap UnqualifiedTyposCorrected; - typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet; typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations; @@ -6548,6 +6718,31 @@ public: /// but have not yet been performed. std::deque<PendingImplicitInstantiation> PendingInstantiations; + class SavePendingInstantiationsAndVTableUsesRAII { + public: + SavePendingInstantiationsAndVTableUsesRAII(Sema &S): S(S) { + SavedPendingInstantiations.swap(S.PendingInstantiations); + SavedVTableUses.swap(S.VTableUses); + } + + ~SavePendingInstantiationsAndVTableUsesRAII() { + // Restore the set of pending vtables. + assert(S.VTableUses.empty() && + "VTableUses should be empty before it is discarded."); + S.VTableUses.swap(SavedVTableUses); + + // Restore the set of pending implicit instantiations. + assert(S.PendingInstantiations.empty() && + "PendingInstantiations should be empty before it is discarded."); + S.PendingInstantiations.swap(SavedPendingInstantiations); + } + + private: + Sema &S; + SmallVector<VTableUse, 16> SavedVTableUses; + std::deque<PendingImplicitInstantiation> SavedPendingInstantiations; + }; + /// \brief The queue of implicit template instantiations that are required /// and must be performed within the current local scope. /// @@ -6597,6 +6792,8 @@ public: DeclarationName Entity, CXXRecordDecl *ThisContext, unsigned ThisTypeQuals); + void SubstExceptionSpec(FunctionDecl *New, const FunctionProtoType *Proto, + const MultiLevelTemplateArgumentList &Args); ParmVarDecl *SubstParmVarDecl(ParmVarDecl *D, const MultiLevelTemplateArgumentList &TemplateArgs, int indexAdjustment, @@ -6656,6 +6853,10 @@ public: const MultiLevelTemplateArgumentList &TemplateArgs, TemplateSpecializationKind TSK); + bool InstantiateInClassInitializer( + SourceLocation PointOfInstantiation, FieldDecl *Instantiation, + FieldDecl *Pattern, const MultiLevelTemplateArgumentList &TemplateArgs); + struct LateInstantiatedAttribute { const Attr *TmplAttr; LocalInstantiationScope *Scope; @@ -7142,33 +7343,10 @@ public: PSK_CodeSeg, }; - enum PragmaSectionFlag : unsigned { - PSF_None = 0, - PSF_Read = 0x1, - PSF_Write = 0x2, - PSF_Execute = 0x4, - PSF_Implicit = 0x8, - PSF_Invalid = 0x80000000U, - }; - - struct SectionInfo { - DeclaratorDecl *Decl; - SourceLocation PragmaSectionLocation; - int SectionFlags; - SectionInfo() {} - SectionInfo(DeclaratorDecl *Decl, - SourceLocation PragmaSectionLocation, - int SectionFlags) - : Decl(Decl), - PragmaSectionLocation(PragmaSectionLocation), - SectionFlags(SectionFlags) {} - }; - - llvm::StringMap<SectionInfo> SectionInfos; - bool UnifySection(const StringRef &SectionName, + bool UnifySection(StringRef SectionName, int SectionFlags, DeclaratorDecl *TheDecl); - bool UnifySection(const StringRef &SectionName, + bool UnifySection(StringRef SectionName, int SectionFlags, SourceLocation PragmaSectionLocation); @@ -7283,6 +7461,16 @@ public: void AddAlignedAttr(SourceRange AttrRange, Decl *D, TypeSourceInfo *T, unsigned SpellingListIndex, bool IsPackExpansion); + /// AddAssumeAlignedAttr - Adds an assume_aligned attribute to a particular + /// declaration. + void AddAssumeAlignedAttr(SourceRange AttrRange, Decl *D, Expr *E, Expr *OE, + unsigned SpellingListIndex); + + /// AddAlignValueAttr - Adds an align_value attribute to a particular + /// declaration. + void AddAlignValueAttr(SourceRange AttrRange, Decl *D, Expr *E, + unsigned SpellingListIndex); + // OpenMP directives and clauses. private: void *VarDataSharingAttributesStack; @@ -7291,6 +7479,10 @@ private: void DestroyDataSharingAttributesStack(); ExprResult VerifyPositiveIntegerConstantInClause(Expr *Op, OpenMPClauseKind CKind); + /// \brief Checks if the specified variable is used in one of the private + /// clauses in OpenMP constructs. + bool IsOpenMPCapturedVar(VarDecl *VD); + public: ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op); @@ -7342,6 +7534,12 @@ public: ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); + /// \brief Called on well-formed '\#pragma omp for simd' after parsing + /// of the associated statement. + StmtResult ActOnOpenMPForSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp sections' after parsing /// of the associated statement. StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, @@ -7371,6 +7569,12 @@ public: ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc, llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); + /// \brief Called on well-formed '\#pragma omp parallel for simd' after + /// parsing of the associated statement. + StmtResult ActOnOpenMPParallelForSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA); /// \brief Called on well-formed '\#pragma omp parallel sections' after /// parsing of the associated statement. StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, @@ -7395,6 +7599,25 @@ public: StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp ordered' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPOrderedDirective(Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp atomic' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp target' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTargetDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed '\#pragma omp teams' after parsing of the + /// associated statement. + StmtResult ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc); OMPClause *ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, @@ -7473,6 +7696,21 @@ public: /// \brief Called on well-formed 'mergeable' clause. OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc); + /// \brief Called on well-formed 'read' clause. + OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'write' clause. + OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'update' clause. + OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'capture' clause. + OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc, + SourceLocation EndLoc); + /// \brief Called on well-formed 'seq_cst' clause. + OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc, + SourceLocation EndLoc); OMPClause * ActOnOpenMPVarListClause(OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, @@ -7615,6 +7853,7 @@ public: VAK_Valid, VAK_ValidInCXX11, VAK_Undefined, + VAK_MSVCUndefined, VAK_Invalid }; @@ -7732,6 +7971,12 @@ public: Expr *SrcExpr, AssignmentAction Action, bool *Complained = nullptr); + /// IsValueInFlagEnum - Determine if a value is allowed as part of a flag + /// enum. If AllowMask is true, then we also allow the complement of a valid + /// value, to be used as a mask. + bool IsValueInFlagEnum(const EnumDecl *ED, const llvm::APInt &Val, + bool AllowMask) const; + /// DiagnoseAssignmentEnum - Warn if assignment to enum is a constant /// integer not in the range of enum values. void DiagnoseAssignmentEnum(QualType DstType, QualType SrcType, @@ -7976,6 +8221,7 @@ public: ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, + SourceRange RecRange, QualType &ReturnType, ExprValueKind &VK); /// \brief Determine the result of a message send expression based on @@ -8067,18 +8313,30 @@ public: CFT_Device, CFT_Global, CFT_Host, - CFT_HostDevice + CFT_HostDevice, + CFT_InvalidTarget }; CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D); - bool CheckCUDATarget(CUDAFunctionTarget CallerTarget, - CUDAFunctionTarget CalleeTarget); - - bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee) { - return CheckCUDATarget(IdentifyCUDATarget(Caller), - IdentifyCUDATarget(Callee)); - } + bool CheckCUDATarget(const FunctionDecl *Caller, const FunctionDecl *Callee); + + /// Given a implicit special member, infer its CUDA target from the + /// calls it needs to make to underlying base/field special members. + /// \param ClassDecl the class for which the member is being created. + /// \param CSM the kind of special member. + /// \param MemberDecl the special member itself. + /// \param ConstRHS true if this is a copy operation with a const object on + /// its RHS. + /// \param Diagnose true if this call should emit diagnostics. + /// \return true if there was an error inferring. + /// The result of this call is implicit CUDA target attribute(s) attached to + /// the member declaration. + bool inferCUDATargetForImplicitSpecialMember(CXXRecordDecl *ClassDecl, + CXXSpecialMember CSM, + CXXMethodDecl *MemberDecl, + bool ConstRHS, + bool Diagnose); /// \name Code completion //@{ @@ -8269,7 +8527,8 @@ private: bool CheckObjCString(Expr *Arg); - ExprResult CheckBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + ExprResult CheckBuiltinFunctionCall(FunctionDecl *FDecl, + unsigned BuiltinID, CallExpr *TheCall); bool CheckARMBuiltinExclusiveCall(unsigned BuiltinID, CallExpr *TheCall, unsigned MaxWidth); @@ -8295,6 +8554,7 @@ public: private: bool SemaBuiltinPrefetch(CallExpr *TheCall); bool SemaBuiltinAssume(CallExpr *TheCall); + bool SemaBuiltinAssumeAligned(CallExpr *TheCall); bool SemaBuiltinLongjmp(CallExpr *TheCall); ExprResult SemaBuiltinAtomicOverloaded(ExprResult TheCallResult); ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, @@ -8322,6 +8582,10 @@ public: FormatStringType Type, bool inFunctionCall, VariadicCallType CallType, llvm::SmallBitVector &CheckedVarArgs); + + bool FormatStringHasSArg(const StringLiteral *FExpr); + + bool GetFormatNSStringIdx(const FormatAttr *Format, unsigned &Idx); private: bool CheckFormatArguments(const FormatAttr *Format, @@ -8359,6 +8623,7 @@ private: void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); + void CheckBoolLikeConversion(Expr *E, SourceLocation CC); void CheckForIntOverflow(Expr *E); void CheckUnsequencedOperations(Expr *E); diff --git a/include/clang/Sema/SemaDiagnostic.h b/include/clang/Sema/SemaDiagnostic.h index fdf959305151..7740d5e29c00 100644 --- a/include/clang/Sema/SemaDiagnostic.h +++ b/include/clang/Sema/SemaDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_DIAGNOSTICSEMA_H -#define LLVM_CLANG_DIAGNOSTICSEMA_H +#ifndef LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H +#define LLVM_CLANG_SEMA_SEMADIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/Sema/SemaFixItUtils.h b/include/clang/Sema/SemaFixItUtils.h index fffca6791454..343ccfb3d630 100644 --- a/include/clang/Sema/SemaFixItUtils.h +++ b/include/clang/Sema/SemaFixItUtils.h @@ -10,8 +10,8 @@ // This file defines helper classes for generation of Sema FixItHints. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_FIXITUTILS_H -#define LLVM_CLANG_SEMA_FIXITUTILS_H +#ifndef LLVM_CLANG_SEMA_SEMAFIXITUTILS_H +#define LLVM_CLANG_SEMA_SEMAFIXITUTILS_H #include "clang/AST/Expr.h" @@ -88,4 +88,4 @@ struct ConversionFixItGenerator { }; } // endof namespace clang -#endif // LLVM_CLANG_SEMA_FIXITUTILS_H +#endif diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index 9199b0fba2a5..045bacf21360 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -12,10 +12,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_SEMA_INTERNAL_H -#define LLVM_CLANG_SEMA_SEMA_INTERNAL_H +#ifndef LLVM_CLANG_SEMA_SEMAINTERNAL_H +#define LLVM_CLANG_SEMA_SEMAINTERNAL_H #include "clang/AST/ASTContext.h" +#include "clang/Sema/Lookup.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaDiagnostic.h" @@ -86,6 +87,213 @@ inline InheritableAttr *getDLLAttr(Decl *D) { return nullptr; } +class TypoCorrectionConsumer : public VisibleDeclConsumer { + typedef SmallVector<TypoCorrection, 1> TypoResultList; + typedef llvm::StringMap<TypoResultList> TypoResultsMap; + typedef std::map<unsigned, TypoResultsMap> TypoEditDistanceMap; + +public: + TypoCorrectionConsumer(Sema &SemaRef, + const DeclarationNameInfo &TypoName, + Sema::LookupNameKind LookupKind, + Scope *S, CXXScopeSpec *SS, + std::unique_ptr<CorrectionCandidateCallback> CCC, + DeclContext *MemberContext, + bool EnteringContext) + : Typo(TypoName.getName().getAsIdentifierInfo()), CurrentTCIndex(0), + SemaRef(SemaRef), S(S), + SS(SS ? llvm::make_unique<CXXScopeSpec>(*SS) : nullptr), + CorrectionValidator(std::move(CCC)), MemberContext(MemberContext), + Result(SemaRef, TypoName, LookupKind), + Namespaces(SemaRef.Context, SemaRef.CurContext, SS), + EnteringContext(EnteringContext), SearchNamespaces(false) { + Result.suppressDiagnostics(); + // Arrange for ValidatedCorrections[0] to always be an empty correction. + ValidatedCorrections.push_back(TypoCorrection()); + } + + bool includeHiddenDecls() const override { return true; } + + // Methods for adding potential corrections to the consumer. + void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, + bool InBaseClass) override; + void FoundName(StringRef Name); + void addKeywordResult(StringRef Keyword); + void addCorrection(TypoCorrection Correction); + + bool empty() const { + return CorrectionResults.empty() && ValidatedCorrections.size() == 1; + } + + /// \brief Return the list of TypoCorrections for the given identifier from + /// the set of corrections that have the closest edit distance, if any. + TypoResultList &operator[](StringRef Name) { + return CorrectionResults.begin()->second[Name]; + } + + /// \brief Return the edit distance of the corrections that have the + /// closest/best edit distance from the original typop. + unsigned getBestEditDistance(bool Normalized) { + if (CorrectionResults.empty()) + return (std::numeric_limits<unsigned>::max)(); + + unsigned BestED = CorrectionResults.begin()->first; + return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED; + } + + /// \brief Set-up method to add to the consumer the set of namespaces to use + /// in performing corrections to nested name specifiers. This method also + /// implicitly adds all of the known classes in the current AST context to the + /// to the consumer for correcting nested name specifiers. + void + addNamespaces(const llvm::MapVector<NamespaceDecl *, bool> &KnownNamespaces); + + /// \brief Return the next typo correction that passes all internal filters + /// and is deemed valid by the consumer's CorrectionCandidateCallback, + /// starting with the corrections that have the closest edit distance. An + /// empty TypoCorrection is returned once no more viable corrections remain + /// in the consumer. + const TypoCorrection &getNextCorrection(); + + /// \brief Get the last correction returned by getNextCorrection(). + const TypoCorrection &getCurrentCorrection() { + return CurrentTCIndex < ValidatedCorrections.size() + ? ValidatedCorrections[CurrentTCIndex] + : ValidatedCorrections[0]; // The empty correction. + } + + /// \brief Return the next typo correction like getNextCorrection, but keep + /// the internal state pointed to the current correction (i.e. the next time + /// getNextCorrection is called, it will return the same correction returned + /// by peekNextcorrection). + const TypoCorrection &peekNextCorrection() { + auto Current = CurrentTCIndex; + const TypoCorrection &TC = getNextCorrection(); + CurrentTCIndex = Current; + return TC; + } + + /// \brief Reset the consumer's position in the stream of viable corrections + /// (i.e. getNextCorrection() will return each of the previously returned + /// corrections in order before returning any new corrections). + void resetCorrectionStream() { + CurrentTCIndex = 0; + } + + /// \brief Return whether the end of the stream of corrections has been + /// reached. + bool finished() { + return CorrectionResults.empty() && + CurrentTCIndex >= ValidatedCorrections.size(); + } + + ASTContext &getContext() const { return SemaRef.Context; } + const LookupResult &getLookupResult() const { return Result; } + + bool isAddressOfOperand() const { return CorrectionValidator->IsAddressOfOperand; } + const CXXScopeSpec *getSS() const { return SS.get(); } + Scope *getScope() const { return S; } + +private: + class NamespaceSpecifierSet { + struct SpecifierInfo { + DeclContext* DeclCtx; + NestedNameSpecifier* NameSpecifier; + unsigned EditDistance; + }; + + typedef SmallVector<DeclContext*, 4> DeclContextList; + typedef SmallVector<SpecifierInfo, 16> SpecifierInfoList; + + ASTContext &Context; + DeclContextList CurContextChain; + std::string CurNameSpecifier; + SmallVector<const IdentifierInfo*, 4> CurContextIdentifiers; + SmallVector<const IdentifierInfo*, 4> CurNameSpecifierIdentifiers; + bool isSorted; + + SpecifierInfoList Specifiers; + llvm::SmallSetVector<unsigned, 4> Distances; + llvm::DenseMap<unsigned, SpecifierInfoList> DistanceMap; + + /// \brief Helper for building the list of DeclContexts between the current + /// context and the top of the translation unit + static DeclContextList buildContextChain(DeclContext *Start); + + void sortNamespaces(); + + unsigned buildNestedNameSpecifier(DeclContextList &DeclChain, + NestedNameSpecifier *&NNS); + + public: + NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, + CXXScopeSpec *CurScopeSpec); + + /// \brief Add the DeclContext (a namespace or record) to the set, computing + /// the corresponding NestedNameSpecifier and its distance in the process. + void addNameSpecifier(DeclContext *Ctx); + + typedef SpecifierInfoList::iterator iterator; + iterator begin() { + if (!isSorted) sortNamespaces(); + return Specifiers.begin(); + } + iterator end() { return Specifiers.end(); } + }; + + void addName(StringRef Name, NamedDecl *ND, + NestedNameSpecifier *NNS = nullptr, bool isKeyword = false); + + /// \brief Find any visible decls for the given typo correction candidate. + /// If none are found, it to the set of candidates for which qualified lookups + /// will be performed to find possible nested name specifier changes. + bool resolveCorrection(TypoCorrection &Candidate); + + /// \brief Perform qualified lookups on the queued set of typo correction + /// candidates and add the nested name specifier changes to each candidate if + /// a lookup succeeds (at which point the candidate will be returned to the + /// main pool of potential corrections). + void performQualifiedLookups(); + + /// \brief The name written that is a typo in the source. + IdentifierInfo *Typo; + + /// \brief The results found that have the smallest edit distance + /// found (so far) with the typo name. + /// + /// The pointer value being set to the current DeclContext indicates + /// whether there is a keyword with this name. + TypoEditDistanceMap CorrectionResults; + + SmallVector<TypoCorrection, 4> ValidatedCorrections; + size_t CurrentTCIndex; + + Sema &SemaRef; + Scope *S; + std::unique_ptr<CXXScopeSpec> SS; + std::unique_ptr<CorrectionCandidateCallback> CorrectionValidator; + DeclContext *MemberContext; + LookupResult Result; + NamespaceSpecifierSet Namespaces; + SmallVector<TypoCorrection, 2> QualifiedResults; + bool EnteringContext; + bool SearchNamespaces; +}; + +inline Sema::TypoExprState::TypoExprState() {} + +inline Sema::TypoExprState::TypoExprState(TypoExprState &&other) LLVM_NOEXCEPT { + *this = std::move(other); } +inline Sema::TypoExprState &Sema::TypoExprState::operator=( + Sema::TypoExprState &&other) LLVM_NOEXCEPT { + Consumer = std::move(other.Consumer); + DiagHandler = std::move(other.DiagHandler); + RecoveryHandler = std::move(other.RecoveryHandler); + return *this; +} + +} // end namespace clang + #endif diff --git a/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h index f6367505f866..d043e2c459b3 100644 --- a/include/clang/Sema/SemaLambda.h +++ b/include/clang/Sema/SemaLambda.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_LAMBDA_H -#define LLVM_CLANG_SEMA_LAMBDA_H +#ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H +#define LLVM_CLANG_SEMA_SEMALAMBDA_H #include "clang/AST/ASTLambda.h" #include "clang/Sema/ScopeInfo.h" namespace clang { @@ -33,4 +33,4 @@ Optional<unsigned> getStackIndexOfNearestEnclosingCaptureCapableLambda( } // clang -#endif // LLVM_CLANG_SEMA_LAMBDA_H +#endif diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index 2c2c36d30be3..8338d975752c 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -10,8 +10,8 @@ // routines. // //===----------------------------------------------------------------------===/ -#ifndef LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H -#define LLVM_CLANG_SEMA_TEMPLATE_DEDUCTION_H +#ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H +#define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H #include "clang/AST/DeclTemplate.h" #include "clang/Basic/PartialDiagnostic.h" diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index 6cab59c93efc..922d0ffa1142 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -17,6 +17,7 @@ #include "clang/AST/DeclCXX.h" #include "clang/Sema/DeclSpec.h" +#include "clang/Sema/Ownership.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -198,10 +199,9 @@ public: void setCorrectionRange(CXXScopeSpec *SS, const DeclarationNameInfo &TypoName) { - CorrectionRange.setBegin(ForceSpecifierReplacement && SS && !SS->isEmpty() - ? SS->getBeginLoc() - : TypoName.getLoc()); - CorrectionRange.setEnd(TypoName.getLoc()); + CorrectionRange = TypoName.getSourceRange(); + if (ForceSpecifierReplacement && SS && !SS->isEmpty()) + CorrectionRange.setBegin(SS->getBeginLoc()); } SourceRange getCorrectionRange() const { @@ -247,11 +247,13 @@ class CorrectionCandidateCallback { public: static const unsigned InvalidDistance = TypoCorrection::InvalidDistance; - CorrectionCandidateCallback() + explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, + NestedNameSpecifier *TypoNNS = nullptr) : WantTypeSpecifiers(true), WantExpressionKeywords(true), - WantCXXNamedCasts(true), WantRemainingKeywords(true), - WantObjCSuper(false), IsObjCIvarLookup(false), - IsAddressOfOperand(false) {} + WantCXXNamedCasts(true), WantFunctionLikeCasts(true), + WantRemainingKeywords(true), WantObjCSuper(false), + IsObjCIvarLookup(false), IsAddressOfOperand(false), Typo(Typo), + TypoNNS(TypoNNS) {} virtual ~CorrectionCandidateCallback() {} @@ -274,20 +276,39 @@ public: /// the default RankCandidate returns either 0 or InvalidDistance depending /// whether ValidateCandidate returns true or false. virtual unsigned RankCandidate(const TypoCorrection &candidate) { - return ValidateCandidate(candidate) ? 0 : InvalidDistance; + return (!MatchesTypo(candidate) && ValidateCandidate(candidate)) + ? 0 + : InvalidDistance; } - // Flags for context-dependent keywords. + void setTypoName(IdentifierInfo *II) { Typo = II; } + void setTypoNNS(NestedNameSpecifier *NNS) { TypoNNS = NNS; } + + // Flags for context-dependent keywords. WantFunctionLikeCasts is only + // used/meaningful when WantCXXNamedCasts is false. // TODO: Expand these to apply to non-keywords or possibly remove them. bool WantTypeSpecifiers; bool WantExpressionKeywords; bool WantCXXNamedCasts; + bool WantFunctionLikeCasts; bool WantRemainingKeywords; bool WantObjCSuper; // Temporary hack for the one case where a CorrectTypoContext enum is used // when looking up results. bool IsObjCIvarLookup; bool IsAddressOfOperand; + +protected: + bool MatchesTypo(const TypoCorrection &candidate) { + return Typo && candidate.isResolved() && !candidate.requiresImport() && + candidate.getCorrectionAsIdentifierInfo() == Typo && + // FIXME: This probably does not return true when both + // NestedNameSpecifiers have the same textual representation. + candidate.getCorrectionSpecifier() == TypoNNS; + } + + IdentifierInfo *Typo; + NestedNameSpecifier *TypoNNS; }; /// @brief Simple template class for restricting typo correction candidates @@ -325,6 +346,7 @@ public: WantTypeSpecifiers = false; WantExpressionKeywords = false; WantCXXNamedCasts = false; + WantFunctionLikeCasts = false; WantRemainingKeywords = false; } diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 7ae1977d3e71..3874f3a64c1b 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -14,8 +14,8 @@ // respective lists. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_PCHBITCODES_H -#define LLVM_CLANG_FRONTEND_PCHBITCODES_H +#ifndef LLVM_CLANG_SERIALIZATION_ASTBITCODES_H +#define LLVM_CLANG_SERIALIZATION_ASTBITCODES_H #include "clang/AST/Type.h" #include "llvm/ADT/DenseMap.h" @@ -35,7 +35,7 @@ namespace clang { /// Version 4 of AST files also requires that the version control branch and /// revision match exactly, since there is no backward compatibility of /// AST files at this time. - const unsigned VERSION_MAJOR = 5; + const unsigned VERSION_MAJOR = 6; /// \brief AST file minor version number supported by this version of /// Clang. @@ -288,7 +288,13 @@ namespace clang { /// \brief Record code for the module map file that was used to build this /// AST file. - MODULE_MAP_FILE = 14 + MODULE_MAP_FILE = 14, + + /// \brief Record code for the signature that identifiers this AST file. + SIGNATURE = 15, + + /// \brief Record code for the module build directory. + MODULE_DIRECTORY = 16, }; /// \brief Record types that occur within the input-files block @@ -545,7 +551,10 @@ namespace clang { LATE_PARSED_TEMPLATE = 50, /// \brief Record code for \#pragma optimize options. - OPTIMIZE_PRAGMA_OPTIONS = 51 + OPTIMIZE_PRAGMA_OPTIONS = 51, + + /// \brief Record code for potentially unused local typedef names. + UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52, }; /// \brief Record types used within a source manager block. @@ -635,7 +644,13 @@ namespace clang { /// \brief Specifies a conflict with another module. SUBMODULE_CONFLICT = 12, /// \brief Specifies a header that is private to this submodule. - SUBMODULE_PRIVATE_HEADER = 13 + SUBMODULE_PRIVATE_HEADER = 13, + /// \brief Specifies a header that is part of the module but must be + /// textually included. + SUBMODULE_TEXTUAL_HEADER = 14, + /// \brief Specifies a header that is private to this submodule but + /// must be textually included. + SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15, }; /// \brief Record types used within a comments block. @@ -759,9 +774,6 @@ namespace clang { /// NUM_PREDEF_TYPE_IDs. const unsigned NUM_PREDEF_TYPE_IDS = 100; - /// \brief The number of allowed abbreviations in bits - const unsigned NUM_ALLOWED_ABBREVS_SIZE = 4; - /// \brief Record codes for each kind of type. /// /// These constants describe the type records that can occur within a @@ -1323,7 +1335,8 @@ namespace clang { EXPR_SUBST_NON_TYPE_TEMPLATE_PARM_PACK,// SubstNonTypeTemplateParmPackExpr EXPR_FUNCTION_PARM_PACK, // FunctionParmPackExpr EXPR_MATERIALIZE_TEMPORARY, // MaterializeTemporaryExpr - + EXPR_CXX_FOLD, // CXXFoldExpr + // CUDA EXPR_CUDA_KERNEL_CALL, // CUDAKernelCallExpr @@ -1339,22 +1352,28 @@ namespace clang { STMT_SEH_FINALLY, // SEHFinallyStmt STMT_SEH_TRY, // SEHTryStmt - // OpenMP drectives + // OpenMP directives STMT_OMP_PARALLEL_DIRECTIVE, STMT_OMP_SIMD_DIRECTIVE, STMT_OMP_FOR_DIRECTIVE, + STMT_OMP_FOR_SIMD_DIRECTIVE, STMT_OMP_SECTIONS_DIRECTIVE, STMT_OMP_SECTION_DIRECTIVE, STMT_OMP_SINGLE_DIRECTIVE, STMT_OMP_MASTER_DIRECTIVE, STMT_OMP_CRITICAL_DIRECTIVE, STMT_OMP_PARALLEL_FOR_DIRECTIVE, + STMT_OMP_PARALLEL_FOR_SIMD_DIRECTIVE, STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE, STMT_OMP_TASK_DIRECTIVE, STMT_OMP_TASKYIELD_DIRECTIVE, STMT_OMP_BARRIER_DIRECTIVE, STMT_OMP_TASKWAIT_DIRECTIVE, STMT_OMP_FLUSH_DIRECTIVE, + STMT_OMP_ORDERED_DIRECTIVE, + STMT_OMP_ATOMIC_DIRECTIVE, + STMT_OMP_TARGET_DIRECTIVE, + STMT_OMP_TEAMS_DIRECTIVE, // ARC EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h index 180f554dafea..c24ccdcd4f56 100644 --- a/include/clang/Serialization/ASTDeserializationListener.h +++ b/include/clang/Serialization/ASTDeserializationListener.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H -#define LLVM_CLANG_FRONTEND_AST_DESERIALIZATION_LISTENER_H +#ifndef LLVM_CLANG_SERIALIZATION_ASTDESERIALIZATIONLISTENER_H +#define LLVM_CLANG_SERIALIZATION_ASTDESERIALIZATIONLISTENER_H #include "clang/Basic/IdentifierTable.h" #include "clang/Serialization/ASTBitCodes.h" diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 3f44440d4b9a..91ad34bd1ca1 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_AST_READER_H -#define LLVM_CLANG_FRONTEND_AST_READER_H +#ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_H +#define LLVM_CLANG_SERIALIZATION_ASTREADER_H #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclarationName.h" @@ -115,7 +115,8 @@ public: /// /// \returns true to indicate the options are invalid or false otherwise. virtual bool ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain) { + bool Complain, + bool AllowCompatibleDifferences) { return false; } @@ -193,6 +194,13 @@ public: bool isOverridden) { return true; } + + /// \brief Returns true if this \c ASTReaderListener wants to receive the + /// imports of the AST file via \c visitImport, false otherwise. + virtual bool needsImportVisitation() const { return false; } + /// \brief If needsImportVisitation returns \c true, this is called for each + /// AST file imported by this AST file. + virtual void visitImport(StringRef Filename) {} }; /// \brief Simple wrapper class for chaining listeners. @@ -202,13 +210,18 @@ class ChainedASTReaderListener : public ASTReaderListener { public: /// Takes ownership of \p First and \p Second. - ChainedASTReaderListener(ASTReaderListener *First, ASTReaderListener *Second) - : First(First), Second(Second) { } + ChainedASTReaderListener(std::unique_ptr<ASTReaderListener> First, + std::unique_ptr<ASTReaderListener> Second) + : First(std::move(First)), Second(std::move(Second)) {} + + std::unique_ptr<ASTReaderListener> takeFirst() { return std::move(First); } + std::unique_ptr<ASTReaderListener> takeSecond() { return std::move(Second); } bool ReadFullVersionInformation(StringRef FullVersion) override; void ReadModuleName(StringRef ModuleName) override; void ReadModuleMapFile(StringRef ModuleMapPath) override; - bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain) override; + bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, + bool AllowCompatibleDifferences) override; bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain) override; bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, @@ -240,8 +253,8 @@ public: PCHValidator(Preprocessor &PP, ASTReader &Reader) : PP(PP), Reader(Reader) {} - bool ReadLanguageOptions(const LangOptions &LangOpts, - bool Complain) override; + bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, + bool AllowCompatibleDifferences) override; bool ReadTargetOptions(const TargetOptions &TargetOpts, bool Complain) override; bool ReadDiagnosticOptions(IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, @@ -437,6 +450,16 @@ private: /// \brief Declarations that have been replaced in a later file in the chain. DeclReplacementMap ReplacedDecls; + /// \brief Declarations that have been imported and have typedef names for + /// linkage purposes. + llvm::DenseMap<std::pair<DeclContext*, IdentifierInfo*>, NamedDecl*> + ImportedTypedefNamesForLinkage; + + /// \brief Mergeable declaration contexts that have anonymous declarations + /// within them, and those anonymous declarations. + llvm::DenseMap<DeclContext*, llvm::SmallVector<NamedDecl*, 2>> + AnonymousDeclarationsForMerging; + struct FileDeclsInfo { ModuleFile *Mod; ArrayRef<serialization::LocalDeclID> Decls; @@ -748,6 +771,11 @@ private: /// at the end of the TU, in which case it directs CodeGen to emit the VTable. SmallVector<uint64_t, 16> DynamicClasses; + /// \brief The IDs of all potentially unused typedef names in the chain. + /// + /// Sema tracks these to emit warnings. + SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates; + /// \brief The IDs of the declarations Sema stores directly. /// /// Sema tracks a few important decls, such as namespace std, directly. @@ -1085,12 +1113,11 @@ private: serialization::InputFile getInputFile(ModuleFile &F, unsigned ID, bool Complain = true); - /// \brief Get a FileEntry out of stored-in-PCH filename, making sure we take - /// into account all the necessary relocations. - const FileEntry *getFileEntry(StringRef filename); - - void MaybeAddSystemRootToFilename(ModuleFile &M, std::string &Filename); +public: + void ResolveImportedPath(ModuleFile &M, std::string &Filename); + static void ResolveImportedPath(std::string &Filename, StringRef Prefix); +private: struct ImportedModule { ModuleFile *Mod; ModuleFile *ImportedBy; @@ -1106,20 +1133,25 @@ private: SourceLocation ImportLoc, ModuleFile *ImportedBy, SmallVectorImpl<ImportedModule> &Loaded, off_t ExpectedSize, time_t ExpectedModTime, + serialization::ASTFileSignature ExpectedSignature, unsigned ClientLoadCapabilities); ASTReadResult ReadControlBlock(ModuleFile &F, SmallVectorImpl<ImportedModule> &Loaded, const ModuleFile *ImportedBy, unsigned ClientLoadCapabilities); ASTReadResult ReadASTBlock(ModuleFile &F, unsigned ClientLoadCapabilities); - bool ParseLineTable(ModuleFile &F, SmallVectorImpl<uint64_t> &Record); + bool ParseLineTable(ModuleFile &F, const RecordData &Record); bool ReadSourceManagerBlock(ModuleFile &F); llvm::BitstreamCursor &SLocCursorForID(int ID); SourceLocation getImportLocation(ModuleFile *F); + ASTReadResult ReadModuleMapFileBlock(RecordData &Record, ModuleFile &F, + const ModuleFile *ImportedBy, + unsigned ClientLoadCapabilities); ASTReadResult ReadSubmoduleBlock(ModuleFile &F, unsigned ClientLoadCapabilities); static bool ParseLanguageOptions(const RecordData &Record, bool Complain, - ASTReaderListener &Listener); + ASTReaderListener &Listener, + bool AllowCompatibleDifferences); static bool ParseTargetOptions(const RecordData &Record, bool Complain, ASTReaderListener &Listener); static bool ParseDiagnosticOptions(const RecordData &Record, bool Complain, @@ -1142,7 +1174,7 @@ private: QualType readTypeRecord(unsigned Index); void readExceptionSpec(ModuleFile &ModuleFile, SmallVectorImpl<QualType> &ExceptionStorage, - FunctionProtoType::ExtProtoInfo &EPI, + FunctionProtoType::ExceptionSpecInfo &ESI, const RecordData &Record, unsigned &Index); RecordLocation TypeCursorForIndex(unsigned Index); void LoadedDecl(unsigned Index, Decl *D); @@ -1245,6 +1277,7 @@ private: void PassInterestingDeclToConsumer(Decl *D); void finishPendingActions(); + void diagnoseOdrViolations(); void pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name); @@ -1369,20 +1402,50 @@ public: void makeNamesVisible(const HiddenNames &Names, Module *Owner, bool FromFinalization); + /// \brief Take the AST callbacks listener. + std::unique_ptr<ASTReaderListener> takeListener() { + return std::move(Listener); + } + /// \brief Set the AST callbacks listener. - void setListener(ASTReaderListener *listener) { - Listener.reset(listener); + void setListener(std::unique_ptr<ASTReaderListener> Listener) { + this->Listener = std::move(Listener); } - /// \brief Add an AST callbak listener. + /// \brief Add an AST callback listener. /// /// Takes ownership of \p L. - void addListener(ASTReaderListener *L) { + void addListener(std::unique_ptr<ASTReaderListener> L) { if (Listener) - L = new ChainedASTReaderListener(L, Listener.release()); - Listener.reset(L); + L = llvm::make_unique<ChainedASTReaderListener>(std::move(L), + std::move(Listener)); + Listener = std::move(L); } + /// RAII object to temporarily add an AST callback listener. + class ListenerScope { + ASTReader &Reader; + bool Chained; + + public: + ListenerScope(ASTReader &Reader, std::unique_ptr<ASTReaderListener> L) + : Reader(Reader), Chained(false) { + auto Old = Reader.takeListener(); + if (Old) { + Chained = true; + L = llvm::make_unique<ChainedASTReaderListener>(std::move(L), + std::move(Old)); + } + Reader.setListener(std::move(L)); + } + ~ListenerScope() { + auto New = Reader.takeListener(); + if (Chained) + Reader.setListener(static_cast<ChainedASTReaderListener *>(New.get()) + ->takeSecond()); + } + }; + /// \brief Set the AST deserialization listener. void setDeserializationListener(ASTDeserializationListener *Listener, bool TakeOwnership = false); @@ -1412,8 +1475,9 @@ public: void UpdateSema(); /// \brief Add in-memory (virtual file) buffer. - void addInMemoryBuffer(StringRef &FileName, llvm::MemoryBuffer *Buffer) { - ModuleMgr.addInMemoryBuffer(FileName, Buffer); + void addInMemoryBuffer(StringRef &FileName, + std::unique_ptr<llvm::MemoryBuffer> Buffer) { + ModuleMgr.addInMemoryBuffer(FileName, std::move(Buffer)); } /// \brief Finalizes the AST reader's state before writing an AST file to @@ -1772,6 +1836,9 @@ public: void ReadDynamicClasses(SmallVectorImpl<CXXRecordDecl *> &Decls) override; + void ReadUnusedLocalTypedefNameCandidates( + llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override; + void ReadLocallyScopedExternCDecls( SmallVectorImpl<NamedDecl *> &Decls) override; @@ -1832,17 +1899,18 @@ public: ModuleFile &M, uint64_t Offset); void installImportedMacro(IdentifierInfo *II, ModuleMacroInfo *MMI, - Module *Owner, bool FromFinalization); + Module *Owner); typedef llvm::TinyPtrVector<DefMacroDirective *> AmbiguousMacros; llvm::DenseMap<IdentifierInfo*, AmbiguousMacros> AmbiguousMacroDefs; void - removeOverriddenMacros(IdentifierInfo *II, AmbiguousMacros &Ambig, + removeOverriddenMacros(IdentifierInfo *II, SourceLocation Loc, + AmbiguousMacros &Ambig, ArrayRef<serialization::SubmoduleID> Overrides); AmbiguousMacros * - removeOverriddenMacros(IdentifierInfo *II, + removeOverriddenMacros(IdentifierInfo *II, SourceLocation Loc, ArrayRef<serialization::SubmoduleID> Overrides); /// \brief Retrieve the macro with the given ID. @@ -1976,6 +2044,9 @@ public: // \brief Read a string static std::string ReadString(const RecordData &Record, unsigned &Idx); + // \brief Read a path + std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx); + /// \brief Read a version tuple. static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); @@ -2050,9 +2121,9 @@ public: /// \brief Retrieve the AST context that this AST reader supplements. ASTContext &getContext() { return Context; } - // \brief Contains declarations that were loaded before we have + // \brief Contains the IDs for declarations that were requested before we have // access to a Sema object. - SmallVector<NamedDecl *, 16> PreloadedDecls; + SmallVector<uint64_t, 16> PreloadedDeclIDs; /// \brief Retrieve the semantic analysis object used to analyze the /// translation unit in which the precompiled header is being @@ -2078,6 +2149,10 @@ public: //RIDErief Loads comments ranges. void ReadComments() override; + + /// Return all input files for the given module file. + void getInputFiles(ModuleFile &F, + SmallVectorImpl<serialization::InputFile> &Files); }; /// \brief Helper class that saves the current stream position and diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index ad6ecdd3519b..9907fae67654 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -11,8 +11,8 @@ // containing a serialized representation of a translation unit. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_AST_WRITER_H -#define LLVM_CLANG_FRONTEND_AST_WRITER_H +#ifndef LLVM_CLANG_SERIALIZATION_ASTWRITER_H +#define LLVM_CLANG_SERIALIZATION_ASTWRITER_H #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Decl.h" @@ -111,7 +111,10 @@ private: /// \brief The module we're currently writing, if any. Module *WritingModule; - + + /// \brief The base directory for any relative paths we emit. + std::string BaseDirectory; + /// \brief Indicates when the AST writing is actively performing /// serialization, rather than just queueing updates. bool WritingAST; @@ -283,6 +286,10 @@ private: llvm::DenseMap<const MacroDefinition *, serialization::PreprocessedEntityID> MacroDefinitions; + /// \brief Cache of indices of anonymous declarations within their lexical + /// contexts. + llvm::DenseMap<const Decl *, unsigned> AnonymousDeclarationNumbers; + /// An update to a Decl. class DeclUpdate { /// A DeclUpdateKind. @@ -453,20 +460,23 @@ private: StringRef isysroot, const std::string &OutputFile); void WriteInputFiles(SourceManager &SourceMgr, HeaderSearchOptions &HSOpts, - StringRef isysroot, bool Modules); void WriteSourceManagerBlock(SourceManager &SourceMgr, - const Preprocessor &PP, - StringRef isysroot); + const Preprocessor &PP); void WritePreprocessor(const Preprocessor &PP, bool IsModule); - void WriteHeaderSearch(const HeaderSearch &HS, StringRef isysroot); + void WriteHeaderSearch(const HeaderSearch &HS); void WritePreprocessorDetail(PreprocessingRecord &PPRec); void WriteSubmodules(Module *WritingModule); void WritePragmaDiagnosticMappings(const DiagnosticsEngine &Diag, bool isModule); void WriteCXXBaseSpecifiersOffsets(); + + unsigned TypeExtQualAbbrev; + unsigned TypeFunctionProtoAbbrev; + void WriteTypeAbbrevs(); void WriteType(QualType T); + uint32_t GenerateNameLookupTable(const DeclContext *DC, llvm::SmallVectorImpl<char> &LookupTable); uint64_t WriteDeclContextLexicalBlock(ASTContext &Context, DeclContext *DC); @@ -494,17 +504,20 @@ private: unsigned DeclContextLexicalAbbrev; unsigned DeclContextVisibleLookupAbbrev; unsigned UpdateVisibleAbbrev; - unsigned DeclRefExprAbbrev; - unsigned CharacterLiteralAbbrev; unsigned DeclRecordAbbrev; - unsigned IntegerLiteralAbbrev; unsigned DeclTypedefAbbrev; unsigned DeclVarAbbrev; unsigned DeclFieldAbbrev; unsigned DeclEnumAbbrev; unsigned DeclObjCIvarAbbrev; + unsigned DeclCXXMethodAbbrev; + + unsigned DeclRefExprAbbrev; + unsigned CharacterLiteralAbbrev; + unsigned IntegerLiteralAbbrev; + unsigned ExprImplicitCastAbbrev; - void WriteDeclsBlockAbbrevs(); + void WriteDeclAbbrevs(); void WriteDecl(ASTContext &Context, Decl *D); void AddFunctionDefinition(const FunctionDecl *FD, RecordData &Record); @@ -527,7 +540,8 @@ public: /// writing a precompiled header. /// /// \param isysroot if non-empty, write a relocatable file whose headers - /// are relative to the given system root. + /// are relative to the given system root. If we're writing a module, its + /// build directory will be used in preference to this if both are available. void WriteAST(Sema &SemaRef, const std::string &OutputFile, Module *WritingModule, StringRef isysroot, @@ -631,6 +645,7 @@ public: DeclarationName Name, RecordDataImpl &Record); void AddDeclarationNameInfo(const DeclarationNameInfo &NameInfo, RecordDataImpl &Record); + unsigned getAnonymousDeclarationNumber(const NamedDecl *D); void AddQualifierInfo(const QualifierInfo &Info, RecordDataImpl &Record); @@ -673,6 +688,17 @@ public: /// \brief Add a string to the given record. void AddString(StringRef Str, RecordDataImpl &Record); + /// \brief Convert a path from this build process into one that is appropriate + /// for emission in the module file. + bool PreparePathForOutput(SmallVectorImpl<char> &Path); + + /// \brief Add a path to the given record. + void AddPath(StringRef Path, RecordDataImpl &Record); + + /// \brief Emit the current record with the given path as a blob. + void EmitRecordWithPath(unsigned Abbrev, RecordDataImpl &Record, + StringRef Path); + /// \brief Add a version tuple to the given record void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); @@ -731,16 +757,26 @@ public: void ClearSwitchCaseIDs(); + unsigned getTypeExtQualAbbrev() const { + return TypeExtQualAbbrev; + } + unsigned getTypeFunctionProtoAbbrev() const { + return TypeFunctionProtoAbbrev; + } + unsigned getDeclParmVarAbbrev() const { return DeclParmVarAbbrev; } - unsigned getDeclRefExprAbbrev() const { return DeclRefExprAbbrev; } - unsigned getCharacterLiteralAbbrev() const { return CharacterLiteralAbbrev; } unsigned getDeclRecordAbbrev() const { return DeclRecordAbbrev; } - unsigned getIntegerLiteralAbbrev() const { return IntegerLiteralAbbrev; } unsigned getDeclTypedefAbbrev() const { return DeclTypedefAbbrev; } unsigned getDeclVarAbbrev() const { return DeclVarAbbrev; } unsigned getDeclFieldAbbrev() const { return DeclFieldAbbrev; } unsigned getDeclEnumAbbrev() const { return DeclEnumAbbrev; } unsigned getDeclObjCIvarAbbrev() const { return DeclObjCIvarAbbrev; } + unsigned getDeclCXXMethodAbbrev() const { return DeclCXXMethodAbbrev; } + + unsigned getDeclRefExprAbbrev() const { return DeclRefExprAbbrev; } + unsigned getCharacterLiteralAbbrev() const { return CharacterLiteralAbbrev; } + unsigned getIntegerLiteralAbbrev() const { return IntegerLiteralAbbrev; } + unsigned getExprImplicitCastAbbrev() const { return ExprImplicitCastAbbrev; } bool hasChain() const { return Chain; } @@ -775,6 +811,7 @@ public: const ObjCPropertyDecl *OrigProp, const ObjCCategoryDecl *ClassExt) override; void DeclarationMarkedUsed(const Decl *D) override; + void DeclarationMarkedOpenMPThreadPrivate(const Decl *D) override; }; /// \brief AST and semantic-analysis consumer that generates a diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index f8ef8a1a63cf..5f8ae1fe7bee 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H -#define LLVM_CLANG_SERIALIZATION_CONTINUOUS_RANGE_MAP_H +#ifndef LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H +#define LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" @@ -117,6 +117,14 @@ public: ~Builder() { std::sort(Self.Rep.begin(), Self.Rep.end(), Compare()); + std::unique(Self.Rep.begin(), Self.Rep.end(), + [](const_reference A, const_reference B) { + // FIXME: we should not allow any duplicate keys, but there are a lot of + // duplicate 0 -> 0 mappings to remove first. + assert((A == B || A.first != B.first) && + "ContinuousRangeMap::Builder given non-unique keys"); + return A == B; + }); } void insert(const value_type &Val) { diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h index 1f0d7523ec29..d8a57be84a52 100644 --- a/include/clang/Serialization/GlobalModuleIndex.h +++ b/include/clang/Serialization/GlobalModuleIndex.h @@ -13,8 +13,8 @@ // queries such as "do any modules know about this identifier?" // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H -#define LLVM_CLANG_SERIALIZATION_GLOBAL_MODULE_INDEX_H +#ifndef LLVM_CLANG_SERIALIZATION_GLOBALMODULEINDEX_H +#define LLVM_CLANG_SERIALIZATION_GLOBALMODULEINDEX_H #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallPtrSet.h" @@ -115,7 +115,7 @@ class GlobalModuleIndex { unsigned NumIdentifierLookupHits; /// \brief Internal constructor. Use \c readIndex() to read an index. - explicit GlobalModuleIndex(llvm::MemoryBuffer *Buffer, + explicit GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer, llvm::BitstreamCursor Cursor); GlobalModuleIndex(const GlobalModuleIndex &) LLVM_DELETED_FUNCTION; diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 49520390559b..426cec5dd7c2 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -42,10 +42,11 @@ namespace reader { /// \brief Specifies the kind of module that has been loaded. enum ModuleKind { - MK_Module, ///< File is a module proper. - MK_PCH, ///< File is a PCH file treated as such. - MK_Preamble, ///< File is a PCH file treated as the preamble. - MK_MainFile ///< File is a PCH file treated as the actual main file. + MK_ImplicitModule, ///< File is an implicitly-loaded module. + MK_ExplicitModule, ///< File is an explicitly-loaded module. + MK_PCH, ///< File is a PCH file treated as such. + MK_Preamble, ///< File is a PCH file treated as the preamble. + MK_MainFile ///< File is a PCH file treated as the actual main file. }; /// \brief Information about the contents of a DeclContext. @@ -96,6 +97,8 @@ public: bool isNotFound() const { return Val.getInt() == NotFound; } }; +typedef unsigned ASTFileSignature; + /// \brief Information about a module that has been loaded by the ASTReader. /// /// Each instance of the Module class corresponds to a single AST file, which @@ -122,6 +125,9 @@ public: /// \brief The name of the module. std::string ModuleName; + /// \brief The base directory of the module. + std::string BaseDirectory; + std::string getTimestampFilename() const { return FileName + ".timestamp"; } @@ -151,6 +157,10 @@ public: /// \brief The file entry for the module file. const FileEntry *File; + /// \brief The signature of the module file, which may be used along with size + /// and modification time to identify this particular file. + ASTFileSignature Signature; + /// \brief Whether this module has been directly imported by the /// user. bool DirectlyImported; diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 3259902222d8..3d10fad0a1b6 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H -#define LLVM_CLANG_SERIALIZATION_MODULE_MANAGER_H +#ifndef LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H +#define LLVM_CLANG_SERIALIZATION_MODULEMANAGER_H #include "clang/Basic/FileManager.h" #include "clang/Serialization/Module.h" @@ -41,7 +41,8 @@ class ModuleManager { FileManager &FileMgr; /// \brief A lookup of in-memory (virtual file) buffers - llvm::DenseMap<const FileEntry *, llvm::MemoryBuffer *> InMemoryBuffers; + llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>> + InMemoryBuffers; /// \brief The visitation order. SmallVector<ModuleFile *, 4> VisitOrder; @@ -141,7 +142,7 @@ public: ModuleFile *lookup(const FileEntry *File); /// \brief Returns the in-memory (virtual file) buffer with the given name - llvm::MemoryBuffer *lookupBuffer(StringRef Name); + std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name); /// \brief Number of modules loaded unsigned size() const { return Chain.size(); } @@ -178,6 +179,12 @@ public: /// \param ExpectedModTime The expected modification time of the module /// file, used for validation. This will be zero if unknown. /// + /// \param ExpectedSignature The expected signature of the module file, used + /// for validation. This will be zero if unknown. + /// + /// \param ReadSignature Reads the signature from an AST file without actually + /// loading it. + /// /// \param Module A pointer to the module file if the module was successfully /// loaded. /// @@ -190,6 +197,9 @@ public: SourceLocation ImportLoc, ModuleFile *ImportedBy, unsigned Generation, off_t ExpectedSize, time_t ExpectedModTime, + ASTFileSignature ExpectedSignature, + std::function<ASTFileSignature(llvm::BitstreamReader &)> + ReadSignature, ModuleFile *&Module, std::string &ErrorStr); @@ -199,7 +209,8 @@ public: ModuleMap *modMap); /// \brief Add an in-memory buffer the list of known buffers - void addInMemoryBuffer(StringRef FileName, llvm::MemoryBuffer *Buffer); + void addInMemoryBuffer(StringRef FileName, + std::unique_ptr<llvm::MemoryBuffer> Buffer); /// \brief Set the global module index. void setGlobalIndex(GlobalModuleIndex *Index); @@ -232,7 +243,7 @@ public: /// Any module that is known to both the global module index and the module /// manager that is *not* in this set can be skipped. void visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData, - llvm::SmallPtrSet<ModuleFile *, 4> *ModuleFilesHit = nullptr); + llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr); /// \brief Visit each of the modules with a depth-first traversal. /// diff --git a/include/clang/Serialization/SerializationDiagnostic.h b/include/clang/Serialization/SerializationDiagnostic.h index c28cfea25c87..d50422aa466c 100644 --- a/include/clang/Serialization/SerializationDiagnostic.h +++ b/include/clang/Serialization/SerializationDiagnostic.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SERIALIZATIONDIAGNOSTIC_H -#define LLVM_CLANG_SERIALIZATIONDIAGNOSTIC_H +#ifndef LLVM_CLANG_SERIALIZATION_SERIALIZATIONDIAGNOSTIC_H +#define LLVM_CLANG_SERIALIZATION_SERIALIZATIONDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" diff --git a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h index eee38e920898..463f04a65ac3 100644 --- a/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h +++ b/include/clang/StaticAnalyzer/Checkers/LocalCheckers.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_LOCALCHECKERS_H -#define LLVM_CLANG_GR_LOCALCHECKERS_H +#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_LOCALCHECKERS_H +#define LLVM_CLANG_STATICANALYZER_CHECKERS_LOCALCHECKERS_H namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h index 26335bf68dd9..ab92a2465c53 100644 --- a/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h +++ b/include/clang/StaticAnalyzer/Checkers/ObjCRetainCount.h @@ -16,10 +16,18 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_OBJCRETAINCOUNT_H -#define LLVM_CLANG_OBJCRETAINCOUNT_H +#ifndef LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H +#define LLVM_CLANG_STATICANALYZER_CHECKERS_OBJCRETAINCOUNT_H -namespace clang { namespace ento { namespace objc_retain { +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" + +namespace clang { +class FunctionDecl; +class ObjCMethodDecl; + +namespace ento { namespace objc_retain { /// An ArgEffect summarizes the retain count behavior on an argument or receiver /// to a function or method. diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index 978c3e20ab20..fc9fc5ee7931 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYZEROPTIONS_H -#define LLVM_CLANG_ANALYZEROPTIONS_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H +#define LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -137,6 +137,13 @@ public: unsigned maxBlockVisitOnPath; + /// \brief Disable all analyzer checks. + /// + /// This flag allows one to disable analyzer checks on the code processed by + /// the given analysis consumer. Note, the code will get parsed and the + /// command-line options will get checked. + unsigned DisableAllChecks : 1; + unsigned ShowCheckerHelp : 1; unsigned AnalyzeAll : 1; unsigned AnalyzerDisplayProgress : 1; @@ -420,6 +427,7 @@ public: AnalysisConstraintsOpt(RangeConstraintsModel), AnalysisDiagOpt(PD_HTML), AnalysisPurgeOpt(PurgeStmt), + DisableAllChecks(0), ShowCheckerHelp(0), AnalyzeAll(0), AnalyzerDisplayProgress(0), diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index 53712319253c..b03371ccee9c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_BUGREPORTER -#define LLVM_CLANG_GR_BUGREPORTER +#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H +#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H #include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" @@ -63,7 +63,7 @@ public: }; typedef const SourceRange *ranges_iterator; - typedef SmallVector<BugReporterVisitor *, 8> VisitorList; + typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList; typedef VisitorList::iterator visitor_iterator; typedef SmallVector<StringRef, 2> ExtraTextList; @@ -179,9 +179,9 @@ public: const ExplodedNode *getErrorNode() const { return ErrorNode; } - const StringRef getDescription() const { return Description; } + StringRef getDescription() const { return Description; } - const StringRef getShortDescription(bool UseFallback = true) const { + StringRef getShortDescription(bool UseFallback = true) const { if (ShortDescription.empty() && UseFallback) return Description; return ShortDescription; @@ -299,9 +299,9 @@ public: /// \sa registerConditionVisitor(), registerTrackNullOrUndefValue(), /// registerFindLastStore(), registerNilReceiverVisitor(), and /// registerVarDeclsLastStore(). - void addVisitor(BugReporterVisitor *visitor); + void addVisitor(std::unique_ptr<BugReporterVisitor> visitor); - /// Iterators through the custom diagnostic visitors. + /// Iterators through the custom diagnostic visitors. visitor_iterator visitor_begin() { return Callbacks.begin(); } visitor_iterator visitor_end() { return Callbacks.end(); } @@ -345,9 +345,12 @@ class BugReportEquivClass : public llvm::FoldingSetNode { llvm::ilist<BugReport> Reports; friend class BugReporter; - void AddReport(BugReport* R) { Reports.push_back(R); } + void AddReport(std::unique_ptr<BugReport> R) { + Reports.push_back(R.release()); + } + public: - BugReportEquivClass(BugReport* R) { Reports.push_back(R); } + BugReportEquivClass(std::unique_ptr<BugReport> R) { AddReport(std::move(R)); } ~BugReportEquivClass(); void Profile(llvm::FoldingSetNodeID& ID) const { diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index f352f806eb9c..83b05ecc52a5 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_BUGREPORTERVISITOR -#define LLVM_CLANG_GR_BUGREPORTERVISITOR +#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H +#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITOR_H #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" @@ -48,7 +48,7 @@ public: /// (Warning: if you have a deep subclass of BugReporterVisitorImpl, the /// default implementation of clone() will NOT do the right thing, and you /// will have to provide your own implementation.) - virtual BugReporterVisitor *clone() const = 0; + virtual std::unique_ptr<BugReporterVisitor> clone() const = 0; /// \brief Return a diagnostic piece which should be associated with the /// given node. @@ -66,17 +66,15 @@ public: /// If returns NULL the default implementation will be used. /// Also note that at most one visitor of a BugReport should generate a /// non-NULL end of path diagnostic piece. - virtual PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR); + virtual std::unique_ptr<PathDiagnosticPiece> + getEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); virtual void Profile(llvm::FoldingSetNodeID &ID) const = 0; /// \brief Generates the default final diagnostic piece. - static PathDiagnosticPiece *getDefaultEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR); - + static std::unique_ptr<PathDiagnosticPiece> + getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, + BugReport &BR); }; /// This class provides a convenience implementation for clone() using the @@ -89,8 +87,8 @@ public: /// will have to provide your own implementation.) template <class DERIVED> class BugReporterVisitorImpl : public BugReporterVisitor { - BugReporterVisitor *clone() const override { - return new DERIVED(*static_cast<const DERIVED *>(this)); + std::unique_ptr<BugReporterVisitor> clone() const override { + return llvm::make_unique<DERIVED>(*static_cast<const DERIVED *>(this)); } }; @@ -268,9 +266,9 @@ public: return nullptr; } - PathDiagnosticPiece *getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR) override; + std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, + const ExplodedNode *N, + BugReport &BR) override; }; /// \brief When a region containing undefined value or '0' value is passed @@ -364,4 +362,4 @@ bool isDeclRefExprToReference(const Expr *E); } // end namespace bugreporter -#endif //LLVM_CLANG_GR__BUGREPORTERVISITOR +#endif diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 24c778552ee4..16226e94df48 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_ANALYSIS_BUGTYPE -#define LLVM_CLANG_ANALYSIS_BUGTYPE +#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGTYPE_H +#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGTYPE_H #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h" diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h index 3f0fe968cc11..8df2bc331b51 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/CommonBugCategories.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H -#define LLVM_CLANG_STATIC_ANALYZER_BUG_CATEGORIES_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_COMMONBUGCATEGORIES_H +#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_COMMONBUGCATEGORIES_H // Common strings used for the "category" of many static analyzer issues. namespace clang { diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index 5a578d015e39..b4ab1ea78545 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PATH_DIAGNOSTIC_H -#define LLVM_CLANG_PATH_DIAGNOSTIC_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H +#define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/SourceLocation.h" @@ -94,8 +94,8 @@ public: FilesMade *filesMade) = 0; virtual StringRef getName() const = 0; - - void HandlePathDiagnostic(PathDiagnostic *D); + + void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D); enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive }; virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } @@ -762,11 +762,11 @@ public: bool isWithinCall() const { return !pathStack.empty(); } - void setEndOfPath(PathDiagnosticPiece *EndPiece) { + void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) { assert(!Loc.isValid() && "End location already set!"); Loc = EndPiece->getLocation(); assert(Loc.isValid() && "Invalid location for end-of-path piece"); - getActivePath().push_back(EndPiece); + getActivePath().push_back(EndPiece.release()); } void appendToDesc(StringRef S) { diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index b9a5b8a27fa9..8cc35148e07f 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_CHECKER -#define LLVM_CLANG_SA_CORE_CHECKER +#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H +#define LLVM_CLANG_STATICANALYZER_CORE_CHECKER_H #include "clang/Analysis/ProgramPoint.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index b364115c99b6..30b048023578 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_CHECKERMANAGER_H -#define LLVM_CLANG_SA_CORE_CHECKERMANAGER_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LangOptions.h" diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index 43e9166b3cdc..ce512fd301ee 100644 --- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H -#define LLVM_CLANG_GR_PATH_DIAGNOSTIC_CLIENTS_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHDIAGNOSTICCONSUMERS_H #include <string> #include <vector> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index 37be69aaba84..cc8a9b8ef071 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_APSINTTYPE_H -#define LLVM_CLANG_SA_CORE_APSINTTYPE_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_APSINTTYPE_H #include "llvm/ADT/APSInt.h" #include <tuple> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 1a398b86484d..dbc59cfbd9d7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_ANALYSISMANAGER_H -#define LLVM_CLANG_GR_ANALYSISMANAGER_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ANALYSISMANAGER_H #include "clang/Analysis/AnalysisContext.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" @@ -23,6 +23,8 @@ namespace clang { +class CodeInjector; + namespace ento { class CheckerManager; @@ -50,7 +52,8 @@ public: StoreManagerCreator storemgr, ConstraintManagerCreator constraintmgr, CheckerManager *checkerMgr, - AnalyzerOptions &Options); + AnalyzerOptions &Options, + CodeInjector* injector = nullptr); ~AnalysisManager(); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 08905fdf0783..5b007f1531df 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_BASICVALUEFACTORY_H -#define LLVM_CLANG_GR_BASICVALUEFACTORY_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H #include "clang/AST/ASTContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h index 0408070e493f..1d779e6cb6ec 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_BLOCKCOUNTER -#define LLVM_CLANG_GR_BLOCKCOUNTER +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BLOCKCOUNTER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BLOCKCOUNTER_H #include "llvm/Support/Allocator.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 4a5426b2747d..00deaa6c1977 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL -#define LLVM_CLANG_STATICANALYZER_PATHSENSITIVE_CALL +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H #include "clang/AST/DeclCXX.h" #include "clang/AST/ExprCXX.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 5a33bdf01b3c..68274f52a60c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT -#define LLVM_CLANG_SA_CORE_PATHSENSITIVE_CHECKERCONTEXT +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERCONTEXT_H #include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index 12547e0969a1..6a42df20d1cb 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_PATHSENSITIVE_CHECKERHELPERS -#define LLVM_CLANG_GR_PATHSENSITIVE_CHECKERHELPERS +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CHECKERHELPERS_H #include "clang/AST/Stmt.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index 51bb89b9e1f9..f8760964b754 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_CONSTRAINT_MANAGER_H -#define LLVM_CLANG_GR_CONSTRAINT_MANAGER_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" @@ -148,8 +148,9 @@ protected: virtual ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym); }; -ConstraintManager* CreateRangeConstraintManager(ProgramStateManager& statemgr, - SubEngine *subengine); +std::unique_ptr<ConstraintManager> +CreateRangeConstraintManager(ProgramStateManager &statemgr, + SubEngine *subengine); } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 76ace6d7cc2a..0dafd5f3bdee 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_COREENGINE -#define LLVM_CLANG_GR_COREENGINE +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H #include "clang/AST/Expr.h" #include "clang/Analysis/AnalysisContext.h" @@ -60,7 +60,7 @@ private: SubEngine& SubEng; /// G - The simulation graph. Each node is a (location,state) pair. - std::unique_ptr<ExplodedGraph> G; + mutable ExplodedGraph G; /// WList - A set of queued nodes that need to be processed by the /// worklist algorithm. It is up to the implementation of WList to decide @@ -95,6 +95,8 @@ private: void HandleBranch(const Stmt *Cond, const Stmt *Term, const CFGBlock *B, ExplodedNode *Pred); + void HandleCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, + const CFGBlock *B, ExplodedNode *Pred); /// Handle conditional logic for running static initializers. void HandleStaticInit(const DeclStmt *DS, const CFGBlock *B, @@ -108,19 +110,12 @@ private: public: /// Construct a CoreEngine object to analyze the provided CFG. - CoreEngine(SubEngine& subengine, - FunctionSummariesTy *FS) - : SubEng(subengine), G(new ExplodedGraph()), - WList(WorkList::makeDFS()), - BCounterFactory(G->getAllocator()), - FunctionSummaries(FS){} + CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS) + : SubEng(subengine), WList(WorkList::makeDFS()), + BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {} /// getGraph - Returns the exploded graph. - ExplodedGraph& getGraph() { return *G.get(); } - - /// takeGraph - Returns the exploded graph. Ownership of the graph is - /// transferred to the caller. - ExplodedGraph *takeGraph() { return G.release(); } + ExplodedGraph &getGraph() { return G; } /// ExecuteWorkList - Run the worklist algorithm for a maximum number of /// steps. Returns true if there is still simulation state on the worklist. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h index 5ac97dbc3145..e13c6410c7be 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h @@ -6,8 +6,8 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_CORE_DYNAMICTYPEINFO_H -#define LLVM_CLANG_SA_CORE_DYNAMICTYPEINFO_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEINFO_H #include "clang/AST/Type.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index f3a582da040f..ba9715b38f3f 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_ENVIRONMENT_H -#define LLVM_CLANG_GR_ENVIRONMENT_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H #include "clang/Analysis/AnalysisContext.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index 98092ef00db7..c4eabb8c2ace 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -16,8 +16,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_EXPLODEDGRAPH -#define LLVM_CLANG_GR_EXPLODEDGRAPH +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H #include "clang/AST/Decl.h" #include "clang/Analysis/AnalysisContext.h" @@ -297,8 +297,8 @@ public: bool IsSink = false, bool* IsNew = nullptr); - ExplodedGraph* MakeEmptyGraph() const { - return new ExplodedGraph(); + std::unique_ptr<ExplodedGraph> MakeEmptyGraph() const { + return llvm::make_unique<ExplodedGraph>(); } /// addRoot - Add an untyped node to the set of roots. @@ -372,9 +372,10 @@ public: /// \param[out] InverseMap An optional map from nodes in the returned graph to /// nodes in this graph. /// \returns The trimmed graph - ExplodedGraph *trim(ArrayRef<const NodeTy *> Nodes, - InterExplodedGraphMap *ForwardMap = nullptr, - InterExplodedGraphMap *InverseMap = nullptr) const; + std::unique_ptr<ExplodedGraph> + trim(ArrayRef<const NodeTy *> Nodes, + InterExplodedGraphMap *ForwardMap = nullptr, + InterExplodedGraphMap *InverseMap = nullptr) const; /// Enable tracking of recently allocated nodes for potential reclamation /// when calling reclaimRecentlyAllocatedNodes(). diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 0fb4a245916f..247bf0c69deb 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_EXPRENGINE -#define LLVM_CLANG_GR_EXPRENGINE +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H #include "clang/AST/Expr.h" #include "clang/AST/Type.h" @@ -227,6 +227,15 @@ public: const CFGBlock *DstT, const CFGBlock *DstF) override; + /// Called by CoreEngine. + /// Used to generate successor nodes for temporary destructors depending + /// on whether the corresponding constructor was visited. + void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, + NodeBuilderContext &BldCtx, + ExplodedNode *Pred, ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) override; + /// Called by CoreEngine. Used to processing branching behavior /// at static initalizers. void processStaticInitializer(const DeclStmt *DS, @@ -408,7 +417,11 @@ public: void VisitIncrementDecrementOperator(const UnaryOperator* U, ExplodedNode *Pred, ExplodedNodeSet &Dst); - + + void VisitCXXBindTemporaryExpr(const CXXBindTemporaryExpr *BTE, + ExplodedNodeSet &PreVisit, + ExplodedNodeSet &Dst); + void VisitCXXCatchStmt(const CXXCatchStmt *CS, ExplodedNode *Pred, ExplodedNodeSet &Dst); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index 169af939f08e..faa350004511 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_FUNCTIONSUMMARY_H -#define LLVM_CLANG_GR_FUNCTIONSUMMARY_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 92b082d5215c..1be7a2612625 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -13,8 +13,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_MEMREGION_H -#define LLVM_CLANG_GR_MEMREGION_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index 4902ef50c7fe..e819b8891179 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_VALUESTATE_H -#define LLVM_CLANG_GR_VALUESTATE_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_H #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" @@ -39,9 +39,10 @@ namespace ento { class CallEvent; class CallEventManager; -typedef ConstraintManager* (*ConstraintManagerCreator)(ProgramStateManager&, - SubEngine*); -typedef StoreManager* (*StoreManagerCreator)(ProgramStateManager&); +typedef std::unique_ptr<ConstraintManager>(*ConstraintManagerCreator)( + ProgramStateManager &, SubEngine *); +typedef std::unique_ptr<StoreManager>(*StoreManagerCreator)( + ProgramStateManager &); //===----------------------------------------------------------------------===// // ProgramStateTrait - Traits used by the Generic Data Map of a ProgramState. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index 823bde798e55..6b4da7db244d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -15,8 +15,8 @@ //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_PROGRAMSTATETRAIT_H -#define LLVM_CLANG_GR_PROGRAMSTATETRAIT_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H #include "llvm/Support/Allocator.h" #include "llvm/Support/DataTypes.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h index 371f3c582f7f..415bb7713d4b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_PROGRAMSTATE_FWD_H -#define LLVM_CLANG_PROGRAMSTATE_FWD_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_FWD_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATE_FWD_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index 29fb413d1ce7..a68d3410a87b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_SVALBUILDER -#define LLVM_CLANG_GR_SVALBUILDER +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H #include "clang/AST/ASTContext.h" #include "clang/AST/Expr.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index d50c3be4bf5d..ef43fe0eea9a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_RVALUE_H -#define LLVM_CLANG_GR_RVALUE_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 84c31661212f..5500c3c9efe3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_STORE_H -#define LLVM_CLANG_GR_STORE_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" @@ -276,8 +276,10 @@ inline StoreRef &StoreRef::operator=(StoreRef const &newStore) { } // FIXME: Do we need to pass ProgramStateManager anymore? -StoreManager *CreateRegionStoreManager(ProgramStateManager& StMgr); -StoreManager *CreateFieldsOnlyRegionStoreManager(ProgramStateManager& StMgr); +std::unique_ptr<StoreManager> +CreateRegionStoreManager(ProgramStateManager &StMgr); +std::unique_ptr<StoreManager> +CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr); } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h index d5ba003a6915..958c8c377ea2 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_STOREREF_H -#define LLVM_CLANG_GR_STOREREF_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H #include <cassert> diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 3482e8d27dbb..741ba0e2f290 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -10,8 +10,8 @@ // This file defines the interface of a subengine of the CoreEngine. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_SUBENGINE_H -#define LLVM_CLANG_GR_SUBENGINE_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SUBENGINE_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SUBENGINE_H #include "clang/Analysis/ProgramPoint.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" @@ -72,6 +72,16 @@ public: const CFGBlock *DstT, const CFGBlock *DstF) = 0; + /// Called by CoreEngine. + /// Used to generate successor nodes for temporary destructors depending + /// on whether the corresponding constructor was visited. + virtual void processCleanupTemporaryBranch(const CXXBindTemporaryExpr *BTE, + NodeBuilderContext &BldCtx, + ExplodedNode *Pred, + ExplodedNodeSet &Dst, + const CFGBlock *DstT, + const CFGBlock *DstF) = 0; + /// Called by CoreEngine. Used to processing branching behavior /// at static initalizers. virtual void processStaticInitializer(const DeclStmt *DS, diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 2b5cc18c9a29..fbeaae48dc9c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_SYMMGR_H -#define LLVM_CLANG_GR_SYMMGR_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h index 4c58d4b1d261..d39b5017d312 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -11,8 +11,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TAINTMANAGER_H -#define LLVM_CLANG_TAINTMANAGER_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h index 8ddc8b9d6f6c..0c56e7d8ea69 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h @@ -11,8 +11,8 @@ // of taint. // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TAINTTAG_H -#define LLVM_CLANG_TAINTTAG_H +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H namespace clang { namespace ento { diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index 3ed145dbd2b6..4f1a60e67556 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_WORKLIST -#define LLVM_CLANG_GR_WORKLIST +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_WORKLIST_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_WORKLIST_H #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h index 30e5d3dd9a2b..37ea05fb99cf 100644 --- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h +++ b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_ANALYSISCONSUMER_H -#define LLVM_CLANG_GR_ANALYSISCONSUMER_H +#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_ANALYSISCONSUMER_H +#define LLVM_CLANG_STATICANALYZER_FRONTEND_ANALYSISCONSUMER_H #include "clang/AST/ASTConsumer.h" #include "clang/Basic/LLVM.h" @@ -25,6 +25,8 @@ namespace clang { class Preprocessor; class DiagnosticsEngine; +class CodeInjector; +class CompilerInstance; namespace ento { class CheckerManager; @@ -37,10 +39,8 @@ public: /// CreateAnalysisConsumer - Creates an ASTConsumer to run various code /// analysis passes. (The set of analyses run is controlled by command-line /// options.) -AnalysisASTConsumer *CreateAnalysisConsumer(const Preprocessor &pp, - const std::string &output, - AnalyzerOptionsRef opts, - ArrayRef<std::string> plugins); +std::unique_ptr<AnalysisASTConsumer> +CreateAnalysisConsumer(CompilerInstance &CI); } // end GR namespace diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h index 1df8c098d93d..2985b7c117ef 100644 --- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h +++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h @@ -7,10 +7,11 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SA_FRONTEND_CHECKERREGISTRATION_H -#define LLVM_CLANG_SA_FRONTEND_CHECKERREGISTRATION_H +#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H +#define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H #include "clang/Basic/LLVM.h" +#include <memory> #include <string> namespace clang { @@ -21,10 +22,9 @@ namespace clang { namespace ento { class CheckerManager; -CheckerManager *createCheckerManager(AnalyzerOptions &opts, - const LangOptions &langOpts, - ArrayRef<std::string> plugins, - DiagnosticsEngine &diags); + std::unique_ptr<CheckerManager> + createCheckerManager(AnalyzerOptions &opts, const LangOptions &langOpts, + ArrayRef<std::string> plugins, DiagnosticsEngine &diags); } // end ento namespace diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index 21ecfc234fbe..36afb4bc5d73 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -7,13 +7,17 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_GR_FRONTENDACTIONS_H -#define LLVM_CLANG_GR_FRONTENDACTIONS_H +#ifndef LLVM_CLANG_STATICANALYZER_FRONTEND_FRONTENDACTIONS_H +#define LLVM_CLANG_STATICANALYZER_FRONTEND_FRONTENDACTIONS_H #include "clang/Frontend/FrontendAction.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" namespace clang { +class Stmt; + namespace ento { //===----------------------------------------------------------------------===// @@ -22,8 +26,29 @@ namespace ento { class AnalysisAction : public ASTFrontendAction { protected: - ASTConsumer *CreateASTConsumer(CompilerInstance &CI, - StringRef InFile) override; + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; +}; + +/// \brief Frontend action to parse model files. +/// +/// This frontend action is responsible for parsing model files. Model files can +/// not be parsed on their own, they rely on type information that is available +/// in another translation unit. The parsing of model files is done by a +/// separate compiler instance that reuses the ASTContext and othen information +/// from the main translation unit that is being compiled. After a model file is +/// parsed, the function definitions will be collected into a StringMap. +class ParseModelFileAction : public ASTFrontendAction { +public: + ParseModelFileAction(llvm::StringMap<Stmt *> &Bodies); + bool isModelParsingAction() const override { return true; } + +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + +private: + llvm::StringMap<Stmt *> &Bodies; }; void printCheckerHelp(raw_ostream &OS, ArrayRef<std::string> plugins); diff --git a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h new file mode 100644 index 000000000000..24f8042587f3 --- /dev/null +++ b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h @@ -0,0 +1,44 @@ +//===-- ModelConsumer.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// \brief This file implements clang::ento::ModelConsumer which is an +/// ASTConsumer for model files. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_GR_MODELCONSUMER_H +#define LLVM_CLANG_GR_MODELCONSUMER_H + +#include "clang/AST/ASTConsumer.h" +#include "llvm/ADT/StringMap.h" + +namespace clang { + +class Stmt; + +namespace ento { + +/// \brief ASTConsumer to consume model files' AST. +/// +/// This consumer collects the bodies of function definitions into a StringMap +/// from a model file. +class ModelConsumer : public ASTConsumer { +public: + ModelConsumer(llvm::StringMap<Stmt *> &Bodies); + + bool HandleTopLevelDecl(DeclGroupRef D) override; + +private: + llvm::StringMap<Stmt *> &Bodies; +}; +} +} + +#endif diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h index 765e7d2e051d..a92e02142005 100644 --- a/include/clang/Tooling/ArgumentsAdjusters.h +++ b/include/clang/Tooling/ArgumentsAdjusters.h @@ -7,59 +7,61 @@ // //===----------------------------------------------------------------------===// // -// This file declares base abstract class ArgumentsAdjuster and its descendants. -// These classes are intended to modify command line arguments obtained from -// a compilation database before they are used to run a frontend action. +// This file declares typedef ArgumentsAdjuster and functions to create several +// useful argument adjusters. +// ArgumentsAdjusters modify command line arguments obtained from a compilation +// database before they are used to run a frontend action. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H #define LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H +#include <functional> #include <string> #include <vector> namespace clang { - namespace tooling { /// \brief A sequence of command line arguments. typedef std::vector<std::string> CommandLineArguments; -/// \brief Abstract interface for a command line adjusters. +/// \brief A prototype of a command line adjuster. /// -/// This abstract interface describes a command line argument adjuster, -/// which is responsible for command line arguments modification before -/// the arguments are used to run a frontend action. -class ArgumentsAdjuster { - virtual void anchor(); -public: - /// \brief Returns adjusted command line arguments. - /// - /// \param Args Input sequence of command line arguments. - /// - /// \returns Modified sequence of command line arguments. - virtual CommandLineArguments Adjust(const CommandLineArguments &Args) = 0; - virtual ~ArgumentsAdjuster() { - } -}; +/// Command line argument adjuster is responsible for command line arguments +/// modification before the arguments are used to run a frontend action. +typedef std::function<CommandLineArguments(const CommandLineArguments &)> + ArgumentsAdjuster; -/// \brief Syntax check only command line adjuster. -/// -/// This class implements ArgumentsAdjuster interface and converts input -/// command line arguments to the "syntax check only" variant. -class ClangSyntaxOnlyAdjuster : public ArgumentsAdjuster { - CommandLineArguments Adjust(const CommandLineArguments &Args) override; -}; +/// \brief Gets an argument adjuster that converts input command line arguments +/// to the "syntax check only" variant. +ArgumentsAdjuster getClangSyntaxOnlyAdjuster(); -/// \brief An argument adjuster which removes output-related command line +/// \brief Gets an argument adjuster which removes output-related command line /// arguments. -class ClangStripOutputAdjuster : public ArgumentsAdjuster { - CommandLineArguments Adjust(const CommandLineArguments &Args) override; -}; +ArgumentsAdjuster getClangStripOutputAdjuster(); + +enum class ArgumentInsertPosition { BEGIN, END }; + +/// \brief Gets an argument adjuster which inserts \p Extra arguments in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster(const CommandLineArguments &Extra, + ArgumentInsertPosition Pos); + +/// \brief Gets an argument adjuster which inserts an \p Extra argument in the +/// specified position. +ArgumentsAdjuster getInsertArgumentAdjuster( + const char *Extra, + ArgumentInsertPosition Pos = ArgumentInsertPosition::END); + +/// \brief Gets an argument adjuster which adjusts the arguments in sequence +/// with the \p First adjuster and then with the \p Second one. +ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, + ArgumentsAdjuster Second); -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang #endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h index 815ede80c233..c23dc9211dc8 100644 --- a/include/clang/Tooling/CommonOptionsParser.h +++ b/include/clang/Tooling/CommonOptionsParser.h @@ -24,8 +24,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H -#define LLVM_TOOLS_CLANG_INCLUDE_CLANG_TOOLING_COMMONOPTIONSPARSER_H +#ifndef LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H +#define LLVM_CLANG_TOOLING_COMMONOPTIONSPARSER_H #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/CommandLine.h" @@ -89,6 +89,8 @@ public: private: std::unique_ptr<CompilationDatabase> Compilations; std::vector<std::string> SourcePathList; + std::vector<std::string> ExtraArgsBefore; + std::vector<std::string> ExtraArgsAfter; }; } // namespace tooling diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h index d1e729a88b27..27c16524e62e 100644 --- a/include/clang/Tooling/CompilationDatabase.h +++ b/include/clang/Tooling/CompilationDatabase.h @@ -25,8 +25,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H -#define LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H +#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H +#define LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" @@ -84,22 +84,22 @@ public: /// FIXME: Currently only supports JSON compilation databases, which /// are named 'compile_commands.json' in the given directory. Extend this /// for other build types (like ninja build files). - static CompilationDatabase *loadFromDirectory(StringRef BuildDirectory, - std::string &ErrorMessage); + static std::unique_ptr<CompilationDatabase> + loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage); /// \brief Tries to detect a compilation database location and load it. /// /// Looks for a compilation database in all parent paths of file 'SourceFile' /// by calling loadFromDirectory. - static CompilationDatabase *autoDetectFromSource(StringRef SourceFile, - std::string &ErrorMessage); + static std::unique_ptr<CompilationDatabase> + autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage); /// \brief Tries to detect a compilation database location and load it. /// /// Looks for a compilation database in directory 'SourceDir' and all /// its parent paths by calling loadFromDirectory. - static CompilationDatabase *autoDetectFromDirectory(StringRef SourceDir, - std::string &ErrorMessage); + static std::unique_ptr<CompilationDatabase> + autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage); /// \brief Returns all compile commands in which the specified file was /// compiled. @@ -142,8 +142,8 @@ public: /// \brief Loads a compilation database from a build directory. /// /// \see CompilationDatabase::loadFromDirectory(). - virtual CompilationDatabase *loadFromDirectory(StringRef Directory, - std::string &ErrorMessage) = 0; + virtual std::unique_ptr<CompilationDatabase> + loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0; }; /// \brief A compilation database that returns a single compile command line. @@ -213,4 +213,4 @@ private: } // end namespace tooling } // end namespace clang -#endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_H +#endif diff --git a/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/include/clang/Tooling/CompilationDatabasePluginRegistry.h index 84fcd24b4a12..7323ec897403 100644 --- a/include/clang/Tooling/CompilationDatabasePluginRegistry.h +++ b/include/clang/Tooling/CompilationDatabasePluginRegistry.h @@ -7,8 +7,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_COMPILATION_DATABASE_PLUGIN_REGISTRY_H -#define LLVM_CLANG_TOOLING_COMPILATION_DATABASE_PLUGIN_REGISTRY_H +#ifndef LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H +#define LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H #include "clang/Tooling/CompilationDatabase.h" #include "llvm/Support/Registry.h" @@ -24,4 +24,4 @@ typedef llvm::Registry<CompilationDatabasePlugin> } // end namespace tooling } // end namespace clang -#endif // LLVM_CLANG_TOOLING_COMPILATION_DATABASE_PLUGIN_REGISTRY_H +#endif diff --git a/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h new file mode 100644 index 000000000000..30a7036c2bb5 --- /dev/null +++ b/include/clang/Tooling/Core/Replacement.h @@ -0,0 +1,229 @@ +//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Classes supporting refactorings that span multiple translation units. +// While single translation unit refactorings are supported via the Rewriter, +// when refactoring multiple translation units changes must be stored in a +// SourceManager independent form, duplicate changes need to be removed, and +// all changes must be applied at once at the end of the refactoring so that +// the code is always parseable. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H +#define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h" +#include <set> +#include <string> +#include <vector> + +namespace clang { + +class Rewriter; + +namespace tooling { + +/// \brief A source range independent of the \c SourceManager. +class Range { +public: + Range() : Offset(0), Length(0) {} + Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {} + + /// \brief Accessors. + /// @{ + unsigned getOffset() const { return Offset; } + unsigned getLength() const { return Length; } + /// @} + + /// \name Range Predicates + /// @{ + /// \brief Whether this range overlaps with \p RHS or not. + bool overlapsWith(Range RHS) const { + return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length; + } + + /// \brief Whether this range contains \p RHS or not. + bool contains(Range RHS) const { + return RHS.Offset >= Offset && + (RHS.Offset + RHS.Length) <= (Offset + Length); + } + /// @} + +private: + unsigned Offset; + unsigned Length; +}; + +/// \brief A text replacement. +/// +/// Represents a SourceManager independent replacement of a range of text in a +/// specific file. +class Replacement { +public: + /// \brief Creates an invalid (not applicable) replacement. + Replacement(); + + /// \brief Creates a replacement of the range [Offset, Offset+Length) in + /// FilePath with ReplacementText. + /// + /// \param FilePath A source file accessible via a SourceManager. + /// \param Offset The byte offset of the start of the range in the file. + /// \param Length The length of the range in bytes. + Replacement(StringRef FilePath, unsigned Offset, + unsigned Length, StringRef ReplacementText); + + /// \brief Creates a Replacement of the range [Start, Start+Length) with + /// ReplacementText. + Replacement(const SourceManager &Sources, SourceLocation Start, unsigned Length, + StringRef ReplacementText); + + /// \brief Creates a Replacement of the given range with ReplacementText. + Replacement(const SourceManager &Sources, const CharSourceRange &Range, + StringRef ReplacementText); + + /// \brief Creates a Replacement of the node with ReplacementText. + template <typename Node> + Replacement(const SourceManager &Sources, const Node &NodeToReplace, + StringRef ReplacementText); + + /// \brief Returns whether this replacement can be applied to a file. + /// + /// Only replacements that are in a valid file can be applied. + bool isApplicable() const; + + /// \brief Accessors. + /// @{ + StringRef getFilePath() const { return FilePath; } + unsigned getOffset() const { return ReplacementRange.getOffset(); } + unsigned getLength() const { return ReplacementRange.getLength(); } + StringRef getReplacementText() const { return ReplacementText; } + /// @} + + /// \brief Applies the replacement on the Rewriter. + bool apply(Rewriter &Rewrite) const; + + /// \brief Returns a human readable string representation. + std::string toString() const; + + private: + void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start, + unsigned Length, StringRef ReplacementText); + void setFromSourceRange(const SourceManager &Sources, + const CharSourceRange &Range, + StringRef ReplacementText); + + std::string FilePath; + Range ReplacementRange; + std::string ReplacementText; +}; + +/// \brief Less-than operator between two Replacements. +bool operator<(const Replacement &LHS, const Replacement &RHS); + +/// \brief Equal-to operator between two Replacements. +bool operator==(const Replacement &LHS, const Replacement &RHS); + +/// \brief A set of Replacements. +/// FIXME: Change to a vector and deduplicate in the RefactoringTool. +typedef std::set<Replacement> Replacements; + +/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. +/// +/// Replacement applications happen independently of the success of +/// other applications. +/// +/// \returns true if all replacements apply. false otherwise. +bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); + +/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. +/// +/// Replacement applications happen independently of the success of +/// other applications. +/// +/// \returns true if all replacements apply. false otherwise. +bool applyAllReplacements(const std::vector<Replacement> &Replaces, + Rewriter &Rewrite); + +/// \brief Applies all replacements in \p Replaces to \p Code. +/// +/// This completely ignores the path stored in each replacement. If one or more +/// replacements cannot be applied, this returns an empty \c string. +std::string applyAllReplacements(StringRef Code, const Replacements &Replaces); + +/// \brief Calculates how a code \p Position is shifted when \p Replaces are +/// applied. +unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position); + +/// \brief Calculates how a code \p Position is shifted when \p Replaces are +/// applied. +/// +/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset(). +unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces, + unsigned Position); + +/// \brief Removes duplicate Replacements and reports if Replacements conflict +/// with one another. All Replacements are assumed to be in the same file. +/// +/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset(). +/// +/// This function sorts \p Replaces so that conflicts can be reported simply by +/// offset into \p Replaces and number of elements in the conflict. +void deduplicate(std::vector<Replacement> &Replaces, + std::vector<Range> &Conflicts); + +/// \brief Collection of Replacements generated from a single translation unit. +struct TranslationUnitReplacements { + /// Name of the main source for the translation unit. + std::string MainSourceFile; + + /// A freeform chunk of text to describe the context of the replacements. + /// Will be printed, for example, when detecting conflicts during replacement + /// deduplication. + std::string Context; + + std::vector<Replacement> Replacements; +}; + +/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. +/// +/// Replacement applications happen independently of the success of +/// other applications. +/// +/// \returns true if all replacements apply. false otherwise. +bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); + +/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. +/// +/// Replacement applications happen independently of the success of +/// other applications. +/// +/// \returns true if all replacements apply. false otherwise. +bool applyAllReplacements(const std::vector<Replacement> &Replaces, + Rewriter &Rewrite); + +/// \brief Applies all replacements in \p Replaces to \p Code. +/// +/// This completely ignores the path stored in each replacement. If one or more +/// replacements cannot be applied, this returns an empty \c string. +std::string applyAllReplacements(StringRef Code, const Replacements &Replaces); + +template <typename Node> +Replacement::Replacement(const SourceManager &Sources, + const Node &NodeToReplace, StringRef ReplacementText) { + const CharSourceRange Range = + CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); + setFromSourceRange(Sources, Range, ReplacementText); +} + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h index be37baff2ffc..745c1645068a 100644 --- a/include/clang/Tooling/FileMatchTrie.h +++ b/include/clang/Tooling/FileMatchTrie.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H -#define LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H +#ifndef LLVM_CLANG_TOOLING_FILEMATCHTRIE_H +#define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" @@ -86,4 +86,4 @@ private: } // end namespace tooling } // end namespace clang -#endif // LLVM_CLANG_TOOLING_FILE_MATCH_TRIE_H +#endif diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h index 1b3335968594..b4edc31652f7 100644 --- a/include/clang/Tooling/JSONCompilationDatabase.h +++ b/include/clang/Tooling/JSONCompilationDatabase.h @@ -12,8 +12,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_JSON_COMPILATION_DATABASE_H -#define LLVM_CLANG_TOOLING_JSON_COMPILATION_DATABASE_H +#ifndef LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H +#define LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H #include "clang/Basic/LLVM.h" #include "clang/Tooling/CompilationDatabase.h" @@ -53,14 +53,14 @@ public: /// /// Returns NULL and sets ErrorMessage if the database could not be /// loaded from the given file. - static JSONCompilationDatabase *loadFromFile(StringRef FilePath, - std::string &ErrorMessage); + static std::unique_ptr<JSONCompilationDatabase> + loadFromFile(StringRef FilePath, std::string &ErrorMessage); /// \brief Loads a JSON compilation database from a data buffer. /// /// Returns NULL and sets ErrorMessage if the database could not be loaded. - static JSONCompilationDatabase *loadFromBuffer(StringRef DatabaseString, - std::string &ErrorMessage); + static std::unique_ptr<JSONCompilationDatabase> + loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage); /// \brief Returns all compile comamnds in which the specified file was /// compiled. @@ -81,8 +81,9 @@ public: private: /// \brief Constructs a JSON compilation database on a memory buffer. - JSONCompilationDatabase(llvm::MemoryBuffer *Database) - : Database(Database), YAMLStream(Database->getBuffer(), SM) {} + JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database) + : Database(std::move(Database)), + YAMLStream(this->Database->getBuffer(), SM) {} /// \brief Parses the database file and creates the index. /// @@ -112,4 +113,4 @@ private: } // end namespace tooling } // end namespace clang -#endif // LLVM_CLANG_TOOLING_JSON_COMPILATION_DATABASE_H +#endif diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h index cd2fb9f6c563..e3e7f83c38c8 100644 --- a/include/clang/Tooling/Refactoring.h +++ b/include/clang/Tooling/Refactoring.h @@ -19,180 +19,16 @@ #ifndef LLVM_CLANG_TOOLING_REFACTORING_H #define LLVM_CLANG_TOOLING_REFACTORING_H -#include "clang/Basic/SourceLocation.h" +#include "clang/Tooling/Core/Replacement.h" #include "clang/Tooling/Tooling.h" -#include "llvm/ADT/StringRef.h" -#include <set> #include <string> namespace clang { class Rewriter; -class SourceLocation; namespace tooling { -/// \brief A source range independent of the \c SourceManager. -class Range { -public: - Range() : Offset(0), Length(0) {} - Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {} - - /// \brief Accessors. - /// @{ - unsigned getOffset() const { return Offset; } - unsigned getLength() const { return Length; } - /// @} - - /// \name Range Predicates - /// @{ - /// \brief Whether this range overlaps with \p RHS or not. - bool overlapsWith(Range RHS) const { - return Offset + Length > RHS.Offset && Offset < RHS.Offset + RHS.Length; - } - - /// \brief Whether this range contains \p RHS or not. - bool contains(Range RHS) const { - return RHS.Offset >= Offset && - (RHS.Offset + RHS.Length) <= (Offset + Length); - } - /// @} - -private: - unsigned Offset; - unsigned Length; -}; - -/// \brief A text replacement. -/// -/// Represents a SourceManager independent replacement of a range of text in a -/// specific file. -class Replacement { -public: - /// \brief Creates an invalid (not applicable) replacement. - Replacement(); - - /// \brief Creates a replacement of the range [Offset, Offset+Length) in - /// FilePath with ReplacementText. - /// - /// \param FilePath A source file accessible via a SourceManager. - /// \param Offset The byte offset of the start of the range in the file. - /// \param Length The length of the range in bytes. - Replacement(StringRef FilePath, unsigned Offset, - unsigned Length, StringRef ReplacementText); - - /// \brief Creates a Replacement of the range [Start, Start+Length) with - /// ReplacementText. - Replacement(const SourceManager &Sources, SourceLocation Start, unsigned Length, - StringRef ReplacementText); - - /// \brief Creates a Replacement of the given range with ReplacementText. - Replacement(const SourceManager &Sources, const CharSourceRange &Range, - StringRef ReplacementText); - - /// \brief Creates a Replacement of the node with ReplacementText. - template <typename Node> - Replacement(const SourceManager &Sources, const Node &NodeToReplace, - StringRef ReplacementText); - - /// \brief Returns whether this replacement can be applied to a file. - /// - /// Only replacements that are in a valid file can be applied. - bool isApplicable() const; - - /// \brief Accessors. - /// @{ - StringRef getFilePath() const { return FilePath; } - unsigned getOffset() const { return ReplacementRange.getOffset(); } - unsigned getLength() const { return ReplacementRange.getLength(); } - StringRef getReplacementText() const { return ReplacementText; } - /// @} - - /// \brief Applies the replacement on the Rewriter. - bool apply(Rewriter &Rewrite) const; - - /// \brief Returns a human readable string representation. - std::string toString() const; - - private: - void setFromSourceLocation(const SourceManager &Sources, SourceLocation Start, - unsigned Length, StringRef ReplacementText); - void setFromSourceRange(const SourceManager &Sources, - const CharSourceRange &Range, - StringRef ReplacementText); - - std::string FilePath; - Range ReplacementRange; - std::string ReplacementText; -}; - -/// \brief Less-than operator between two Replacements. -bool operator<(const Replacement &LHS, const Replacement &RHS); - -/// \brief Equal-to operator between two Replacements. -bool operator==(const Replacement &LHS, const Replacement &RHS); - -/// \brief A set of Replacements. -/// FIXME: Change to a vector and deduplicate in the RefactoringTool. -typedef std::set<Replacement> Replacements; - -/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. -/// -/// Replacement applications happen independently of the success of -/// other applications. -/// -/// \returns true if all replacements apply. false otherwise. -bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); - -/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. -/// -/// Replacement applications happen independently of the success of -/// other applications. -/// -/// \returns true if all replacements apply. false otherwise. -bool applyAllReplacements(const std::vector<Replacement> &Replaces, - Rewriter &Rewrite); - -/// \brief Applies all replacements in \p Replaces to \p Code. -/// -/// This completely ignores the path stored in each replacement. If one or more -/// replacements cannot be applied, this returns an empty \c string. -std::string applyAllReplacements(StringRef Code, const Replacements &Replaces); - -/// \brief Calculates how a code \p Position is shifted when \p Replaces are -/// applied. -unsigned shiftedCodePosition(const Replacements& Replaces, unsigned Position); - -/// \brief Calculates how a code \p Position is shifted when \p Replaces are -/// applied. -/// -/// \pre Replaces[i].getOffset() <= Replaces[i+1].getOffset(). -unsigned shiftedCodePosition(const std::vector<Replacement> &Replaces, - unsigned Position); - -/// \brief Removes duplicate Replacements and reports if Replacements conflict -/// with one another. -/// -/// \post Replaces[i].getOffset() <= Replaces[i+1].getOffset(). -/// -/// This function sorts \p Replaces so that conflicts can be reported simply by -/// offset into \p Replaces and number of elements in the conflict. -void deduplicate(std::vector<Replacement> &Replaces, - std::vector<Range> &Conflicts); - -/// \brief Collection of Replacements generated from a single translation unit. -struct TranslationUnitReplacements { - /// Name of the main source for the translation unit. - std::string MainSourceFile; - - /// A freeform chunk of text to describe the context of the replacements. - /// Will be printed, for example, when detecting conflicts during replacement - /// deduplication. - std::string Context; - - std::vector<Replacement> Replacements; -}; - /// \brief A tool to run refactorings. /// /// This is a refactoring specific version of \see ClangTool. FrontendActions @@ -230,15 +66,7 @@ private: Replacements Replace; }; -template <typename Node> -Replacement::Replacement(const SourceManager &Sources, - const Node &NodeToReplace, StringRef ReplacementText) { - const CharSourceRange Range = - CharSourceRange::getTokenRange(NodeToReplace->getSourceRange()); - setFromSourceRange(Sources, Range, ReplacementText); -} - } // end namespace tooling } // end namespace clang -#endif // end namespace LLVM_CLANG_TOOLING_REFACTORING_H +#endif // LLVM_CLANG_TOOLING_REFACTORING_H diff --git a/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h index 19f277431a3e..6ef9ea11f0ae 100644 --- a/include/clang/Tooling/RefactoringCallbacks.h +++ b/include/clang/Tooling/RefactoringCallbacks.h @@ -26,8 +26,8 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H -#define LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H +#ifndef LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H +#define LLVM_CLANG_TOOLING_REFACTORINGCALLBACKS_H #include "clang/ASTMatchers/ASTMatchFinder.h" #include "clang/Tooling/Refactoring.h" @@ -87,4 +87,4 @@ private: } // end namespace tooling } // end namespace clang -#endif // LLVM_CLANG_TOOLING_REFACTORING_CALLBACKS_H +#endif diff --git a/include/clang/Tooling/ReplacementsYaml.h b/include/clang/Tooling/ReplacementsYaml.h index ac9f46908ffe..4a7666d2c555 100644 --- a/include/clang/Tooling/ReplacementsYaml.h +++ b/include/clang/Tooling/ReplacementsYaml.h @@ -13,8 +13,8 @@ /// //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_TOOLING_REPLACEMENTS_YAML_H -#define LLVM_CLANG_TOOLING_REPLACEMENTS_YAML_H +#ifndef LLVM_CLANG_TOOLING_REPLACEMENTSYAML_H +#define LLVM_CLANG_TOOLING_REPLACEMENTSYAML_H #include "clang/Tooling/Refactoring.h" #include "llvm/Support/YAMLTraits.h" @@ -73,4 +73,4 @@ template <> struct MappingTraits<clang::tooling::TranslationUnitReplacements> { } // end namespace yaml } // end namespace llvm -#endif // LLVM_CLANG_TOOLING_REPLACEMENTS_YAML_H +#endif diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 769acd325367..393cc1deace5 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -30,6 +30,7 @@ #ifndef LLVM_CLANG_TOOLING_TOOLING_H #define LLVM_CLANG_TOOLING_TOOLING_H +#include "clang/AST/ASTConsumer.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" @@ -142,6 +143,10 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, const Twine &FileName = "input.cc"); +/// The first part of the pair is the filename, the second part the +/// file-content. +typedef std::vector<std::pair<std::string, std::string>> FileContentMappings; + /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and /// with additional other flags. /// @@ -151,9 +156,10 @@ bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, /// \param FileName The file name which 'Code' will be mapped as. /// /// \return - True if 'ToolAction' was successfully executed. -bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code, - const std::vector<std::string> &Args, - const Twine &FileName = "input.cc"); +bool runToolOnCodeWithArgs( + clang::FrontendAction *ToolAction, const Twine &Code, + const std::vector<std::string> &Args, const Twine &FileName = "input.cc", + const FileContentMappings &VirtualMappedFiles = FileContentMappings()); /// \brief Builds an AST for 'Code'. /// @@ -202,7 +208,9 @@ class ToolInvocation { ~ToolInvocation(); /// \brief Set a \c DiagnosticConsumer to use during parsing. - void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer); + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { + this->DiagConsumer = DiagConsumer; + } /// \brief Map a virtual file to be used while running the tool. /// @@ -249,10 +257,12 @@ class ClangTool { ClangTool(const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths); - virtual ~ClangTool() { clearArgumentsAdjusters(); } + ~ClangTool(); /// \brief Set a \c DiagnosticConsumer to use during parsing. - void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer); + void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { + this->DiagConsumer = DiagConsumer; + } /// \brief Map a virtual file to be used while running the tool. /// @@ -260,19 +270,11 @@ class ClangTool { /// \param Content A null terminated buffer of the file's content. void mapVirtualFile(StringRef FilePath, StringRef Content); - /// \brief Install command line arguments adjuster. - /// - /// \param Adjuster Command line arguments adjuster. - // - /// FIXME: Function is deprecated. Use (clear/append)ArgumentsAdjuster instead. - /// Remove it once all callers are gone. - void setArgumentsAdjuster(ArgumentsAdjuster *Adjuster); - /// \brief Append a command line arguments adjuster to the adjuster chain. /// /// \param Adjuster An argument adjuster, which will be run on the output of /// previous argument adjusters. - void appendArgumentsAdjuster(ArgumentsAdjuster *Adjuster); + void appendArgumentsAdjuster(ArgumentsAdjuster Adjuster); /// \brief Clear the command line arguments adjuster chain. void clearArgumentsAdjusters(); @@ -292,14 +294,14 @@ class ClangTool { FileManager &getFiles() { return *Files; } private: - // We store compile commands as pair (file name, compile command). - std::vector< std::pair<std::string, CompileCommand> > CompileCommands; + const CompilationDatabase &Compilations; + std::vector<std::string> SourcePaths; llvm::IntrusiveRefCntPtr<FileManager> Files; // Contains a list of pairs (<file name>, <file content>). std::vector< std::pair<StringRef, StringRef> > MappedFileContents; - SmallVector<ArgumentsAdjuster *, 2> ArgsAdjusters; + ArgumentsAdjuster ArgsAdjuster; DiagnosticConsumer *DiagConsumer; }; @@ -335,8 +337,8 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( SourceFileCallbacks *Callbacks) : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} - clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &, - StringRef) override { + std::unique_ptr<clang::ASTConsumer> + CreateASTConsumer(clang::CompilerInstance &, StringRef) override { return ConsumerFactory->newASTConsumer(); } diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap index 03806016cc48..5058d15025d8 100644 --- a/include/clang/module.modulemap +++ b/include/clang/module.modulemap @@ -39,6 +39,7 @@ module Clang_Basic { exclude header "Basic/BuiltinsR600.def" exclude header "Basic/BuiltinsX86.def" exclude header "Basic/BuiltinsXCore.def" + exclude header "Basic/BuiltinsLe64.def" exclude header "Basic/DiagnosticOptions.def" exclude header "Basic/LangOptions.def" exclude header "Basic/OpenCLExtensions.def" @@ -47,9 +48,6 @@ module Clang_Basic { exclude header "Basic/Sanitizers.def" exclude header "Basic/TokenKinds.def" - // This file is one big layering violation. - exclude header "Basic/AllDiagnostics.h" - // This file includes a header from Lex. exclude header "Basic/PlistSupport.h" @@ -62,6 +60,24 @@ module Clang_Basic { module Clang_CodeGen { requires cplusplus umbrella "CodeGen" module * { export * } } module Clang_Config { requires cplusplus umbrella "Config" module * { export * } } +// Files for diagnostic groups are spread all over the include/clang/ tree, but +// logically form a single module. +module Clang_Diagnostics { + requires cplusplus + + module All { header "Basic/AllDiagnostics.h" export * } + module Analysis { header "Analysis/AnalysisDiagnostic.h" export * } + module AST { header "AST/ASTDiagnostic.h" export * } + module Comment { header "AST/CommentDiagnostic.h" export * } + module Driver { header "Driver/DriverDiagnostic.h" export * } + module Frontend { header "Frontend/FrontendDiagnostic.h" export * } + module Lex { header "Lex/LexDiagnostic.h" export * } + module Parse { header "Parse/ParseDiagnostic.h" export * } + // FIXME: This breaks the build of Clang_Sema, for unknown reasons. + //module Sema { header "Sema/SemaDiagnostic.h" export * } + module Serialization { header "Serialization/SerializationDiagnostic.h" export * } +} + module Clang_Driver { requires cplusplus umbrella "Driver" @@ -101,9 +117,6 @@ module Clang_StaticAnalyzer { // This file is intended for repeated textual inclusion. exclude header "StaticAnalyzer/Core/Analyses.def" - // FIXME: This is logically a part of Basic, but has been put in the wrong place. - exclude header "StaticAnalyzer/Core/AnalyzerOptions.h" - module * { export * } } |