diff options
Diffstat (limited to 'include/clang')
405 files changed, 27903 insertions, 18567 deletions
diff --git a/include/clang/ARCMigrate/ARCMT.h b/include/clang/ARCMigrate/ARCMT.h index 74081867eebc2..30c24f1cdb10e 100644 --- a/include/clang/ARCMigrate/ARCMT.h +++ b/include/clang/ARCMigrate/ARCMT.h @@ -22,7 +22,7 @@ namespace clang { namespace arcmt { class MigrationPass; -/// \brief Creates an AST with the provided CompilerInvocation but with these +/// Creates an AST with the provided CompilerInvocation but with these /// changes: /// -if a PCH/PTH is set, the original header is used instead /// -Automatic Reference Counting mode is enabled @@ -45,7 +45,7 @@ checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input, bool emitPremigrationARCErrors = false, StringRef plistOut = StringRef()); -/// \brief Works similar to checkForManualIssues but instead of checking, it +/// Works similar to checkForManualIssues but instead of checking, it /// applies automatic modifications to source files to conform to ARC. /// /// \returns false if no error is produced, true otherwise. @@ -55,7 +55,7 @@ applyTransformations(CompilerInvocation &origCI, std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticConsumer *DiagClient); -/// \brief Applies automatic modifications and produces temporary files +/// Applies automatic modifications and produces temporary files /// and metadata into the \p outputDir path. /// /// \param emitPremigrationARCErrors if true all ARC errors will get emitted @@ -72,7 +72,7 @@ bool migrateWithTemporaryFiles( DiagnosticConsumer *DiagClient, StringRef outputDir, bool emitPremigrationARCErrors, StringRef plistOut); -/// \brief Get the set of file remappings from the \p outputDir path that +/// Get the set of file remappings from the \p outputDir path that /// migrateWithTemporaryFiles produced. /// /// \returns false if no error is produced, true otherwise. @@ -80,7 +80,7 @@ bool getFileRemappings(std::vector<std::pair<std::string,std::string> > &remap, StringRef outputDir, DiagnosticConsumer *DiagClient); -/// \brief Get the set of file remappings from a list of files with remapping +/// Get the set of file remappings from a list of files with remapping /// info. /// /// \returns false if no error is produced, true otherwise. diff --git a/include/clang/ARCMigrate/ARCMTActions.h b/include/clang/ARCMigrate/ARCMTActions.h index 554e0c0c6d028..2571ca75be515 100644 --- a/include/clang/ARCMigrate/ARCMTActions.h +++ b/include/clang/ARCMigrate/ARCMTActions.h @@ -55,7 +55,7 @@ public: bool emitPremigrationARCErrors); }; -/// \brief Migrates to modern ObjC syntax. +/// Migrates to modern ObjC syntax. class ObjCMigrateAction : public WrapperFrontendAction { std::string MigrateDir; unsigned ObjCMigAction; diff --git a/include/clang/AST/APValue.h b/include/clang/AST/APValue.h index 7c431f3be8c4c..d4057c9da5f38 100644 --- a/include/clang/AST/APValue.h +++ b/include/clang/AST/APValue.h @@ -53,7 +53,58 @@ public: MemberPointer, AddrLabelDiff }; - typedef llvm::PointerUnion<const ValueDecl *, const Expr *> LValueBase; + + class LValueBase { + public: + typedef llvm::PointerUnion<const ValueDecl *, const Expr *> PtrTy; + + LValueBase() : CallIndex(0), Version(0) {} + + template <class T> + LValueBase(T P, unsigned I = 0, unsigned V = 0) + : Ptr(P), CallIndex(I), Version(V) {} + + template <class T> + bool is() const { return Ptr.is<T>(); } + + template <class T> + T get() const { return Ptr.get<T>(); } + + template <class T> + T dyn_cast() const { return Ptr.dyn_cast<T>(); } + + void *getOpaqueValue() const; + + bool isNull() const; + + explicit operator bool () const; + + PtrTy getPointer() const { + return Ptr; + } + + unsigned getCallIndex() const { + return CallIndex; + } + + void setCallIndex(unsigned Index) { + CallIndex = Index; + } + + unsigned getVersion() const { + return Version; + } + + bool operator==(const LValueBase &Other) const { + return Ptr == Other.Ptr && CallIndex == Other.CallIndex && + Version == Other.Version; + } + + private: + PtrTy Ptr; + unsigned CallIndex, Version; + }; + typedef llvm::PointerIntPair<const Decl *, 1, bool> BaseOrMemberType; union LValuePathEntry { /// BaseOrMember - The FieldDecl or CXXRecordDecl indicating the next item @@ -135,15 +186,15 @@ public: } APValue(const APValue &RHS); APValue(APValue &&RHS) : Kind(Uninitialized) { swap(RHS); } - APValue(LValueBase B, const CharUnits &O, NoLValuePath N, unsigned CallIndex, + APValue(LValueBase B, const CharUnits &O, NoLValuePath N, bool IsNullPtr = false) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O, N, CallIndex, IsNullPtr); + MakeLValue(); setLValue(B, O, N, IsNullPtr); } APValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, - bool OnePastTheEnd, unsigned CallIndex, bool IsNullPtr = false) + bool OnePastTheEnd, bool IsNullPtr = false) : Kind(Uninitialized) { - MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, CallIndex, IsNullPtr); + MakeLValue(); setLValue(B, O, Path, OnePastTheEnd, IsNullPtr); } APValue(UninitArray, unsigned InitElts, unsigned Size) : Kind(Uninitialized) { MakeArray(InitElts, Size); @@ -168,14 +219,14 @@ public: MakeUninit(); } - /// \brief Returns whether the object performed allocations. + /// Returns whether the object performed allocations. /// /// If APValues are constructed via placement new, \c needsCleanup() /// indicates whether the destructor must be called in order to correctly /// free all allocated memory. bool needsCleanup() const; - /// \brief Swaps the contents of this and the given APValue. + /// Swaps the contents of this and the given APValue. void swap(APValue &RHS); ValueKind getKind() const { return Kind; } @@ -255,6 +306,7 @@ public: bool hasLValuePath() const; ArrayRef<LValuePathEntry> getLValuePath() const; unsigned getLValueCallIndex() const; + unsigned getLValueVersion() const; bool isNullPointer() const; APValue &getVectorElt(unsigned I) { @@ -376,10 +428,10 @@ public: ((ComplexAPFloat *)(char *)Data.buffer)->Imag = std::move(I); } void setLValue(LValueBase B, const CharUnits &O, NoLValuePath, - unsigned CallIndex, bool IsNullPtr); + bool IsNullPtr); void setLValue(LValueBase B, const CharUnits &O, ArrayRef<LValuePathEntry> Path, bool OnePastTheEnd, - unsigned CallIndex, bool IsNullPtr); + bool IsNullPtr); void setUnion(const FieldDecl *Field, const APValue &Value) { assert(isUnion() && "Invalid accessor"); ((UnionData*)(char*)Data.buffer)->Field = Field; @@ -451,4 +503,14 @@ private: } // end namespace clang. +namespace llvm { +template<> struct DenseMapInfo<clang::APValue::LValueBase> { + static clang::APValue::LValueBase getEmptyKey(); + static clang::APValue::LValueBase getTombstoneKey(); + static unsigned getHashValue(const clang::APValue::LValueBase &Base); + static bool isEqual(const clang::APValue::LValueBase &LHS, + const clang::APValue::LValueBase &RHS); +}; +} + #endif diff --git a/include/clang/AST/ASTConsumer.h b/include/clang/AST/ASTConsumer.h index ad368c86c79c8..1167c566a35f3 100644 --- a/include/clang/AST/ASTConsumer.h +++ b/include/clang/AST/ASTConsumer.h @@ -32,7 +32,7 @@ namespace clang { /// clients that read ASTs. This abstraction layer allows the client to be /// independent of the AST producer (e.g. parser vs AST dump file reader, etc). class ASTConsumer { - /// \brief Whether this AST consumer also requires information about + /// Whether this AST consumer also requires information about /// semantic analysis. bool SemaConsumer; @@ -53,7 +53,7 @@ public: /// \returns true to continue parsing, or false to abort parsing. virtual bool HandleTopLevelDecl(DeclGroupRef D); - /// \brief This callback is invoked each time an inline (method or friend) + /// This callback is invoked each time an inline (method or friend) /// function definition in a class is completed. virtual void HandleInlineFunctionDefinition(FunctionDecl *D) {} @@ -72,22 +72,22 @@ public: /// can be defined in declspecs). virtual void HandleTagDeclDefinition(TagDecl *D) {} - /// \brief This callback is invoked the first time each TagDecl is required to + /// This callback is invoked the first time each TagDecl is required to /// be complete. virtual void HandleTagDeclRequiredDefinition(const TagDecl *D) {} - /// \brief Invoked when a function is implicitly instantiated. + /// Invoked when a function is implicitly instantiated. /// Note that at this point point it does not have a body, its body is /// instantiated at the end of the translation unit and passed to /// HandleTopLevelDecl. virtual void HandleCXXImplicitFunctionInstantiation(FunctionDecl *D) {} - /// \brief Handle the specified top-level declaration that occurred inside + /// Handle the specified top-level declaration that occurred inside /// and ObjC container. /// The default implementation ignored them. virtual void HandleTopLevelDeclInObjCContainer(DeclGroupRef D); - /// \brief Handle an ImportDecl that was implicitly created due to an + /// Handle an ImportDecl that was implicitly created due to an /// inclusion directive. /// The default implementation passes it to HandleTopLevelDecl. virtual void HandleImplicitImportDecl(ImportDecl *D); @@ -103,7 +103,7 @@ public: /// modified by the introduction of an implicit zero initializer. virtual void CompleteTentativeDefinition(VarDecl *D) {} - /// \brief Callback invoked when an MSInheritanceAttr has been attached to a + /// Callback invoked when an MSInheritanceAttr has been attached to a /// CXXRecordDecl. virtual void AssignInheritanceModel(CXXRecordDecl *RD) {} @@ -111,19 +111,19 @@ public: // variable has been instantiated. virtual void HandleCXXStaticMemberVarInstantiation(VarDecl *D) {} - /// \brief Callback involved at the end of a translation unit to + /// Callback involved at the end of a translation unit to /// notify the consumer that a vtable for the given C++ class is /// required. /// /// \param RD The class whose vtable was used. virtual void HandleVTable(CXXRecordDecl *RD) {} - /// \brief If the consumer is interested in entities getting modified after + /// If the consumer is interested in entities getting modified after /// their initial creation, it should return a pointer to /// an ASTMutationListener here. virtual ASTMutationListener *GetASTMutationListener() { return nullptr; } - /// \brief If the consumer is interested in entities being deserialized from + /// If the consumer is interested in entities being deserialized from /// AST files, it should return a pointer to a ASTDeserializationListener here virtual ASTDeserializationListener *GetASTDeserializationListener() { return nullptr; @@ -132,7 +132,7 @@ public: /// PrintStats - If desired, print any statistics. virtual void PrintStats() {} - /// \brief This callback is called for each function if the Parser was + /// This callback is called for each function if the Parser was /// initialized with \c SkipFunctionBodies set to \c true. /// /// \return \c true if the function's body should be skipped. The function diff --git a/include/clang/AST/ASTContext.h b/include/clang/AST/ASTContext.h index a5d080035df00..c6f8e2973e8e7 100644 --- a/include/clang/AST/ASTContext.h +++ b/include/clang/AST/ASTContext.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::ASTContext interface. +/// Defines the clang::ASTContext interface. // //===----------------------------------------------------------------------===// @@ -18,6 +18,7 @@ #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/CanonicalType.h" #include "clang/AST/CommentCommandTraits.h" +#include "clang/AST/ComparisonCategories.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" @@ -144,7 +145,7 @@ struct TypeInfo { : Width(Width), Align(Align), AlignIsRequired(AlignIsRequired) {} }; -/// \brief Holds long-lived AST nodes (such as types and decls) that can be +/// 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> { friend class NestedNameSpecifier; @@ -167,6 +168,7 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::FoldingSet<DependentAddressSpaceType> DependentAddressSpaceTypes; mutable llvm::FoldingSet<VectorType> VectorTypes; + mutable llvm::FoldingSet<DependentVectorType> DependentVectorTypes; mutable llvm::FoldingSet<FunctionNoProtoType> FunctionNoProtoTypes; mutable llvm::ContextualFoldingSet<FunctionProtoType, ASTContext&> FunctionProtoTypes; @@ -206,13 +208,13 @@ class ASTContext : public RefCountedBase<ASTContext> { ASTContext&> SubstTemplateTemplateParmPacks; - /// \brief The set of nested name specifiers. + /// The set of nested name specifiers. /// /// This set is managed by the NestedNameSpecifier class. mutable llvm::FoldingSet<NestedNameSpecifier> NestedNameSpecifiers; mutable NestedNameSpecifier *GlobalNestedNameSpecifier = nullptr; - /// \brief A cache mapping from RecordDecls to ASTRecordLayouts. + /// A cache mapping from RecordDecls to ASTRecordLayouts. /// /// This is lazily created. This is intentionally not serialized. mutable llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*> @@ -220,35 +222,35 @@ class ASTContext : public RefCountedBase<ASTContext> { mutable llvm::DenseMap<const ObjCContainerDecl*, const ASTRecordLayout*> ObjCLayouts; - /// \brief A cache from types to size and alignment information. + /// A cache from types to size and alignment information. using TypeInfoMap = llvm::DenseMap<const Type *, struct TypeInfo>; mutable TypeInfoMap MemoizedTypeInfo; - /// \brief A cache mapping from CXXRecordDecls to key functions. + /// A cache mapping from CXXRecordDecls to key functions. llvm::DenseMap<const CXXRecordDecl*, LazyDeclPtr> KeyFunctions; - /// \brief Mapping from ObjCContainers to their ObjCImplementations. + /// Mapping from ObjCContainers to their ObjCImplementations. llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*> ObjCImpls; - /// \brief Mapping from ObjCMethod to its duplicate declaration in the same + /// Mapping from ObjCMethod to its duplicate declaration in the same /// interface. llvm::DenseMap<const ObjCMethodDecl*,const ObjCMethodDecl*> ObjCMethodRedecls; - /// \brief Mapping from __block VarDecls to their copy initialization expr. + /// Mapping from __block VarDecls to their copy initialization expr. llvm::DenseMap<const VarDecl*, Expr*> BlockVarCopyInits; - /// \brief Mapping from class scope functions specialization to their + /// Mapping from class scope functions specialization to their /// template patterns. llvm::DenseMap<const FunctionDecl*, FunctionDecl*> ClassScopeSpecializationPattern; - /// \brief Mapping from materialized temporaries with static storage duration + /// Mapping from materialized temporaries with static storage duration /// that appear in constant initializers to their evaluated values. These are /// allocated in a std::map because their address must be stable. llvm::DenseMap<const MaterializeTemporaryExpr *, APValue *> MaterializedTemporaryValues; - /// \brief Representation of a "canonical" template template parameter that + /// Representation of a "canonical" template template parameter that /// is used in canonical template names. class CanonicalTemplateTemplateParm : public llvm::FoldingSetNode { TemplateTemplateParmDecl *Parm; @@ -270,32 +272,32 @@ class ASTContext : public RefCountedBase<ASTContext> { TemplateTemplateParmDecl * getCanonicalTemplateTemplateParmDecl(TemplateTemplateParmDecl *TTP) const; - /// \brief The typedef for the __int128_t type. + /// The typedef for the __int128_t type. mutable TypedefDecl *Int128Decl = nullptr; - /// \brief The typedef for the __uint128_t type. + /// The typedef for the __uint128_t type. mutable TypedefDecl *UInt128Decl = nullptr; - /// \brief The typedef for the target specific predefined + /// The typedef for the target specific predefined /// __builtin_va_list type. mutable TypedefDecl *BuiltinVaListDecl = nullptr; /// The typedef for the predefined \c __builtin_ms_va_list type. mutable TypedefDecl *BuiltinMSVaListDecl = nullptr; - /// \brief The typedef for the predefined \c id type. + /// The typedef for the predefined \c id type. mutable TypedefDecl *ObjCIdDecl = nullptr; - /// \brief The typedef for the predefined \c SEL type. + /// The typedef for the predefined \c SEL type. mutable TypedefDecl *ObjCSelDecl = nullptr; - /// \brief The typedef for the predefined \c Class type. + /// The typedef for the predefined \c Class type. mutable TypedefDecl *ObjCClassDecl = nullptr; - /// \brief The typedef for the predefined \c Protocol class in Objective-C. + /// The typedef for the predefined \c Protocol class in Objective-C. mutable ObjCInterfaceDecl *ObjCProtocolClassDecl = nullptr; - /// \brief The typedef for the predefined 'BOOL' type. + /// The typedef for the predefined 'BOOL' type. mutable TypedefDecl *BOOLDecl = nullptr; // Typedefs which may be provided defining the structure of Objective-C @@ -327,53 +329,53 @@ class ASTContext : public RefCountedBase<ASTContext> { QualType ObjCNSStringType; - /// \brief The typedef declaration for the Objective-C "instancetype" type. + /// The typedef declaration for the Objective-C "instancetype" type. TypedefDecl *ObjCInstanceTypeDecl = nullptr; - /// \brief The type for the C FILE type. + /// The type for the C FILE type. TypeDecl *FILEDecl = nullptr; - /// \brief The type for the C jmp_buf type. + /// The type for the C jmp_buf type. TypeDecl *jmp_bufDecl = nullptr; - /// \brief The type for the C sigjmp_buf type. + /// The type for the C sigjmp_buf type. TypeDecl *sigjmp_bufDecl = nullptr; - /// \brief The type for the C ucontext_t type. + /// The type for the C ucontext_t type. TypeDecl *ucontext_tDecl = nullptr; - /// \brief Type for the Block descriptor for Blocks CodeGen. + /// Type for the Block descriptor for Blocks CodeGen. /// /// Since this is only used for generation of debug info, it is not /// serialized. mutable RecordDecl *BlockDescriptorType = nullptr; - /// \brief Type for the Block descriptor for Blocks CodeGen. + /// Type for the Block descriptor for Blocks CodeGen. /// /// Since this is only used for generation of debug info, it is not /// serialized. mutable RecordDecl *BlockDescriptorExtendedType = nullptr; - /// \brief Declaration for the CUDA cudaConfigureCall function. + /// Declaration for the CUDA cudaConfigureCall function. FunctionDecl *cudaConfigureCallDecl = nullptr; - /// \brief Keeps track of all declaration attributes. + /// Keeps track of all declaration attributes. /// /// Since so few decls have attrs, we keep them in a hash map instead of /// wasting space in the Decl class. llvm::DenseMap<const Decl*, AttrVec*> DeclAttrs; - /// \brief A mapping from non-redeclarable declarations in modules that were + /// A mapping from non-redeclarable declarations in modules that were /// merged with other declarations to the canonical declaration that they were /// merged into. llvm::DenseMap<Decl*, Decl*> MergedDecls; - /// \brief A mapping from a defining declaration to a list of modules (other + /// A mapping from a defining declaration to a list of modules (other /// than the owning module of the declaration) that contain merged /// definitions of that entity. llvm::DenseMap<NamedDecl*, llvm::TinyPtrVector<Module*>> MergedDefModules; - /// \brief Initializers for a module, in order. Each Decl will be either + /// Initializers for a module, in order. Each Decl will be either /// something that has a semantic effect on startup (such as a variable with /// a non-constant initializer), or an ImportDecl (which recursively triggers /// initialization of another module). @@ -388,7 +390,7 @@ class ASTContext : public RefCountedBase<ASTContext> { ASTContext &this_() { return *this; } public: - /// \brief A type synonym for the TemplateOrInstantiation mapping. + /// A type synonym for the TemplateOrInstantiation mapping. using TemplateOrSpecializationInfo = llvm::PointerUnion<VarTemplateDecl *, MemberSpecializationInfo *>; @@ -398,7 +400,7 @@ private: friend class ASTWriter; friend class CXXRecordDecl; - /// \brief A mapping to contain the template or declaration that + /// A mapping to contain the template or declaration that /// a variable declaration describes or was instantiated from, /// respectively. /// @@ -431,7 +433,7 @@ private: llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo> TemplateOrInstantiation; - /// \brief Keeps track of the declaration from which a using declaration was + /// Keeps track of the declaration from which a using declaration was /// created during instantiation. /// /// The source and target declarations are always a UsingDecl, an @@ -461,7 +463,7 @@ private: llvm::DenseMap<FieldDecl *, FieldDecl *> InstantiatedFromUnnamedFieldDecl; - /// \brief Mapping that stores the methods overridden by a given C++ + /// Mapping that stores the methods overridden by a given C++ /// member function. /// /// Since most C++ member functions aren't virtual and therefore @@ -470,18 +472,18 @@ private: using CXXMethodVector = llvm::TinyPtrVector<const CXXMethodDecl *>; llvm::DenseMap<const CXXMethodDecl *, CXXMethodVector> OverriddenMethods; - /// \brief Mapping from each declaration context to its corresponding + /// Mapping from each declaration context to its corresponding /// mangling numbering context (used for constructs like lambdas which /// need to be consistently numbered for the mangler). llvm::DenseMap<const DeclContext *, std::unique_ptr<MangleNumberingContext>> MangleNumberingContexts; - /// \brief Side-table of mangling numbers for declarations which rarely + /// Side-table of mangling numbers for declarations which rarely /// need them (like static local vars). llvm::MapVector<const NamedDecl *, unsigned> MangleNumbers; llvm::MapVector<const VarDecl *, unsigned> StaticLocalNumbers; - /// \brief Mapping that stores parameterIndex values for ParmVarDecls when + /// Mapping that stores parameterIndex values for ParmVarDecls when /// that value exceeds the bitfield size of ParmVarDeclBits.ParameterIndex. using ParameterIndexTable = llvm::DenseMap<const VarDecl *, unsigned>; ParameterIndexTable ParamIndices; @@ -494,38 +496,38 @@ private: mutable BuiltinTemplateDecl *MakeIntegerSeqDecl = nullptr; mutable BuiltinTemplateDecl *TypePackElementDecl = nullptr; - /// \brief The associated SourceManager object. + /// The associated SourceManager object. SourceManager &SourceMgr; - /// \brief The language options used to create the AST associated with + /// The language options used to create the AST associated with /// this ASTContext object. LangOptions &LangOpts; - /// \brief Blacklist object that is used by sanitizers to decide which + /// Blacklist object that is used by sanitizers to decide which /// entities should not be instrumented. std::unique_ptr<SanitizerBlacklist> SanitizerBL; - /// \brief Function filtering mechanism to determine whether a given function + /// Function filtering mechanism to determine whether a given function /// should be imbued with the XRay "always" or "never" attributes. std::unique_ptr<XRayFunctionFilter> XRayFilter; - /// \brief The allocator used to create AST objects. + /// The allocator used to create AST objects. /// /// AST objects are never destructed; rather, all memory associated with the /// AST objects will be released when the ASTContext itself is destroyed. mutable llvm::BumpPtrAllocator BumpAlloc; - /// \brief Allocator for partial diagnostics. + /// Allocator for partial diagnostics. PartialDiagnostic::StorageAllocator DiagAllocator; - /// \brief The current C++ ABI. + /// The current C++ ABI. std::unique_ptr<CXXABI> ABI; CXXABI *createCXXABI(const TargetInfo &T); - /// \brief The logical -> physical address space map. + /// The logical -> physical address space map. const LangASMap *AddrSpaceMap = nullptr; - /// \brief Address space map mangling must be used with language specific + /// Address space map mangling must be used with language specific /// address spaces (e.g. OpenCL/CUDA) bool AddrSpaceMapMangling; @@ -541,10 +543,10 @@ public: IntrusiveRefCntPtr<ExternalASTSource> ExternalSource; ASTMutationListener *Listener = nullptr; - /// \brief Contains parents of a node. + /// Contains parents of a node. using ParentVector = llvm::SmallVector<ast_type_traits::DynTypedNode, 2>; - /// \brief Maps from a node to its parents. This is used for nodes that have + /// Maps from a node to its parents. This is used for nodes that have /// pointer identity only, which are more common and we can save space by /// only storing a unique pointer to them. using ParentMapPointers = @@ -602,7 +604,7 @@ public: } }; - /// \brief Returns the parents of the given node. + /// Returns the parents of the given node. /// /// Note that this will lazily compute the parents of all nodes /// and store them for later retrieval. Thus, the first call is O(n) @@ -701,10 +703,10 @@ public: return FullSourceLoc(Loc,SourceMgr); } - /// \brief All comments in this translation unit. + /// All comments in this translation unit. RawCommentList Comments; - /// \brief True if comments are already loaded from ExternalASTSource. + /// True if comments are already loaded from ExternalASTSource. mutable bool CommentsLoaded = false; class RawCommentAndCacheFlags { @@ -761,18 +763,18 @@ public: const Decl *OriginalDecl; }; - /// \brief Mapping from declarations to comments attached to any + /// Mapping from declarations to comments attached to any /// redeclaration. /// /// Raw comments are owned by Comments list. This mapping is populated /// lazily. mutable llvm::DenseMap<const Decl *, RawCommentAndCacheFlags> RedeclComments; - /// \brief Mapping from declarations to parsed comments attached to any + /// Mapping from declarations to parsed comments attached to any /// redeclaration. mutable llvm::DenseMap<const Decl *, comments::FullComment *> ParsedComments; - /// \brief Return the documentation comment attached to a given declaration, + /// Return the documentation comment attached to a given declaration, /// without looking into cache. RawComment *getRawCommentForDeclNoCache(const Decl *D) const; @@ -784,10 +786,10 @@ public: void addComment(const RawComment &RC) { assert(LangOpts.RetainCommentsFromSystemHeaders || !SourceMgr.isInSystemHeader(RC.getSourceRange().getBegin())); - Comments.addComment(RC, BumpAlloc); + Comments.addComment(RC, LangOpts.CommentOpts, BumpAlloc); } - /// \brief Return the documentation comment attached to a given declaration. + /// Return the documentation comment attached to a given declaration. /// Returns nullptr if no comment is attached. /// /// \param OriginalDecl if not nullptr, is set to declaration AST node that @@ -815,7 +817,7 @@ public: private: mutable comments::CommandTraits CommentCommandTraits; - /// \brief Iterator that visits import declarations. + /// Iterator that visits import declarations. class import_iterator { ImportDecl *Import = nullptr; @@ -857,13 +859,13 @@ public: return CommentCommandTraits; } - /// \brief Retrieve the attributes for the given declaration. + /// Retrieve the attributes for the given declaration. AttrVec& getDeclAttrs(const Decl *D); - /// \brief Erase the attributes corresponding to the given declaration. + /// Erase the attributes corresponding to the given declaration. void eraseDeclAttrs(const Decl *D); - /// \brief If this variable is an instantiated static data member of a + /// If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. // FIXME: Remove ? @@ -878,7 +880,7 @@ public: void setClassScopeSpecializationPattern(FunctionDecl *FD, FunctionDecl *Pattern); - /// \brief Note that the static data member \p Inst is an instantiation of + /// Note that the static data member \p Inst is an instantiation of /// the static data member template \p Tmpl of a class template. void setInstantiatedFromStaticDataMember(VarDecl *Inst, VarDecl *Tmpl, TemplateSpecializationKind TSK, @@ -887,12 +889,12 @@ public: void setTemplateOrSpecializationInfo(VarDecl *Inst, TemplateOrSpecializationInfo TSI); - /// \brief If the given using decl \p Inst is an instantiation of a + /// If the given using decl \p Inst is an instantiation of a /// (possibly unresolved) using decl from a template instantiation, /// return it. NamedDecl *getInstantiatedFromUsingDecl(NamedDecl *Inst); - /// \brief Remember that the using decl \p Inst is an instantiation + /// Remember that the using decl \p Inst is an instantiation /// of the using decl \p Pattern of a class template. void setInstantiatedFromUsingDecl(NamedDecl *Inst, NamedDecl *Pattern); @@ -919,12 +921,12 @@ public: overridden_method_range overridden_methods(const CXXMethodDecl *Method) const; - /// \brief Note that the given C++ \p Method overrides the given \p + /// Note that the given C++ \p Method overrides the given \p /// Overridden method. void addOverriddenMethod(const CXXMethodDecl *Method, const CXXMethodDecl *Overridden); - /// \brief Return C++ or ObjC overridden methods for the given \p Method. + /// Return C++ or ObjC overridden methods for the given \p Method. /// /// An ObjC method is considered to override any method in the class's /// base classes, its protocols, or its categories' protocols, that has @@ -935,7 +937,7 @@ public: const NamedDecl *Method, SmallVectorImpl<const NamedDecl *> &Overridden) const; - /// \brief Notify the AST context that a new import declaration has been + /// Notify the AST context that a new import declaration has been /// parsed or implicitly created within this translation unit. void addedLocalImportDecl(ImportDecl *Import); @@ -957,16 +959,16 @@ public: MergedDecls[D] = Primary; } - /// \brief Note that the definition \p ND has been merged into module \p M, + /// Note that the definition \p ND has been merged into module \p M, /// and should be visible whenever \p M is visible. void mergeDefinitionIntoModule(NamedDecl *ND, Module *M, bool NotifyListeners = true); - /// \brief Clean up the merged definition list. Call this if you might have + /// Clean up the merged definition list. Call this if you might have /// added duplicates into the list. void deduplicateMergedDefinitonsFor(NamedDecl *ND); - /// \brief Get the additional modules in which the definition \p Def has + /// Get the additional modules in which the definition \p Def has /// been merged. ArrayRef<Module*> getModulesWithMergedDefinition(const NamedDecl *Def) { auto MergedIt = MergedDefModules.find(Def); @@ -999,12 +1001,24 @@ public: CanQualType WCharTy; // [C++ 3.9.1p5]. CanQualType WideCharTy; // Same as WCharTy in C++, integer type in C99. CanQualType WIntTy; // [C99 7.24.1], integer type unchanged by default promotions. + CanQualType Char8Ty; // [C++20 proposal] CanQualType Char16Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType Char32Ty; // [C++0x 3.9.1p5], integer type in C99. CanQualType SignedCharTy, ShortTy, IntTy, LongTy, LongLongTy, Int128Ty; CanQualType UnsignedCharTy, UnsignedShortTy, UnsignedIntTy, UnsignedLongTy; CanQualType UnsignedLongLongTy, UnsignedInt128Ty; CanQualType FloatTy, DoubleTy, LongDoubleTy, Float128Ty; + CanQualType ShortAccumTy, AccumTy, + LongAccumTy; // ISO/IEC JTC1 SC22 WG14 N1169 Extension + CanQualType UnsignedShortAccumTy, UnsignedAccumTy, UnsignedLongAccumTy; + CanQualType ShortFractTy, FractTy, LongFractTy; + CanQualType UnsignedShortFractTy, UnsignedFractTy, UnsignedLongFractTy; + CanQualType SatShortAccumTy, SatAccumTy, SatLongAccumTy; + CanQualType SatUnsignedShortAccumTy, SatUnsignedAccumTy, + SatUnsignedLongAccumTy; + CanQualType SatShortFractTy, SatFractTy, SatLongFractTy; + CanQualType SatUnsignedShortFractTy, SatUnsignedFractTy, + SatUnsignedLongFractTy; CanQualType HalfTy; // [OpenCL 6.1.1.1], ARM NEON CanQualType Float16Ty; // C11 extension ISO/IEC TS 18661-3 CanQualType FloatComplexTy, DoubleComplexTy, LongDoubleComplexTy; @@ -1036,20 +1050,20 @@ public: ASTContext &operator=(const ASTContext &) = delete; ~ASTContext(); - /// \brief Attach an external AST source to the AST context. + /// Attach an external AST source to the AST context. /// /// The external AST source provides the ability to load parts of /// the abstract syntax tree as needed from some external storage, /// e.g., a precompiled header. void setExternalSource(IntrusiveRefCntPtr<ExternalASTSource> Source); - /// \brief Retrieve a pointer to the external AST source associated + /// Retrieve a pointer to the external AST source associated /// with this AST context, if any. ExternalASTSource *getExternalSource() const { return ExternalSource.get(); } - /// \brief Attach an AST mutation listener to the AST context. + /// Attach an AST mutation listener to the AST context. /// /// The AST mutation listener provides the ability to track modifications to /// the abstract syntax tree entities committed after they were initially @@ -1058,7 +1072,7 @@ public: this->Listener = Listener; } - /// \brief Retrieve a pointer to the AST mutation listener associated + /// Retrieve a pointer to the AST mutation listener associated /// with this AST context, if any. ASTMutationListener *getASTMutationListener() const { return Listener; } @@ -1068,18 +1082,18 @@ public: BuiltinTemplateDecl *buildBuiltinTemplateDecl(BuiltinTemplateKind BTK, const IdentifierInfo *II) const; - /// \brief Create a new implicit TU-level CXXRecordDecl or RecordDecl + /// Create a new implicit TU-level CXXRecordDecl or RecordDecl /// declaration. RecordDecl *buildImplicitRecord(StringRef Name, RecordDecl::TagKind TK = TTK_Struct) const; - /// \brief Create a new implicit TU-level typedef declaration. + /// Create a new implicit TU-level typedef declaration. TypedefDecl *buildImplicitTypedef(QualType T, StringRef Name) const; - /// \brief Retrieve the declaration for the 128-bit signed integer type. + /// Retrieve the declaration for the 128-bit signed integer type. TypedefDecl *getInt128Decl() const; - /// \brief Retrieve the declaration for the 128-bit unsigned integer type. + /// Retrieve the declaration for the 128-bit unsigned integer type. TypedefDecl *getUInt128Decl() const; //===--------------------------------------------------------------------===// @@ -1087,7 +1101,7 @@ public: //===--------------------------------------------------------------------===// private: - /// \brief Return a type with extended qualifiers. + /// Return a type with extended qualifiers. QualType getExtQualType(const Type *Base, Qualifiers Quals) const; QualType getTypeDeclTypeSlow(const TypeDecl *Decl) const; @@ -1095,7 +1109,7 @@ private: QualType getPipeType(QualType T, bool ReadOnly) const; public: - /// \brief Return the uniqued reference to the type for an address space + /// Return the uniqued reference to the type for an address space /// qualified type with the specified type and address space. /// /// The resulting type has a union of the qualifiers from T and the address @@ -1103,29 +1117,29 @@ public: /// replaced. QualType getAddrSpaceQualType(QualType T, LangAS AddressSpace) const; - /// \brief Remove any existing address space on the type and returns the type + /// Remove any existing address space on the type and returns the type /// with qualifiers intact (or that's the idea anyway) /// /// The return type should be T with all prior qualifiers minus the address /// space. QualType removeAddrSpaceQualType(QualType T) const; - /// \brief Apply Objective-C protocol qualifiers to the given type. + /// Apply Objective-C protocol qualifiers to the given type. /// \param allowOnPointerType specifies if we can apply protocol /// qualifiers on ObjCObjectPointerType. It can be set to true when - /// contructing the canonical type of a Objective-C type parameter. + /// constructing the canonical type of a Objective-C type parameter. QualType applyObjCProtocolQualifiers(QualType type, ArrayRef<ObjCProtocolDecl *> protocols, bool &hasError, bool allowOnPointerType = false) const; - /// \brief Return the uniqued reference to the type for an Objective-C + /// Return the uniqued reference to the type for an Objective-C /// gc-qualified type. /// - /// The retulting type has a union of the qualifiers from T and the gc + /// The resulting type has a union of the qualifiers from T and the gc /// attribute. QualType getObjCGCQualType(QualType T, Qualifiers::GC gcAttr) const; - /// \brief Return the uniqued reference to the type for a \c restrict + /// Return the uniqued reference to the type for a \c restrict /// qualified type. /// /// The resulting type has a union of the qualifiers from \p T and @@ -1134,7 +1148,7 @@ public: return T.withFastQualifiers(Qualifiers::Restrict); } - /// \brief Return the uniqued reference to the type for a \c volatile + /// Return the uniqued reference to the type for a \c volatile /// qualified type. /// /// The resulting type has a union of the qualifiers from \p T and @@ -1143,7 +1157,7 @@ public: return T.withFastQualifiers(Qualifiers::Volatile); } - /// \brief Return the uniqued reference to the type for a \c const + /// Return the uniqued reference to the type for a \c const /// qualified type. /// /// The resulting type has a union of the qualifiers from \p T and \c const. @@ -1152,41 +1166,48 @@ public: /// calling T.withConst(). QualType getConstType(QualType T) const { return T.withConst(); } - /// \brief Change the ExtInfo on a function type. + /// Change the ExtInfo on a function type. const FunctionType *adjustFunctionType(const FunctionType *Fn, FunctionType::ExtInfo EInfo); /// Adjust the given function result type. CanQualType getCanonicalFunctionResultType(QualType ResultType) const; - /// \brief Change the result type of a function type once it is deduced. + /// Change the result type of a function type once it is deduced. void adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType); - /// \brief Determine whether two function types are the same, ignoring + /// Get a function type and produce the equivalent function type with the + /// specified exception specification. Type sugar that can be present on a + /// declaration of a function with an exception specification is permitted + /// and preserved. Other type sugar (for instance, typedefs) is not. + QualType getFunctionTypeWithExceptionSpec( + QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI); + + /// Determine whether two function types are the same, ignoring /// exception specifications in cases where they're part of the type. bool hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U); - /// \brief Change the exception specification on a function once it is + /// 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 + /// Return the uniqued reference to the type for a complex /// number with the specified element type. QualType getComplexType(QualType T) const; CanQualType getComplexType(CanQualType T) const { return CanQualType::CreateUnsafe(getComplexType((QualType) T)); } - /// \brief Return the uniqued reference to the type for a pointer to + /// Return the uniqued reference to the type for a pointer to /// the specified type. QualType getPointerType(QualType T) const; CanQualType getPointerType(CanQualType T) const { return CanQualType::CreateUnsafe(getPointerType((QualType) T)); } - /// \brief Return the uniqued reference to a type adjusted from the original + /// Return the uniqued reference to a type adjusted from the original /// type to a new type. QualType getAdjustedType(QualType Orig, QualType New) const; CanQualType getAdjustedType(CanQualType Orig, CanQualType New) const { @@ -1194,7 +1215,7 @@ public: getAdjustedType((QualType)Orig, (QualType)New)); } - /// \brief Return the uniqued reference to the decayed version of the given + /// Return the uniqued reference to the decayed version of the given /// type. Can only be called on array and function types which decay to /// pointer types. QualType getDecayedType(QualType T) const; @@ -1202,11 +1223,11 @@ public: return CanQualType::CreateUnsafe(getDecayedType((QualType) T)); } - /// \brief Return the uniqued reference to the atomic type for the specified + /// Return the uniqued reference to the atomic type for the specified /// type. QualType getAtomicType(QualType T) const; - /// \brief Return the uniqued reference to the type for a block of the + /// Return the uniqued reference to the type for a block of the /// specified type. QualType getBlockPointerType(QualType T) const; @@ -1214,10 +1235,10 @@ public: /// blocks. QualType getBlockDescriptorType() const; - /// \brief Return a read_only pipe type for the specified type. + /// Return a read_only pipe type for the specified type. QualType getReadPipeType(QualType T) const; - /// \brief Return a write_only pipe type for the specified type. + /// Return a write_only pipe type for the specified type. QualType getWritePipeType(QualType T) const; /// Gets the struct used to keep track of the extended descriptor for @@ -1241,36 +1262,36 @@ public: /// Returns true iff we need copy/dispose helpers for the given type. bool BlockRequiresCopying(QualType Ty, const VarDecl *D); - /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout is set - /// to false in this case. If HasByrefExtendedLayout returns true, byref variable - /// has extended lifetime. + /// Returns true, if given type has a known lifetime. HasByrefExtendedLayout + /// is set to false in this case. If HasByrefExtendedLayout returns true, + /// byref variable has extended lifetime. bool getByrefLifetime(QualType Ty, Qualifiers::ObjCLifetime &Lifetime, bool &HasByrefExtendedLayout) const; - /// \brief Return the uniqued reference to the type for an lvalue reference + /// Return the uniqued reference to the type for an lvalue reference /// to the specified type. QualType getLValueReferenceType(QualType T, bool SpelledAsLValue = true) const; - /// \brief Return the uniqued reference to the type for an rvalue reference + /// Return the uniqued reference to the type for an rvalue reference /// to the specified type. QualType getRValueReferenceType(QualType T) const; - /// \brief Return the uniqued reference to the type for a member pointer to + /// Return the uniqued reference to the type for a member pointer to /// the specified type in the specified class. /// /// The class \p Cls is a \c Type because it could be a dependent name. QualType getMemberPointerType(QualType T, const Type *Cls) const; - /// \brief Return a non-unique reference to the type for a variable array of + /// Return a non-unique reference to the type for a variable array of /// the specified element type. QualType getVariableArrayType(QualType EltTy, Expr *NumElts, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals, SourceRange Brackets) const; - /// \brief Return a non-unique reference to the type for a dependently-sized + /// Return a non-unique reference to the type for a dependently-sized /// array of the specified element type. /// /// FIXME: We will need these to be uniqued, or at least comparable, at some @@ -1280,29 +1301,34 @@ public: unsigned IndexTypeQuals, SourceRange Brackets) const; - /// \brief Return a unique reference to the type for an incomplete array of + /// Return a unique reference to the type for an incomplete array of /// the specified element type. QualType getIncompleteArrayType(QualType EltTy, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; - /// \brief Return the unique reference to the type for a constant array of + /// Return the unique reference to the type for a constant array of /// the specified element type. QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, ArrayType::ArraySizeModifier ASM, unsigned IndexTypeQuals) const; - /// \brief Returns a vla type where known sizes are replaced with [*]. + /// Returns a vla type where known sizes are replaced with [*]. QualType getVariableArrayDecayedType(QualType Ty) const; - /// \brief Return the unique reference to a vector type of the specified + /// Return the unique reference to a vector type of the specified /// element type and size. /// /// \pre \p VectorType must be a built-in type. QualType getVectorType(QualType VectorType, unsigned NumElts, VectorType::VectorKind VecKind) const; + /// Return the unique reference to the type for a dependently sized vector of + /// the specified element type. + QualType getDependentVectorType(QualType VectorType, Expr *SizeExpr, + SourceLocation AttrLoc, + VectorType::VectorKind VecKind) const; - /// \brief Return the unique reference to an extended vector type + /// Return the unique reference to an extended vector type /// of the specified element type and size. /// /// \pre \p VectorType must be a built-in type. @@ -1321,7 +1347,7 @@ public: Expr *AddrSpaceExpr, SourceLocation AttrLoc) const; - /// \brief Return a K&R style C function type like 'int()'. + /// Return a K&R style C function type like 'int()'. QualType getFunctionNoProtoType(QualType ResultTy, const FunctionType::ExtInfo &Info) const; @@ -1329,20 +1355,22 @@ public: return getFunctionNoProtoType(ResultTy, FunctionType::ExtInfo()); } - /// \brief Return a normal function type with a typed argument list. + /// Return a normal function type with a typed argument list. QualType getFunctionType(QualType ResultTy, ArrayRef<QualType> Args, const FunctionProtoType::ExtProtoInfo &EPI) const { return getFunctionTypeInternal(ResultTy, Args, EPI, false); } + QualType adjustStringLiteralBaseType(QualType StrLTy) const; + private: - /// \brief Return a normal function type with a typed argument list. + /// Return a normal function type with a typed argument list. QualType getFunctionTypeInternal(QualType ResultTy, ArrayRef<QualType> Args, const FunctionProtoType::ExtProtoInfo &EPI, bool OnlyWantCanonical) const; public: - /// \brief Return the unique reference to the type for the specified type + /// Return the unique reference to the type for the specified type /// declaration. QualType getTypeDeclType(const TypeDecl *Decl, const TypeDecl *PrevDecl = nullptr) const { @@ -1358,7 +1386,7 @@ public: return getTypeDeclTypeSlow(Decl); } - /// \brief Return the unique reference to the type for the specified + /// Return the unique reference to the type for the specified /// typedef-name decl. QualType getTypedefType(const TypedefNameDecl *Decl, QualType Canon = QualType()) const; @@ -1404,8 +1432,8 @@ public: QualType getParenType(QualType NamedType) const; QualType getElaboratedType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - QualType NamedType) const; + NestedNameSpecifier *NNS, QualType NamedType, + TagDecl *OwnedTagDecl = nullptr) const; QualType getDependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, const IdentifierInfo *Name, @@ -1455,105 +1483,105 @@ public: bool QIdProtocolsAdoptObjCObjectProtocols(QualType QT, ObjCInterfaceDecl *IDecl); - /// \brief Return a ObjCObjectPointerType type for the given ObjCObjectType. + /// Return a ObjCObjectPointerType type for the given ObjCObjectType. QualType getObjCObjectPointerType(QualType OIT) const; - /// \brief GCC extension. + /// GCC extension. QualType getTypeOfExprType(Expr *e) const; QualType getTypeOfType(QualType t) const; - /// \brief C++11 decltype. + /// C++11 decltype. QualType getDecltypeType(Expr *e, QualType UnderlyingType) const; - /// \brief Unary type transforms + /// Unary type transforms QualType getUnaryTransformType(QualType BaseType, QualType UnderlyingType, UnaryTransformType::UTTKind UKind) const; - /// \brief C++11 deduced auto type. + /// C++11 deduced auto type. QualType getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, bool IsDependent) const; - /// \brief C++11 deduction pattern for 'auto' type. + /// C++11 deduction pattern for 'auto' type. QualType getAutoDeductType() const; - /// \brief C++11 deduction pattern for 'auto &&' type. + /// C++11 deduction pattern for 'auto &&' type. QualType getAutoRRefDeductType() const; - /// \brief C++17 deduced class template specialization type. + /// C++17 deduced class template specialization type. QualType getDeducedTemplateSpecializationType(TemplateName Template, QualType DeducedType, bool IsDependent) const; - /// \brief Return the unique reference to the type for the specified TagDecl + /// Return the unique reference to the type for the specified TagDecl /// (struct/union/class/enum) decl. QualType getTagDeclType(const TagDecl *Decl) const; - /// \brief Return the unique type for "size_t" (C99 7.17), defined in + /// Return the unique type for "size_t" (C99 7.17), defined in /// <stddef.h>. /// /// The sizeof operator requires this (C99 6.5.3.4p4). CanQualType getSizeType() const; - /// \brief Return the unique signed counterpart of + /// Return the unique signed counterpart of /// the integer type corresponding to size_t. CanQualType getSignedSizeType() const; - /// \brief Return the unique type for "intmax_t" (C99 7.18.1.5), defined in + /// Return the unique type for "intmax_t" (C99 7.18.1.5), defined in /// <stdint.h>. CanQualType getIntMaxType() const; - /// \brief Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in + /// Return the unique type for "uintmax_t" (C99 7.18.1.5), defined in /// <stdint.h>. CanQualType getUIntMaxType() const; - /// \brief Return the unique wchar_t type available in C++ (and available as + /// Return the unique wchar_t type available in C++ (and available as /// __wchar_t as a Microsoft extension). QualType getWCharType() const { return WCharTy; } - /// \brief Return the type of wide characters. In C++, this returns the + /// Return the type of wide characters. In C++, this returns the /// unique wchar_t type. In C99, this returns a type compatible with the type /// defined in <stddef.h> as defined by the target. QualType getWideCharType() const { return WideCharTy; } - /// \brief Return the type of "signed wchar_t". + /// Return the type of "signed wchar_t". /// /// Used when in C++, as a GCC extension. QualType getSignedWCharType() const; - /// \brief Return the type of "unsigned wchar_t". + /// Return the type of "unsigned wchar_t". /// /// Used when in C++, as a GCC extension. QualType getUnsignedWCharType() const; - /// \brief In C99, this returns a type compatible with the type + /// In C99, this returns a type compatible with the type /// defined in <stddef.h> as defined by the target. QualType getWIntType() const { return WIntTy; } - /// \brief Return a type compatible with "intptr_t" (C99 7.18.1.4), + /// Return a type compatible with "intptr_t" (C99 7.18.1.4), /// as defined by the target. QualType getIntPtrType() const; - /// \brief Return a type compatible with "uintptr_t" (C99 7.18.1.4), + /// Return a type compatible with "uintptr_t" (C99 7.18.1.4), /// as defined by the target. QualType getUIntPtrType() const; - /// \brief Return the unique type for "ptrdiff_t" (C99 7.17) defined in + /// Return the unique type for "ptrdiff_t" (C99 7.17) defined in /// <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType getPointerDiffType() const; - /// \brief Return the unique unsigned counterpart of "ptrdiff_t" + /// Return the unique unsigned counterpart of "ptrdiff_t" /// integer type. The standard (C11 7.21.6.1p7) refers to this type /// in the definition of %tu format specifier. QualType getUnsignedPointerDiffType() const; - /// \brief Return the unique type for "pid_t" defined in + /// Return the unique type for "pid_t" defined in /// <sys/types.h>. We need this to compute the correct type for vfork(). QualType getProcessIDType() const; - /// \brief Return the C structure type used to represent constant CFStrings. + /// Return the C structure type used to represent constant CFStrings. QualType getCFConstantStringType() const; - /// \brief Returns the C struct type for objc_super + /// Returns the C struct type for objc_super QualType getObjCSuperType() const; void setObjCSuperType(QualType ST) { ObjCSuperType = ST; } @@ -1582,7 +1610,7 @@ public: ObjCNSStringType = T; } - /// \brief Retrieve the type that \c id has been defined to, which may be + /// Retrieve the type that \c id has been defined to, which may be /// different from the built-in \c id if \c id has been typedef'd. QualType getObjCIdRedefinitionType() const { if (ObjCIdRedefinitionType.isNull()) @@ -1590,12 +1618,12 @@ public: return ObjCIdRedefinitionType; } - /// \brief Set the user-written type that redefines \c id. + /// Set the user-written type that redefines \c id. void setObjCIdRedefinitionType(QualType RedefType) { ObjCIdRedefinitionType = RedefType; } - /// \brief Retrieve the type that \c Class has been defined to, which may be + /// Retrieve the type that \c Class has been defined to, which may be /// different from the built-in \c Class if \c Class has been typedef'd. QualType getObjCClassRedefinitionType() const { if (ObjCClassRedefinitionType.isNull()) @@ -1603,12 +1631,12 @@ public: return ObjCClassRedefinitionType; } - /// \brief Set the user-written type that redefines 'SEL'. + /// Set the user-written type that redefines 'SEL'. void setObjCClassRedefinitionType(QualType RedefType) { ObjCClassRedefinitionType = RedefType; } - /// \brief Retrieve the type that 'SEL' has been defined to, which may be + /// Retrieve the type that 'SEL' has been defined to, which may be /// different from the built-in 'SEL' if 'SEL' has been typedef'd. QualType getObjCSelRedefinitionType() const { if (ObjCSelRedefinitionType.isNull()) @@ -1616,7 +1644,7 @@ public: return ObjCSelRedefinitionType; } - /// \brief Set the user-written type that redefines 'SEL'. + /// Set the user-written type that redefines 'SEL'. void setObjCSelRedefinitionType(QualType RedefType) { ObjCSelRedefinitionType = RedefType; } @@ -1676,68 +1704,68 @@ public: return TypePackElementName; } - /// \brief Retrieve the Objective-C "instancetype" type, if already known; + /// Retrieve the Objective-C "instancetype" type, if already known; /// otherwise, returns a NULL type; QualType getObjCInstanceType() { return getTypeDeclType(getObjCInstanceTypeDecl()); } - /// \brief Retrieve the typedef declaration corresponding to the Objective-C + /// Retrieve the typedef declaration corresponding to the Objective-C /// "instancetype" type. TypedefDecl *getObjCInstanceTypeDecl(); - /// \brief Set the type for the C FILE type. + /// Set the type for the C FILE type. void setFILEDecl(TypeDecl *FILEDecl) { this->FILEDecl = FILEDecl; } - /// \brief Retrieve the C FILE type. + /// Retrieve the C FILE type. QualType getFILEType() const { if (FILEDecl) return getTypeDeclType(FILEDecl); return QualType(); } - /// \brief Set the type for the C jmp_buf type. + /// Set the type for the C jmp_buf type. void setjmp_bufDecl(TypeDecl *jmp_bufDecl) { this->jmp_bufDecl = jmp_bufDecl; } - /// \brief Retrieve the C jmp_buf type. + /// Retrieve the C jmp_buf type. QualType getjmp_bufType() const { if (jmp_bufDecl) return getTypeDeclType(jmp_bufDecl); return QualType(); } - /// \brief Set the type for the C sigjmp_buf type. + /// Set the type for the C sigjmp_buf type. void setsigjmp_bufDecl(TypeDecl *sigjmp_bufDecl) { this->sigjmp_bufDecl = sigjmp_bufDecl; } - /// \brief Retrieve the C sigjmp_buf type. + /// Retrieve the C sigjmp_buf type. QualType getsigjmp_bufType() const { if (sigjmp_bufDecl) return getTypeDeclType(sigjmp_bufDecl); return QualType(); } - /// \brief Set the type for the C ucontext_t type. + /// Set the type for the C ucontext_t type. void setucontext_tDecl(TypeDecl *ucontext_tDecl) { this->ucontext_tDecl = ucontext_tDecl; } - /// \brief Retrieve the C ucontext_t type. + /// Retrieve the C ucontext_t type. QualType getucontext_tType() const { if (ucontext_tDecl) return getTypeDeclType(ucontext_tDecl); return QualType(); } - /// \brief The result type of logical operations, '<', '>', '!=', etc. + /// The result type of logical operations, '<', '>', '!=', etc. QualType getLogicalOperationType() const { return getLangOpts().CPlusPlus ? BoolTy : IntTy; } - /// \brief Emit the Objective-CC type encoding for the given type \p T into + /// Emit the Objective-CC type encoding for the given type \p T into /// \p S. /// /// If \p Field is specified then record field names are also encoded. @@ -1745,17 +1773,17 @@ public: const FieldDecl *Field=nullptr, QualType *NotEncodedT=nullptr) const; - /// \brief Emit the Objective-C property type encoding for the given + /// Emit the Objective-C property type encoding for the given /// type \p T into \p S. void getObjCEncodingForPropertyType(QualType T, std::string &S) const; void getLegacyIntegralTypeEncoding(QualType &t) const; - /// \brief Put the string version of the type qualifiers \p QT into \p S. + /// Put the string version of the type qualifiers \p QT into \p S. void getObjCEncodingForTypeQualifier(Decl::ObjCDeclQualifier QT, std::string &S) const; - /// \brief Emit the encoded type for the function \p Decl into \p S. + /// Emit the encoded type for the function \p Decl into \p S. /// /// This is in the same format as Objective-C method encodings. /// @@ -1763,12 +1791,12 @@ public: /// types is incomplete), false otherwise. std::string getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const; - /// \brief Emit the encoded type for the method declaration \p Decl into + /// Emit the encoded type for the method declaration \p Decl into /// \p S. std::string getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, bool Extended = false) const; - /// \brief Return the encoded type for this block declaration. + /// Return the encoded type for this block declaration. std::string getObjCEncodingForBlock(const BlockExpr *blockExpr) const; /// getObjCEncodingForPropertyDecl - Return the encoded type for @@ -1785,15 +1813,15 @@ public: const ObjCPropertyDecl *PD, const Decl *Container) const; - /// \brief Return the size of type \p T for Objective-C encoding purpose, + /// Return the size of type \p T for Objective-C encoding purpose, /// in characters. CharUnits getObjCEncodingTypeSize(QualType T) const; - /// \brief Retrieve the typedef corresponding to the predefined \c id type + /// Retrieve the typedef corresponding to the predefined \c id type /// in Objective-C. TypedefDecl *getObjCIdDecl() const; - /// \brief Represents the Objective-CC \c id type. + /// Represents the Objective-CC \c id type. /// /// This is set up lazily, by Sema. \c id is always a (typedef for a) /// pointer type, a pointer to a struct. @@ -1801,21 +1829,21 @@ public: return getTypeDeclType(getObjCIdDecl()); } - /// \brief Retrieve the typedef corresponding to the predefined 'SEL' type + /// Retrieve the typedef corresponding to the predefined 'SEL' type /// in Objective-C. TypedefDecl *getObjCSelDecl() const; - /// \brief Retrieve the type that corresponds to the predefined Objective-C + /// Retrieve the type that corresponds to the predefined Objective-C /// 'SEL' type. QualType getObjCSelType() const { return getTypeDeclType(getObjCSelDecl()); } - /// \brief Retrieve the typedef declaration corresponding to the predefined + /// Retrieve the typedef declaration corresponding to the predefined /// Objective-C 'Class' type. TypedefDecl *getObjCClassDecl() const; - /// \brief Represents the Objective-C \c Class type. + /// Represents the Objective-C \c Class type. /// /// This is set up lazily, by Sema. \c Class is always a (typedef for a) /// pointer type, a pointer to a struct. @@ -1823,40 +1851,40 @@ public: return getTypeDeclType(getObjCClassDecl()); } - /// \brief Retrieve the Objective-C class declaration corresponding to + /// Retrieve the Objective-C class declaration corresponding to /// the predefined \c Protocol class. ObjCInterfaceDecl *getObjCProtocolDecl() const; - /// \brief Retrieve declaration of 'BOOL' typedef + /// Retrieve declaration of 'BOOL' typedef TypedefDecl *getBOOLDecl() const { return BOOLDecl; } - /// \brief Save declaration of 'BOOL' typedef + /// Save declaration of 'BOOL' typedef void setBOOLDecl(TypedefDecl *TD) { BOOLDecl = TD; } - /// \brief type of 'BOOL' type. + /// type of 'BOOL' type. QualType getBOOLType() const { return getTypeDeclType(getBOOLDecl()); } - /// \brief Retrieve the type of the Objective-C \c Protocol class. + /// Retrieve the type of the Objective-C \c Protocol class. QualType getObjCProtoType() const { return getObjCInterfaceType(getObjCProtocolDecl()); } - /// \brief Retrieve the C type declaration corresponding to the predefined + /// Retrieve the C type declaration corresponding to the predefined /// \c __builtin_va_list type. TypedefDecl *getBuiltinVaListDecl() const; - /// \brief Retrieve the type of the \c __builtin_va_list type. + /// Retrieve the type of the \c __builtin_va_list type. QualType getBuiltinVaListType() const { return getTypeDeclType(getBuiltinVaListDecl()); } - /// \brief Retrieve the C type declaration corresponding to the predefined + /// Retrieve the C type declaration corresponding to the predefined /// \c __va_list_tag type used to help define the \c __builtin_va_list type /// for some targets. Decl *getVaListTagDecl() const; @@ -1870,18 +1898,22 @@ public: return getTypeDeclType(getBuiltinMSVaListDecl()); } - /// \brief Return a type with additional \c const, \c volatile, or + /// Return whether a declaration to a builtin is allowed to be + /// overloaded/redeclared. + bool canBuiltinBeRedeclared(const FunctionDecl *) const; + + /// Return a type with additional \c const, \c volatile, or /// \c restrict qualifiers. QualType getCVRQualifiedType(QualType T, unsigned CVR) const { return getQualifiedType(T, Qualifiers::fromCVRMask(CVR)); } - /// \brief Un-split a SplitQualType. + /// Un-split a SplitQualType. QualType getQualifiedType(SplitQualType split) const { return getQualifiedType(split.Ty, split.Quals); } - /// \brief Return a type with additional qualifiers. + /// Return a type with additional qualifiers. QualType getQualifiedType(QualType T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) return T.withFastQualifiers(Qs.getFastQualifiers()); @@ -1890,14 +1922,14 @@ public: return getExtQualType(Ptr, Qc); } - /// \brief Return a type with additional qualifiers. + /// Return a type with additional qualifiers. QualType getQualifiedType(const Type *T, Qualifiers Qs) const { if (!Qs.hasNonFastQualifiers()) return QualType(T, Qs.getFastQualifiers()); return getExtQualType(T, Qs); } - /// \brief Return a type with the given lifetime qualifier. + /// Return a type with the given lifetime qualifier. /// /// \pre Neither type.ObjCLifetime() nor \p lifetime may be \c OCL_None. QualType getLifetimeQualifiedType(QualType type, @@ -1921,6 +1953,9 @@ public: return getQualifiedType(type.getUnqualifiedType(), Qs); } + unsigned char getFixedPointScale(QualType Ty) const; + unsigned char getFixedPointIBits(QualType Ty) const; + DeclarationNameInfo getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const; @@ -1954,7 +1989,7 @@ public: GE_Missing_ucontext }; - /// \brief Return the type for the specified builtin. + /// Return the type for the specified builtin. /// /// If \p IntegerConstantArgs is non-null, it is filled in with a bitmask of /// arguments to the builtin that are required to be integer constant @@ -1962,6 +1997,10 @@ public: QualType GetBuiltinType(unsigned ID, GetBuiltinTypeError &Error, unsigned *IntegerConstantArgs = nullptr) const; + /// Types and expressions required to build C++2a three-way comparisons + /// using operator<=>, including the values return by builtin <=> operators. + ComparisonCategories CompCategories; + private: CanQualType getFromTargetType(unsigned Type) const; TypeInfo getTypeInfoImpl(const Type *T) const; @@ -1971,18 +2010,18 @@ private: //===--------------------------------------------------------------------===// public: - /// \brief Return one of the GCNone, Weak or Strong Objective-C garbage + /// Return one of the GCNone, Weak or Strong Objective-C garbage /// collection attributes. Qualifiers::GC getObjCGCAttrKind(QualType Ty) const; - /// \brief Return true if the given vector types are of the same unqualified + /// Return true if the given vector types are of the same unqualified /// type or if they are equivalent to the same GCC vector type. /// /// \note This ignores whether they are target-specific (AltiVec or Neon) /// types. bool areCompatibleVectorTypes(QualType FirstVec, QualType SecondVec); - /// \brief Return true if this is an \c NSObject object with its \c NSObject + /// Return true if this is an \c NSObject object with its \c NSObject /// attribute set. static bool isObjCNSObjectType(QualType Ty) { return Ty->isObjCNSObjectType(); @@ -1992,48 +2031,48 @@ public: // Type Sizing and Analysis //===--------------------------------------------------------------------===// - /// \brief Return the APFloat 'semantics' for the specified scalar floating + /// Return the APFloat 'semantics' for the specified scalar floating /// point type. const llvm::fltSemantics &getFloatTypeSemantics(QualType T) const; - /// \brief Get the size and alignment of the specified complete type in bits. + /// Get the size and alignment of the specified complete type in bits. TypeInfo getTypeInfo(const Type *T) const; TypeInfo getTypeInfo(QualType T) const { return getTypeInfo(T.getTypePtr()); } - /// \brief Get default simd alignment of the specified complete type in bits. + /// Get default simd alignment of the specified complete type in bits. unsigned getOpenMPDefaultSimdAlign(QualType T) const; - /// \brief Return the size of the specified (complete) type \p T, in bits. + /// Return the size of the specified (complete) type \p T, in bits. 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. + /// Return the size of the character type, in bits. uint64_t getCharWidth() const { return getTypeSize(CharTy); } - /// \brief Convert a size in bits to a size in characters. + /// Convert a size in bits to a size in characters. CharUnits toCharUnitsFromBits(int64_t BitSize) const; - /// \brief Convert a size in characters to a size in bits. + /// Convert a size in characters to a size in bits. int64_t toBits(CharUnits CharSize) const; - /// \brief Return the size of the specified (complete) type \p T, in + /// Return the size of the specified (complete) type \p T, in /// characters. CharUnits getTypeSizeInChars(QualType T) const; CharUnits getTypeSizeInChars(const Type *T) const; - /// \brief Return the ABI-specified alignment of a (complete) type \p T, in + /// Return the ABI-specified alignment of a (complete) type \p T, in /// bits. 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 type, in bits, or 0 if + /// Return the ABI-specified alignment of a type, in bits, or 0 if /// the type is incomplete and we cannot determine the alignment (for /// example, from alignment attributes). unsigned getTypeAlignIfKnown(QualType T) const; - /// \brief Return the ABI-specified alignment of a (complete) type \p T, in + /// Return the ABI-specified alignment of a (complete) type \p T, in /// characters. CharUnits getTypeAlignInChars(QualType T) const; CharUnits getTypeAlignInChars(const Type *T) const; @@ -2045,31 +2084,31 @@ 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 + /// 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 + /// Return the "preferred" alignment of the specified type \p T for /// the current target, in bits. /// /// This can be different than the ABI alignment in cases where it is /// beneficial for performance to overalign a data type. unsigned getPreferredTypeAlign(const Type *T) const; - /// \brief Return the default alignment for __attribute__((aligned)) on + /// Return the default alignment for __attribute__((aligned)) on /// this target, to be used if no alignment value is specified. unsigned getTargetDefaultAlignForAttributeAligned() const; - /// \brief Return the alignment in bits that should be given to a + /// Return the alignment in bits that should be given to a /// global variable with type \p T. unsigned getAlignOfGlobalVar(QualType T) const; - /// \brief Return the alignment in characters that should be given to a + /// Return the alignment in characters that should be given to a /// global variable with type \p T. CharUnits getAlignOfGlobalVarInChars(QualType T) const; - /// \brief Return a conservative estimate of the alignment of the specified + /// Return a conservative estimate of the alignment of the specified /// decl \p D. /// /// \pre \p D must not be a bitfield type, as bitfields do not have a valid @@ -2081,12 +2120,12 @@ public: /// pointers and large arrays get extra alignment. CharUnits getDeclAlign(const Decl *D, bool ForAlignof = false) const; - /// \brief Get or compute information about the layout of the specified + /// Get or compute information about the layout of the specified /// record (struct/union/class) \p D, which indicates its size and field /// position information. const ASTRecordLayout &getASTRecordLayout(const RecordDecl *D) const; - /// \brief Get or compute information about the layout of the specified + /// Get or compute information about the layout of the specified /// Objective-C interface. const ASTRecordLayout &getASTObjCInterfaceLayout(const ObjCInterfaceDecl *D) const; @@ -2094,14 +2133,14 @@ public: void DumpRecordLayout(const RecordDecl *RD, raw_ostream &OS, bool Simple = false) const; - /// \brief Get or compute information about the layout of the specified + /// Get or compute information about the layout of the specified /// Objective-C implementation. /// /// This may differ from the interface if synthesized ivars are present. const ASTRecordLayout & getASTObjCImplementationLayout(const ObjCImplementationDecl *D) const; - /// \brief Get our current best idea for the key function of the + /// Get our current best idea for the key function of the /// given record decl, or nullptr if there isn't one. /// /// The key function is, according to the Itanium C++ ABI section 5.2.3: @@ -2113,7 +2152,7 @@ public: /// the result of this computation can change. const CXXMethodDecl *getCurrentKeyFunction(const CXXRecordDecl *RD); - /// \brief Observe that the given method cannot be a key function. + /// Observe that the given method cannot be a key function. /// Checks the key-function cache for the method's class and clears it /// if matches the given declaration. /// @@ -2155,7 +2194,7 @@ public: void CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols); - /// \brief Return true if the specified type has unique object representations + /// Return true if the specified type has unique object representations /// according to (C++17 [meta.unary.prop]p9) bool hasUniqueObjectRepresentations(QualType Ty) const; @@ -2163,7 +2202,7 @@ public: // Type Operators //===--------------------------------------------------------------------===// - /// \brief Return the canonical (structural) type corresponding to the + /// Return the canonical (structural) type corresponding to the /// specified potentially non-canonical type \p T. /// /// The non-canonical version of a type may have many "decorated" versions of @@ -2179,14 +2218,14 @@ public: return T->getCanonicalTypeInternal().getTypePtr(); } - /// \brief Return the canonical parameter type corresponding to the specific + /// Return the canonical parameter type corresponding to the specific /// potentially non-canonical one. /// /// Qualifiers are stripped off, functions are turned into function /// pointers, and arrays decay one level into pointers. CanQualType getCanonicalParamType(QualType T) const; - /// \brief Determine whether the given types \p T1 and \p T2 are equivalent. + /// Determine whether the given types \p T1 and \p T2 are equivalent. bool hasSameType(QualType T1, QualType T2) const { return getCanonicalType(T1) == getCanonicalType(T2); } @@ -2194,7 +2233,7 @@ public: return getCanonicalType(T1) == getCanonicalType(T2); } - /// \brief Return this type as a completely-unqualified array type, + /// Return this type as a completely-unqualified array type, /// capturing the qualifiers in \p Quals. /// /// This will remove the minimal amount of sugaring from the types, similar @@ -2209,7 +2248,7 @@ public: /// that corresponds to it. Otherwise, returns T.getUnqualifiedType(). QualType getUnqualifiedArrayType(QualType T, Qualifiers &Quals); - /// \brief Determine whether the given types are equivalent after + /// Determine whether the given types are equivalent after /// cvr-qualifiers have been removed. bool hasSameUnqualifiedType(QualType T1, QualType T2) const { return getCanonicalType(T1).getTypePtr() == @@ -2249,9 +2288,22 @@ public: bool ObjCMethodsAreEqual(const ObjCMethodDecl *MethodDecl, const ObjCMethodDecl *MethodImp); - bool UnwrapSimilarPointerTypes(QualType &T1, QualType &T2); + bool UnwrapSimilarTypes(QualType &T1, QualType &T2); + bool UnwrapSimilarArrayTypes(QualType &T1, QualType &T2); + + /// Determine if two types are similar, according to the C++ rules. That is, + /// determine if they are the same other than qualifiers on the initial + /// sequence of pointer / pointer-to-member / array (and in Clang, object + /// pointer) types and their element types. + /// + /// Clang offers a number of qualifiers in addition to the C++ qualifiers; + /// those qualifiers are also ignored in the 'similarity' check. + bool hasSimilarType(QualType T1, QualType T2); + + /// Determine if two types are similar, ignoring only CVR qualifiers. + bool hasCvrSimilarType(QualType T1, QualType T2); - /// \brief Retrieves the "canonical" nested name specifier for a + /// Retrieves the "canonical" nested name specifier for a /// given nested name specifier. /// /// The canonical nested name specifier is a nested name specifier @@ -2277,11 +2329,11 @@ public: NestedNameSpecifier * getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const; - /// \brief Retrieves the default calling convention for the current target. + /// Retrieves the default calling convention for the current target. CallingConv getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod) const; - /// \brief Retrieves the "canonical" template name that refers to a + /// Retrieves the "canonical" template name that refers to a /// given template. /// /// The canonical template name is the simplest expression that can @@ -2301,11 +2353,11 @@ public: /// types, values, and templates. TemplateName getCanonicalTemplateName(TemplateName Name) const; - /// \brief Determine whether the given template names refer to the same + /// Determine whether the given template names refer to the same /// template. bool hasSameTemplateName(TemplateName X, TemplateName Y); - /// \brief Retrieve the "canonical" template argument. + /// Retrieve the "canonical" template argument. /// /// The canonical template argument is the simplest template argument /// (which may be a type, value, expression, or declaration) that @@ -2332,33 +2384,33 @@ public: return dyn_cast_or_null<DependentSizedArrayType>(getAsArrayType(T)); } - /// \brief Return the innermost element type of an array type. + /// Return the innermost element type of an array type. /// /// For example, will return "int" for int[m][n] QualType getBaseElementType(const ArrayType *VAT) const; - /// \brief Return the innermost element type of a type (which needn't + /// Return the innermost element type of a type (which needn't /// actually be an array type). QualType getBaseElementType(QualType QT) const; - /// \brief Return number of constant array elements. + /// Return number of constant array elements. uint64_t getConstantArrayElementCount(const ConstantArrayType *CA) const; - /// \brief Perform adjustment on the parameter type of a function. + /// Perform adjustment on the parameter type of a function. /// /// This routine adjusts the given parameter type @p T to the actual /// parameter type used by semantic analysis (C99 6.7.5.3p[7,8], /// C++ [dcl.fct]p3). The adjusted parameter type is returned. QualType getAdjustedParameterType(QualType T) const; - /// \brief Retrieve the parameter type as adjusted for use in the signature + /// Retrieve the parameter type as adjusted for use in the signature /// of a function, decaying array and function types and removing top-level /// cv-qualifiers. QualType getSignatureParameterType(QualType T) const; QualType getExceptionObjectType(QualType T) const; - /// \brief Return the properly qualified result of decaying the specified + /// Return the properly qualified result of decaying the specified /// array type to a pointer. /// /// This operation is non-trivial when handling typedefs etc. The canonical @@ -2368,35 +2420,35 @@ public: /// See C99 6.7.5.3p7 and C99 6.3.2.1p3. QualType getArrayDecayedType(QualType T) const; - /// \brief Return the type that \p PromotableType will promote to: C99 + /// Return the type that \p PromotableType will promote to: C99 /// 6.3.1.1p2, assuming that \p PromotableType is a promotable integer type. QualType getPromotedIntegerType(QualType PromotableType) const; - /// \brief Recurses in pointer/array types until it finds an Objective-C + /// Recurses in pointer/array types until it finds an Objective-C /// retainable type and returns its ownership. Qualifiers::ObjCLifetime getInnerObjCOwnership(QualType T) const; - /// \brief Whether this is a promotable bitfield reference according + /// Whether this is a promotable bitfield reference according /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions). /// /// \returns the type this bit-field will promote to, or NULL if no /// promotion occurs. QualType isPromotableBitField(Expr *E) const; - /// \brief Return the highest ranked integer type, see C99 6.3.1.8p1. + /// Return the highest ranked integer type, see C99 6.3.1.8p1. /// /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If /// \p LHS < \p RHS, return -1. int getIntegerTypeOrder(QualType LHS, QualType RHS) const; - /// \brief Compare the rank of the two specified floating point types, + /// Compare the rank of the two specified floating point types, /// ignoring the domain of the type (i.e. 'double' == '_Complex double'). /// /// If \p LHS > \p RHS, returns 1. If \p LHS == \p RHS, returns 0. If /// \p LHS < \p RHS, return -1. int getFloatingTypeOrder(QualType LHS, QualType RHS) const; - /// \brief Return a real floating point or a complex type (based on + /// Return a real floating point or a complex type (based on /// \p typeDomain/\p typeSize). /// /// \param typeDomain a real floating point or complex type. @@ -2521,13 +2573,20 @@ public: // Per C99 6.2.5p6, for every signed integer type, there is a corresponding // unsigned integer type. This method takes a signed type, and returns the // corresponding unsigned integer type. + // With the introduction of fixed point types in ISO N1169, this method also + // accepts fixed point types and returns the corresponding unsigned type for + // a given fixed point type. QualType getCorrespondingUnsignedType(QualType T) const; + // Per ISO N1169, this method accepts fixed point types and returns the + // corresponding saturated type for a given fixed point type. + QualType getCorrespondingSaturatedType(QualType Ty) const; + //===--------------------------------------------------------------------===// // Integer Values //===--------------------------------------------------------------------===// - /// \brief Make an APSInt of the appropriate width and signedness for the + /// Make an APSInt of the appropriate width and signedness for the /// given \p Value and integer \p Type. llvm::APSInt MakeIntValue(uint64_t Value, QualType Type) const { // If Type is a signed integer type larger than 64 bits, we need to be sure @@ -2542,28 +2601,28 @@ public: bool isSentinelNullExpr(const Expr *E); - /// \brief Get the implementation of the ObjCInterfaceDecl \p D, or nullptr if + /// Get the implementation of the ObjCInterfaceDecl \p D, or nullptr if /// none exists. ObjCImplementationDecl *getObjCImplementation(ObjCInterfaceDecl *D); - /// \brief Get the implementation of the ObjCCategoryDecl \p D, or nullptr if + /// Get the implementation of the ObjCCategoryDecl \p D, or nullptr if /// none exists. ObjCCategoryImplDecl *getObjCImplementation(ObjCCategoryDecl *D); - /// \brief Return true if there is at least one \@implementation in the TU. + /// Return true if there is at least one \@implementation in the TU. bool AnyObjCImplementation() { return !ObjCImpls.empty(); } - /// \brief Set the implementation of ObjCInterfaceDecl. + /// Set the implementation of ObjCInterfaceDecl. void setObjCImplementation(ObjCInterfaceDecl *IFaceD, ObjCImplementationDecl *ImplD); - /// \brief Set the implementation of ObjCCategoryDecl. + /// Set the implementation of ObjCCategoryDecl. void setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD); - /// \brief Get the duplicate declaration of a ObjCMethod in the same + /// Get the duplicate declaration of a ObjCMethod in the same /// interface, or null if none exists. const ObjCMethodDecl * getObjCMethodRedeclaration(const ObjCMethodDecl *MD) const; @@ -2571,19 +2630,19 @@ public: void setObjCMethodRedeclaration(const ObjCMethodDecl *MD, const ObjCMethodDecl *Redecl); - /// \brief Returns the Objective-C interface that \p ND belongs to if it is + /// Returns the Objective-C interface that \p ND belongs to if it is /// an Objective-C method/property/ivar etc. that is part of an interface, /// otherwise returns null. const ObjCInterfaceDecl *getObjContainingInterface(const NamedDecl *ND) const; - /// \brief Set the copy inialization expression of a block var decl. + /// Set the copy inialization expression of a block var decl. void setBlockVarCopyInits(VarDecl*VD, Expr* Init); - /// \brief Get the copy initialization expression of the VarDecl \p VD, or + /// Get the copy initialization expression of the VarDecl \p VD, or /// nullptr if none exists. Expr *getBlockVarCopyInits(const VarDecl* VD); - /// \brief Allocate an uninitialized TypeSourceInfo. + /// Allocate an uninitialized TypeSourceInfo. /// /// The caller should initialize the memory held by TypeSourceInfo using /// the TypeLoc wrappers. @@ -2596,14 +2655,14 @@ public: /// should be calculated based on the type. TypeSourceInfo *CreateTypeSourceInfo(QualType T, unsigned Size = 0) const; - /// \brief Allocate a TypeSourceInfo where all locations have been + /// Allocate a TypeSourceInfo where all locations have been /// initialized to a given location, which defaults to the empty /// location. TypeSourceInfo * getTrivialTypeSourceInfo(QualType T, SourceLocation Loc = SourceLocation()) const; - /// \brief Add a deallocation callback that will be invoked when the + /// Add a deallocation callback that will be invoked when the /// ASTContext is destroyed. /// /// \param Callback A callback function that will be invoked on destruction. @@ -2625,7 +2684,7 @@ public: GVALinkage GetGVALinkageForFunction(const FunctionDecl *FD) const; GVALinkage GetGVALinkageForVariable(const VarDecl *VD); - /// \brief Determines if the decl can be CodeGen'ed or deserialized from PCH + /// Determines if the decl can be CodeGen'ed or deserialized from PCH /// lazily, only when used; this is only relevant for function or file scoped /// var definitions. /// @@ -2633,6 +2692,12 @@ public: /// it is not used. bool DeclMustBeEmitted(const Decl *D); + /// Visits all versions of a multiversioned function with the passed + /// predicate. + void forEachMultiversionedFunctionVersion( + const FunctionDecl *FD, + llvm::function_ref<void(const FunctionDecl *)> Pred) const; + const CXXConstructorDecl * getCopyConstructorForExceptionObject(CXXRecordDecl *RD); @@ -2653,21 +2718,21 @@ public: void setStaticLocalNumber(const VarDecl *VD, unsigned Number); unsigned getStaticLocalNumber(const VarDecl *VD) const; - /// \brief Retrieve the context for computing mangling numbers in the given + /// Retrieve the context for computing mangling numbers in the given /// DeclContext. MangleNumberingContext &getManglingNumberContext(const DeclContext *DC); std::unique_ptr<MangleNumberingContext> createMangleNumberingContext() const; - /// \brief Used by ParmVarDecl to store on the side the + /// Used by ParmVarDecl to store on the side the /// index of the parameter when it exceeds the size of the normal bitfield. void setParameterIndex(const ParmVarDecl *D, unsigned index); - /// \brief Used by ParmVarDecl to retrieve on the side the + /// Used by ParmVarDecl to retrieve on the side the /// index of the parameter when it exceeds the size of the normal bitfield. unsigned getParameterIndex(const ParmVarDecl *D) const; - /// \brief Get the storage for the constant value of a materialized temporary + /// Get the storage for the constant value of a materialized temporary /// of static storage duration. APValue *getMaterializedTemporaryValue(const MaterializeTemporaryExpr *E, bool MayCreate); @@ -2676,50 +2741,50 @@ public: // Statistics //===--------------------------------------------------------------------===// - /// \brief The number of implicitly-declared default constructors. + /// The number of implicitly-declared default constructors. static unsigned NumImplicitDefaultConstructors; - /// \brief The number of implicitly-declared default constructors for + /// The number of implicitly-declared default constructors for /// which declarations were built. static unsigned NumImplicitDefaultConstructorsDeclared; - /// \brief The number of implicitly-declared copy constructors. + /// The number of implicitly-declared copy constructors. static unsigned NumImplicitCopyConstructors; - /// \brief The number of implicitly-declared copy constructors for + /// The number of implicitly-declared copy constructors for /// which declarations were built. static unsigned NumImplicitCopyConstructorsDeclared; - /// \brief The number of implicitly-declared move constructors. + /// The number of implicitly-declared move constructors. static unsigned NumImplicitMoveConstructors; - /// \brief The number of implicitly-declared move constructors for + /// The number of implicitly-declared move constructors for /// which declarations were built. static unsigned NumImplicitMoveConstructorsDeclared; - /// \brief The number of implicitly-declared copy assignment operators. + /// The number of implicitly-declared copy assignment operators. static unsigned NumImplicitCopyAssignmentOperators; - /// \brief The number of implicitly-declared copy assignment operators for + /// The number of implicitly-declared copy assignment operators for /// which declarations were built. static unsigned NumImplicitCopyAssignmentOperatorsDeclared; - /// \brief The number of implicitly-declared move assignment operators. + /// The number of implicitly-declared move assignment operators. static unsigned NumImplicitMoveAssignmentOperators; - /// \brief The number of implicitly-declared move assignment operators for + /// The number of implicitly-declared move assignment operators for /// which declarations were built. static unsigned NumImplicitMoveAssignmentOperatorsDeclared; - /// \brief The number of implicitly-declared destructors. + /// The number of implicitly-declared destructors. static unsigned NumImplicitDestructors; - /// \brief The number of implicitly-declared destructors for which + /// The number of implicitly-declared destructors for which /// declarations were built. static unsigned NumImplicitDestructorsDeclared; public: - /// \brief Initialize built-in types. + /// Initialize built-in types. /// /// This routine may only be invoked once for a given ASTContext object. /// It is normally invoked after ASTContext construction. @@ -2756,7 +2821,7 @@ public: QualType T, std::string& S, bool Extended) const; - /// \brief Returns true if this is an inline-initialized static data member + /// Returns true if this is an inline-initialized static data member /// which is treated as a definition for MSVC compatibility. bool isMSStaticDataMemberInlineDefinition(const VarDecl *VD) const; @@ -2774,7 +2839,7 @@ public: Strong }; - /// \brief Determine whether a definition of this inline variable should + /// Determine whether a definition of this inline variable should /// be treated as a weak or strong definition. For compatibility with /// C++14 and before, for a constexpr static data member, if there is an /// out-of-line declaration of the member, we may promote it from weak to @@ -2790,7 +2855,7 @@ private: getObjCLayout(const ObjCInterfaceDecl *D, const ObjCImplementationDecl *Impl) const; - /// \brief A set of deallocations that should be performed when the + /// A set of deallocations that should be performed when the /// ASTContext is destroyed. // FIXME: We really should have a better mechanism in the ASTContext to // manage running destructors for types which do variable sized allocation @@ -2841,13 +2906,13 @@ public: llvm::StringMap<SectionInfo> SectionInfos; }; -/// \brief Utility function for constructing a nullary selector. +/// Utility function for constructing a nullary selector. inline Selector GetNullarySelector(StringRef name, ASTContext &Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(0, &II); } -/// \brief Utility function for constructing an unary selector. +/// Utility function for constructing an unary selector. inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { IdentifierInfo* II = &Ctx.Idents.get(name); return Ctx.Selectors.getSelector(1, &II); @@ -2857,7 +2922,7 @@ inline Selector GetUnarySelector(StringRef name, ASTContext &Ctx) { // operator new and delete aren't allowed inside namespaces. -/// @brief Placement new for using the ASTContext's allocator. +/// Placement new for using the ASTContext's allocator. /// /// This placement form of operator new uses the ASTContext's allocator for /// obtaining memory. @@ -2890,7 +2955,7 @@ inline void *operator new(size_t Bytes, const clang::ASTContext &C, return C.Allocate(Bytes, Alignment); } -/// @brief Placement delete companion to the new above. +/// Placement delete companion to the new above. /// /// This operator is just a companion to the new above. There is no way of /// invoking it directly; see the new operator for more details. This operator @@ -2928,7 +2993,7 @@ inline void *operator new[](size_t Bytes, const clang::ASTContext& C, return C.Allocate(Bytes, Alignment); } -/// @brief Placement delete[] companion to the new[] above. +/// Placement delete[] companion to the new[] above. /// /// This operator is just a companion to the new[] above. There is no way of /// invoking it directly; see the new[] operator for more details. This operator @@ -2938,7 +3003,7 @@ inline void operator delete[](void *Ptr, const clang::ASTContext &C, size_t) { C.Deallocate(Ptr); } -/// \brief Create the representation of a LazyGenerationalUpdatePtr. +/// Create the representation of a LazyGenerationalUpdatePtr. template <typename Owner, typename T, void (clang::ExternalASTSource::*Update)(Owner)> typename clang::LazyGenerationalUpdatePtr<Owner, T, Update>::ValueType diff --git a/include/clang/AST/ASTDiagnostic.h b/include/clang/AST/ASTDiagnostic.h index 27c85e65f2c11..b08865dde3c10 100644 --- a/include/clang/AST/ASTDiagnostic.h +++ b/include/clang/AST/ASTDiagnostic.h @@ -24,7 +24,7 @@ namespace clang { }; } // end namespace diag - /// \brief DiagnosticsEngine argument formatting function for diagnostics that + /// DiagnosticsEngine argument formatting function for diagnostics that /// involve AST nodes. /// /// This function formats diagnostic arguments for various AST nodes, diff --git a/include/clang/AST/ASTFwd.h b/include/clang/AST/ASTFwd.h index 003d489c1ca40..038d5c3d36115 100644 --- a/include/clang/AST/ASTFwd.h +++ b/include/clang/AST/ASTFwd.h @@ -8,7 +8,7 @@ //===--------------------------------------------------------------===// /// /// \file -/// \brief Forward declaration of all AST node types. +/// Forward declaration of all AST node types. /// //===-------------------------------------------------------------===// diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index 66b9cd394b9d9..6e6a1926254bc 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -1,4 +1,4 @@ -//===--- ASTImporter.h - Importing ASTs from other Contexts -----*- C++ -*-===// +//===- ASTImporter.h - Importing ASTs from other Contexts -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,82 +11,95 @@ // context into another context. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_AST_ASTIMPORTER_H #define LLVM_CLANG_AST_ASTIMPORTER_H #include "clang/AST/DeclarationName.h" +#include "clang/AST/NestedNameSpecifier.h" +#include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" +#include <utility> namespace clang { - class ASTContext; - class CXXCtorInitializer; - class CXXBaseSpecifier; - class Decl; - class DeclContext; - class DiagnosticsEngine; - class Expr; - class FileManager; - class IdentifierInfo; - class NestedNameSpecifier; - class Stmt; - class TypeSourceInfo; - - /// \brief Imports selected nodes from one AST context into another context, + +class ASTContext; +class CXXBaseSpecifier; +class CXXCtorInitializer; +class Decl; +class DeclContext; +class Expr; +class FileManager; +class NamedDecl; +class Stmt; +class TagDecl; +class TypeSourceInfo; +class Attr; + + // \brief Returns with a list of declarations started from the canonical decl + // then followed by subsequent decls in the translation unit. + // This gives a canonical list for each entry in the redecl chain. + // `Decl::redecls()` gives a list of decls which always start from the + // previous decl and the next item is actually the previous item in the order + // of source locations. Thus, `Decl::redecls()` gives different lists for + // the different entries in a given redecl chain. + llvm::SmallVector<Decl*, 2> getCanonicalForwardRedeclChain(Decl* D); + + /// Imports selected nodes from one AST context into another context, /// merging AST nodes where appropriate. class ASTImporter { public: - typedef llvm::DenseSet<std::pair<Decl *, Decl *> > NonEquivalentDeclSet; - typedef llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *> - ImportedCXXBaseSpecifierMap; + using NonEquivalentDeclSet = llvm::DenseSet<std::pair<Decl *, Decl *>>; + using ImportedCXXBaseSpecifierMap = + llvm::DenseMap<const CXXBaseSpecifier *, CXXBaseSpecifier *>; private: - /// \brief The contexts we're importing to and from. + /// The contexts we're importing to and from. ASTContext &ToContext, &FromContext; - /// \brief The file managers we're importing to and from. + /// The file managers we're importing to and from. FileManager &ToFileManager, &FromFileManager; - /// \brief Whether to perform a minimal import. + /// Whether to perform a minimal import. bool Minimal; - /// \brief Whether the last diagnostic came from the "from" context. - bool LastDiagFromFrom; + /// Whether the last diagnostic came from the "from" context. + bool LastDiagFromFrom = false; - /// \brief Mapping from the already-imported types in the "from" context + /// Mapping from the already-imported types in the "from" context /// to the corresponding types in the "to" context. llvm::DenseMap<const Type *, const Type *> ImportedTypes; - /// \brief Mapping from the already-imported declarations in the "from" + /// Mapping from the already-imported declarations in the "from" /// context to the corresponding declarations in the "to" context. llvm::DenseMap<Decl *, Decl *> ImportedDecls; - /// \brief Mapping from the already-imported statements in the "from" + /// Mapping from the already-imported statements in the "from" /// context to the corresponding statements in the "to" context. llvm::DenseMap<Stmt *, Stmt *> ImportedStmts; - /// \brief Mapping from the already-imported FileIDs in the "from" source + /// Mapping from the already-imported FileIDs in the "from" source /// manager to the corresponding FileIDs in the "to" source manager. llvm::DenseMap<FileID, FileID> ImportedFileIDs; - /// \brief Mapping from the already-imported CXXBasesSpecifier in + /// Mapping from the already-imported CXXBasesSpecifier in /// the "from" source manager to the corresponding CXXBasesSpecifier /// in the "to" source manager. ImportedCXXBaseSpecifierMap ImportedCXXBaseSpecifiers; - - /// \brief Imported, anonymous tag declarations that are missing their - /// corresponding typedefs. - SmallVector<TagDecl *, 4> AnonTagsWithPendingTypedefs; - /// \brief Declaration (from, to) pairs that are known not to be equivalent + /// Declaration (from, to) pairs that are known not to be equivalent /// (which we have already complained about). NonEquivalentDeclSet NonEquivalentDecls; public: - /// \brief Create a new AST importer. + /// Create a new AST importer. /// /// \param ToContext The context we'll be importing into. /// @@ -105,135 +118,144 @@ namespace clang { virtual ~ASTImporter(); - /// \brief Whether the importer will perform a minimal import, creating + /// Whether the importer will perform a minimal import, creating /// to-be-completed forward declarations when possible. bool isMinimalImport() const { return Minimal; } - /// \brief Import the given type from the "from" context into the "to" + /// Import the given type from the "from" context into the "to" /// context. /// /// \returns the equivalent type in the "to" context, or a NULL type if /// an error occurred. QualType Import(QualType FromT); - /// \brief Import the given type source information from the + /// Import the given type source information from the /// "from" context into the "to" context. /// /// \returns the equivalent type source information in the "to" /// context, or NULL if an error occurred. TypeSourceInfo *Import(TypeSourceInfo *FromTSI); - /// \brief Import the given declaration from the "from" context into the + /// Import the given attribute from the "from" context into the + /// "to" context. + /// + /// \returns the equivalent attribute in the "to" context. + Attr *Import(const Attr *FromAttr); + + /// Import the given declaration from the "from" context into the /// "to" context. /// /// \returns the equivalent declaration in the "to" context, or a NULL type /// if an error occurred. Decl *Import(Decl *FromD); + Decl *Import(const Decl *FromD) { + return Import(const_cast<Decl *>(FromD)); + } - /// \brief Return the copy of the given declaration in the "to" context if + /// Return the copy of the given declaration in the "to" context if /// it has already been imported from the "from" context. Otherwise return /// NULL. Decl *GetAlreadyImportedOrNull(Decl *FromD); - /// \brief Import the given declaration context from the "from" + /// Import the given declaration context from the "from" /// AST context into the "to" AST context. /// /// \returns the equivalent declaration context in the "to" /// context, or a NULL type if an error occurred. DeclContext *ImportContext(DeclContext *FromDC); - /// \brief Import the given expression from the "from" context into the + /// Import the given expression from the "from" context into the /// "to" context. /// /// \returns the equivalent expression in the "to" context, or NULL if /// an error occurred. Expr *Import(Expr *FromE); - /// \brief Import the given statement from the "from" context into the + /// Import the given statement from the "from" context into the /// "to" context. /// /// \returns the equivalent statement in the "to" context, or NULL if /// an error occurred. Stmt *Import(Stmt *FromS); - /// \brief Import the given nested-name-specifier from the "from" + /// Import the given nested-name-specifier from the "from" /// context into the "to" context. /// /// \returns the equivalent nested-name-specifier in the "to" /// context, or NULL if an error occurred. NestedNameSpecifier *Import(NestedNameSpecifier *FromNNS); - /// \brief Import the given nested-name-specifier from the "from" + /// Import the given nested-name-specifier from the "from" /// context into the "to" context. /// /// \returns the equivalent nested-name-specifier in the "to" /// context. NestedNameSpecifierLoc Import(NestedNameSpecifierLoc FromNNS); - /// \brief Import the goven template name from the "from" context into the + /// Import the goven template name from the "from" context into the /// "to" context. TemplateName Import(TemplateName From); - /// \brief Import the given source location from the "from" context into + /// Import the given source location from the "from" context into /// the "to" context. /// /// \returns the equivalent source location in the "to" context, or an /// invalid source location if an error occurred. SourceLocation Import(SourceLocation FromLoc); - /// \brief Import the given source range from the "from" context into + /// Import the given source range from the "from" context into /// the "to" context. /// /// \returns the equivalent source range in the "to" context, or an /// invalid source location if an error occurred. SourceRange Import(SourceRange FromRange); - /// \brief Import the given declaration name from the "from" + /// Import the given declaration name from the "from" /// context into the "to" context. /// /// \returns the equivalent declaration name in the "to" context, /// or an empty declaration name if an error occurred. DeclarationName Import(DeclarationName FromName); - /// \brief Import the given identifier from the "from" context + /// Import the given identifier from the "from" context /// into the "to" context. /// /// \returns the equivalent identifier in the "to" context. IdentifierInfo *Import(const IdentifierInfo *FromId); - /// \brief Import the given Objective-C selector from the "from" + /// Import the given Objective-C selector from the "from" /// context into the "to" context. /// /// \returns the equivalent selector in the "to" context. Selector Import(Selector FromSel); - /// \brief Import the given file ID from the "from" context into the + /// Import the given file ID from the "from" context into the /// "to" context. /// /// \returns the equivalent file ID in the source manager of the "to" /// context. FileID Import(FileID); - /// \brief Import the given C++ constructor initializer from the "from" + /// Import the given C++ constructor initializer from the "from" /// context into the "to" context. /// /// \returns the equivalent initializer in the "to" context. CXXCtorInitializer *Import(CXXCtorInitializer *FromInit); - /// \brief Import the given CXXBaseSpecifier from the "from" context into + /// Import the given CXXBaseSpecifier from the "from" context into /// the "to" context. /// /// \returns the equivalent CXXBaseSpecifier in the source manager of the /// "to" context. CXXBaseSpecifier *Import(const CXXBaseSpecifier *FromSpec); - /// \brief Import the definition of the given declaration, including all of + /// Import the definition of the given declaration, including all of /// the declarations it contains. /// /// This routine is intended to be used void ImportDefinition(Decl *From); - /// \brief Cope with a name conflict when importing a declaration into the + /// Cope with a name conflict when importing a declaration into the /// given context. /// /// This routine is invoked whenever there is a name conflict while @@ -265,41 +287,41 @@ namespace clang { NamedDecl **Decls, unsigned NumDecls); - /// \brief Retrieve the context that AST nodes are being imported into. + /// Retrieve the context that AST nodes are being imported into. ASTContext &getToContext() const { return ToContext; } - /// \brief Retrieve the context that AST nodes are being imported from. + /// Retrieve the context that AST nodes are being imported from. ASTContext &getFromContext() const { return FromContext; } - /// \brief Retrieve the file manager that AST nodes are being imported into. + /// Retrieve the file manager that AST nodes are being imported into. FileManager &getToFileManager() const { return ToFileManager; } - /// \brief Retrieve the file manager that AST nodes are being imported from. + /// Retrieve the file manager that AST nodes are being imported from. FileManager &getFromFileManager() const { return FromFileManager; } - /// \brief Report a diagnostic in the "to" context. + /// Report a diagnostic in the "to" context. DiagnosticBuilder ToDiag(SourceLocation Loc, unsigned DiagID); - /// \brief Report a diagnostic in the "from" context. + /// Report a diagnostic in the "from" context. DiagnosticBuilder FromDiag(SourceLocation Loc, unsigned DiagID); - /// \brief Return the set of declarations that we know are not equivalent. + /// Return the set of declarations that we know are not equivalent. NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } - /// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. + /// Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. /// Mark the Decl as complete, filling it in as much as possible. /// /// \param D A declaration in the "to" context. virtual void CompleteDecl(Decl* D); - /// \brief Note that we have imported the "from" declaration by mapping it - /// to the (potentially-newly-created) "to" declaration. - /// /// Subclasses can override this function to observe all of the \c From -> /// \c To declaration mappings as they are imported. - virtual Decl *Imported(Decl *From, Decl *To); - - /// \brief Called by StructuralEquivalenceContext. If a RecordDecl is + virtual Decl *Imported(Decl *From, Decl *To) { return To; } + + /// Store and assign the imported declaration to its counterpart. + Decl *MapImported(Decl *From, Decl *To); + + /// Called by StructuralEquivalenceContext. If a RecordDecl is /// being compared to another RecordDecl as part of import, completing the /// other RecordDecl may trigger importation of the first RecordDecl. This /// happens especially for anonymous structs. If the original of the second @@ -307,11 +329,12 @@ namespace clang { /// importation, eliminating this loop. virtual Decl *GetOriginalDecl(Decl *To) { return nullptr; } - /// \brief Determine whether the given types are structurally + /// Determine whether the given types are structurally /// equivalent. bool IsStructurallyEquivalent(QualType From, QualType To, bool Complain = true); }; -} + +} // namespace clang #endif // LLVM_CLANG_AST_ASTIMPORTER_H diff --git a/include/clang/AST/ASTLambda.h b/include/clang/AST/ASTLambda.h index 69df2d8c01138..2fe4e2563b36f 100644 --- a/include/clang/AST/ASTLambda.h +++ b/include/clang/AST/ASTLambda.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file provides some common utility functions for processing +/// This file provides some common utility functions for processing /// Lambda related AST Constructs. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/AST/ASTMutationListener.h b/include/clang/AST/ASTMutationListener.h index 9395d36d87e58..31ae2b111e013 100644 --- a/include/clang/AST/ASTMutationListener.h +++ b/include/clang/AST/ASTMutationListener.h @@ -41,86 +41,86 @@ namespace clang { class VarTemplateDecl; class VarTemplateSpecializationDecl; -/// \brief An abstract interface that should be implemented by listeners +/// An abstract interface that should be implemented by listeners /// that want to be notified when an AST entity gets modified after its /// initial creation. class ASTMutationListener { public: virtual ~ASTMutationListener(); - /// \brief A new TagDecl definition was completed. + /// A new TagDecl definition was completed. virtual void CompletedTagDefinition(const TagDecl *D) { } - /// \brief A new declaration with name has been added to a DeclContext. + /// A new declaration with name has been added to a DeclContext. virtual void AddedVisibleDecl(const DeclContext *DC, const Decl *D) {} - /// \brief An implicit member was added after the definition was completed. + /// An implicit member was added after the definition was completed. virtual void AddedCXXImplicitMember(const CXXRecordDecl *RD, const Decl *D) {} - /// \brief A template specialization (or partial one) was added to the + /// A template specialization (or partial one) was added to the /// template declaration. virtual void AddedCXXTemplateSpecialization(const ClassTemplateDecl *TD, const ClassTemplateSpecializationDecl *D) {} - /// \brief A template specialization (or partial one) was added to the + /// A template specialization (or partial one) was added to the /// template declaration. virtual void AddedCXXTemplateSpecialization(const VarTemplateDecl *TD, const VarTemplateSpecializationDecl *D) {} - /// \brief A template specialization (or partial one) was added to the + /// A template specialization (or partial one) was added to the /// template declaration. virtual void AddedCXXTemplateSpecialization(const FunctionTemplateDecl *TD, const FunctionDecl *D) {} - /// \brief A function's exception specification has been evaluated or + /// A function's exception specification has been evaluated or /// instantiated. virtual void ResolvedExceptionSpec(const FunctionDecl *FD) {} - /// \brief A function's return type has been deduced. + /// A function's return type has been deduced. virtual void DeducedReturnType(const FunctionDecl *FD, QualType ReturnType); - /// \brief A virtual destructor's operator delete has been resolved. + /// A virtual destructor's operator delete has been resolved. virtual void ResolvedOperatorDelete(const CXXDestructorDecl *DD, const FunctionDecl *Delete, Expr *ThisArg) {} - /// \brief An implicit member got a definition. + /// An implicit member got a definition. virtual void CompletedImplicitDefinition(const FunctionDecl *D) {} - /// \brief The instantiation of a templated function or variable was + /// The instantiation of a templated function or variable was /// requested. In particular, the point of instantiation and template /// specialization kind of \p D may have changed. virtual void InstantiationRequested(const ValueDecl *D) {} - /// \brief A templated variable's definition was implicitly instantiated. + /// A templated variable's definition was implicitly instantiated. virtual void VariableDefinitionInstantiated(const VarDecl *D) {} - /// \brief A function template's definition was instantiated. + /// A function template's definition was instantiated. virtual void FunctionDefinitionInstantiated(const FunctionDecl *D) {} - /// \brief A default argument was instantiated. + /// A default argument was instantiated. virtual void DefaultArgumentInstantiated(const ParmVarDecl *D) {} - /// \brief A default member initializer was instantiated. + /// A default member initializer was instantiated. virtual void DefaultMemberInitializerInstantiated(const FieldDecl *D) {} - /// \brief A new objc category class was added for an interface. + /// A new objc category class was added for an interface. virtual void AddedObjCCategoryToInterface(const ObjCCategoryDecl *CatD, const ObjCInterfaceDecl *IFD) {} - /// \brief A declaration is marked used which was not previously marked used. + /// A declaration is marked used which was not previously marked used. /// /// \param D the declaration marked used virtual void DeclarationMarkedUsed(const Decl *D) {} - /// \brief A declaration is marked as OpenMP threadprivate which was not + /// 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) {} - /// \brief A declaration is marked as OpenMP declaretarget which was not + /// A declaration is marked as OpenMP declaretarget which was not /// previously marked as declaretarget. /// /// \param D the declaration marked OpenMP declaretarget. @@ -128,14 +128,14 @@ public: virtual void DeclarationMarkedOpenMPDeclareTarget(const Decl *D, const Attr *Attr) {} - /// \brief A definition has been made visible by being redefined locally. + /// A definition has been made visible by being redefined locally. /// /// \param D The definition that was previously not visible. /// \param M The containing module in which the definition was made visible, /// if any. virtual void RedefinedHiddenDefinition(const NamedDecl *D, Module *M) {} - /// \brief An attribute was added to a RecordDecl + /// An attribute was added to a RecordDecl /// /// \param Attr The attribute that was added to the Record /// diff --git a/include/clang/AST/ASTStructuralEquivalence.h b/include/clang/AST/ASTStructuralEquivalence.h index 23674c65f332f..d32f87d43e041 100644 --- a/include/clang/AST/ASTStructuralEquivalence.h +++ b/include/clang/AST/ASTStructuralEquivalence.h @@ -1,4 +1,4 @@ -//===--- ASTStructuralEquivalence.h - ---------------------------*- C++ -*-===// +//===- ASTStructuralEquivalence.h -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,6 +19,7 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/Optional.h" #include <deque> +#include <utility> namespace clang { @@ -29,6 +30,14 @@ class QualType; class RecordDecl; class SourceLocation; +/// \brief Whether to perform a normal or minimal equivalence check. +/// In case of `Minimal`, we do not perform a recursive check of decls with +/// external storage. +enum class StructuralEquivalenceKind { + Default, + Minimal, +}; + struct StructuralEquivalenceContext { /// AST contexts for which we are checking structural equivalence. ASTContext &FromCtx, &ToCtx; @@ -46,6 +55,8 @@ struct StructuralEquivalenceContext { /// (which we have already complained about). llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls; + StructuralEquivalenceKind EqKind; + /// Whether we're being strict about the spelling of types when /// unifying two types. bool StrictTypeSpelling; @@ -57,27 +68,35 @@ struct StructuralEquivalenceContext { bool Complain; /// \c true if the last diagnostic came from ToCtx. - bool LastDiagFromC2; + bool LastDiagFromC2 = false; StructuralEquivalenceContext( ASTContext &FromCtx, ASTContext &ToCtx, llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls, + StructuralEquivalenceKind EqKind, bool StrictTypeSpelling = false, bool Complain = true, bool ErrorOnTagTypeMismatch = false) : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling), - ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain), - LastDiagFromC2(false) {} + EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling), + ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {} DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID); DiagnosticBuilder Diag2(SourceLocation Loc, unsigned DiagID); /// Determine whether the two declarations are structurally /// equivalent. - bool IsStructurallyEquivalent(Decl *D1, Decl *D2); + /// Implementation functions (all static functions in + /// ASTStructuralEquivalence.cpp) must never call this function because that + /// will wreak havoc the internal state (\c DeclsToCheck and + /// \c TentativeEquivalences members) and can cause faulty equivalent results. + bool IsEquivalent(Decl *D1, Decl *D2); /// Determine whether the two types are structurally equivalent. - bool IsStructurallyEquivalent(QualType T1, QualType T2); + /// Implementation functions (all static functions in + /// ASTStructuralEquivalence.cpp) must never call this function because that + /// will wreak havoc the internal state (\c DeclsToCheck and + /// \c TentativeEquivalences members) and can cause faulty equivalent results. + bool IsEquivalent(QualType T1, QualType T2); /// Find the index of the given anonymous struct/union within its /// context. @@ -98,6 +117,7 @@ private: /// \returns true if an error occurred, false otherwise. bool Finish(); }; + } // namespace clang #endif // LLVM_CLANG_AST_ASTSTRUCTURALEQUIVALENCE_H diff --git a/include/clang/AST/ASTTypeTraits.h b/include/clang/AST/ASTTypeTraits.h index 51d60a90a146b..9df9793370c4a 100644 --- a/include/clang/AST/ASTTypeTraits.h +++ b/include/clang/AST/ASTTypeTraits.h @@ -38,62 +38,62 @@ struct PrintingPolicy; namespace ast_type_traits { -/// \brief Kind identifier. +/// Kind identifier. /// /// It can be constructed from any node kind and allows for runtime type /// hierarchy checks. /// Use getFromNodeKind<T>() to construct them. class ASTNodeKind { public: - /// \brief Empty identifier. It matches nothing. + /// Empty identifier. It matches nothing. ASTNodeKind() : KindId(NKI_None) {} - /// \brief Construct an identifier for T. + /// Construct an identifier for T. template <class T> static ASTNodeKind getFromNodeKind() { return ASTNodeKind(KindToKindId<T>::Id); } /// \{ - /// \brief Construct an identifier for the dynamic type of the node + /// 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. + /// Returns \c true if \c this and \c Other represent the same kind. bool isSame(ASTNodeKind Other) const { return KindId != NKI_None && KindId == Other.KindId; } - /// \brief Returns \c true only for the default \c ASTNodeKind() + /// 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. + /// 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. bool isBaseOf(ASTNodeKind Other, unsigned *Distance = nullptr) const; - /// \brief String representation of the kind. + /// String representation of the kind. StringRef asStringRef() const; - /// \brief Strict weak ordering for ASTNodeKind. + /// Strict weak ordering for ASTNodeKind. bool operator<(const ASTNodeKind &Other) const { return KindId < Other.KindId; } - /// \brief Return the most derived type between \p Kind1 and \p Kind2. + /// 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 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. + /// 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(); } @@ -115,7 +115,7 @@ public: } private: - /// \brief Kind ids. + /// Kind ids. /// /// Includes all possible base and derived kinds. enum NodeKindId { @@ -140,16 +140,16 @@ private: NKI_NumberOfKinds }; - /// \brief Use getFromNodeKind<T>() to construct the kind. + /// Use getFromNodeKind<T>() to construct the kind. ASTNodeKind(NodeKindId KindId) : KindId(KindId) {} - /// \brief Returns \c true if \c Base is a base kind of (or same as) \c + /// Returns \c true if \c Base is a base kind of (or same as) \c /// Derived. /// \param Distance If non-null, used to return the distance between \c Base /// and \c Derived in the class hierarchy. static bool isBaseOf(NodeKindId Base, NodeKindId Derived, unsigned *Distance); - /// \brief Helper meta-function to convert a kind T to its enum value. + /// Helper meta-function to convert a kind T to its enum value. /// /// This struct is specialized below for all known kinds. template <class T> struct KindToKindId { @@ -158,11 +158,11 @@ private: template <class T> struct KindToKindId<const T> : KindToKindId<T> {}; - /// \brief Per kind info. + /// Per kind info. struct KindInfo { - /// \brief The id of the parent kind, or None if it has no parent. + /// The id of the parent kind, or None if it has no parent. NodeKindId ParentId; - /// \brief Name of the kind. + /// Name of the kind. const char *Name; }; static const KindInfo AllKindInfo[NKI_NumberOfKinds]; @@ -197,7 +197,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { return OS; } -/// \brief A dynamically typed AST node container. +/// A dynamically typed AST node container. /// /// Stores an AST node in a type safe way. This allows writing code that /// works with different kinds of AST nodes, despite the fact that they don't @@ -211,13 +211,13 @@ inline raw_ostream &operator<<(raw_ostream &OS, ASTNodeKind K) { /// the supported base types. class DynTypedNode { public: - /// \brief Creates a \c DynTypedNode from \c Node. + /// Creates a \c DynTypedNode from \c Node. template <typename T> static DynTypedNode create(const T &Node) { return BaseConverter<T>::create(Node); } - /// \brief Retrieve the stored node as type \c T. + /// Retrieve the stored node as type \c T. /// /// Returns NULL if the stored node does not have a type that is /// convertible to \c T. @@ -234,7 +234,7 @@ public: return BaseConverter<T>::get(NodeKind, Storage.buffer); } - /// \brief Retrieve the stored node as type \c T. + /// 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> @@ -244,7 +244,7 @@ public: ASTNodeKind getNodeKind() const { return NodeKind; } - /// \brief Returns a pointer that identifies the stored AST node. + /// 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 @@ -255,21 +255,21 @@ public: : nullptr; } - /// \brief Prints the node to the given output stream. + /// Prints the node to the given output stream. void print(llvm::raw_ostream &OS, const PrintingPolicy &PP) const; - /// \brief Dumps the node to the given output stream. + /// Dumps the node to the given output stream. void dump(llvm::raw_ostream &OS, SourceManager &SM) const; - /// \brief For nodes which represent textual entities in the source code, + /// For nodes which represent textual entities in the source code, /// return their SourceRange. For all other nodes, return SourceRange(). SourceRange getSourceRange() const; /// @{ - /// \brief Imposes an order on \c DynTypedNode. + /// Imposes an order on \c DynTypedNode. /// /// Supports comparison of nodes that support memoization. - /// FIXME: Implement comparsion for other node types (currently + /// FIXME: Implement comparison for other node types (currently /// only Stmt, Decl, Type and NestedNameSpecifier return memoization data). bool operator<(const DynTypedNode &Other) const { if (!NodeKind.isSame(Other.NodeKind)) @@ -326,7 +326,7 @@ public: } /// @} - /// \brief Hooks for using DynTypedNode as a key in a DenseMap. + /// Hooks for using DynTypedNode as a key in a DenseMap. struct DenseMapInfo { static inline DynTypedNode getEmptyKey() { DynTypedNode Node; @@ -368,10 +368,10 @@ public: }; private: - /// \brief Takes care of converting from and to \c T. + /// Takes care of converting from and to \c T. template <typename T, typename EnablerT = void> struct BaseConverter; - /// \brief Converter that uses dyn_cast<T> from a stored BaseT*. + /// 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<T>().isBaseOf(NodeKind)) @@ -391,7 +391,7 @@ private: } }; - /// \brief Converter that stores T* (by pointer). + /// Converter that stores T* (by pointer). template <typename T> struct PtrConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) @@ -411,7 +411,7 @@ private: } }; - /// \brief Converter that stores T (by value). + /// Converter that stores T (by value). template <typename T> struct ValueConverter { static const T *get(ASTNodeKind NodeKind, const char Storage[]) { if (ASTNodeKind::getFromNodeKind<T>().isSame(NodeKind)) @@ -432,7 +432,7 @@ private: ASTNodeKind NodeKind; - /// \brief Stores the data of the node. + /// Stores the data of the node. /// /// Note that we can store \c Decls, \c Stmts, \c Types, /// \c NestedNameSpecifiers and \c CXXCtorInitializer by pointer as they are diff --git a/include/clang/AST/ASTUnresolvedSet.h b/include/clang/AST/ASTUnresolvedSet.h index 3693aeccfe14f..9bf63bb6e2d7d 100644 --- a/include/clang/AST/ASTUnresolvedSet.h +++ b/include/clang/AST/ASTUnresolvedSet.h @@ -26,7 +26,7 @@ namespace clang { class NamedDecl; -/// \brief An UnresolvedSet-like class which uses the ASTContext's allocator. +/// An UnresolvedSet-like class which uses the ASTContext's allocator. class ASTUnresolvedSet { friend class LazyASTUnresolvedSet; @@ -89,7 +89,7 @@ public: const DeclAccessPair &operator[](unsigned I) const { return Decls[I]; } }; -/// \brief An UnresolvedSet-like class that might not have been loaded from the +/// An UnresolvedSet-like class that might not have been loaded from the /// external AST source yet. class LazyASTUnresolvedSet { mutable ASTUnresolvedSet Impl; diff --git a/include/clang/AST/Attr.h b/include/clang/AST/Attr.h index bbe320c28a3b5..32a61c59d2368 100644 --- a/include/clang/AST/Attr.h +++ b/include/clang/AST/Attr.h @@ -23,9 +23,9 @@ #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> @@ -52,8 +52,10 @@ protected: unsigned Inherited : 1; unsigned IsPackExpansion : 1; unsigned Implicit : 1; + // FIXME: These are properties of the attribute kind, not state for this + // instance of the attribute. unsigned IsLateParsed : 1; - unsigned DuplicatesAllowed : 1; + unsigned InheritEvenIfAlreadyPresent : 1; void *operator new(size_t bytes) noexcept { llvm_unreachable("Attrs cannot be allocated with regular 'new'."); @@ -74,10 +76,10 @@ public: protected: Attr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) + bool IsLateParsed) : Range(R), AttrKind(AK), SpellingListIndex(SpellingListIndex), Inherited(false), IsPackExpansion(false), Implicit(false), - IsLateParsed(IsLateParsed), DuplicatesAllowed(DuplicatesAllowed) {} + IsLateParsed(IsLateParsed), InheritEvenIfAlreadyPresent(false) {} public: @@ -94,7 +96,7 @@ public: bool isInherited() const { return Inherited; } - /// \brief Returns true if the attribute has been implicitly created instead + /// Returns true if the attribute has been implicitly created instead /// of explicitly written by the user. bool isImplicit() const { return Implicit; } void setImplicit(bool I) { Implicit = I; } @@ -109,18 +111,13 @@ public: // Pretty print this attribute. void printPretty(raw_ostream &OS, const PrintingPolicy &Policy) const; - - /// \brief By default, attributes cannot be duplicated when being merged; - /// however, an attribute can override this. Returns true if the attribute - /// can be duplicated when merging. - bool duplicatesAllowed() const { return DuplicatesAllowed; } }; class StmtAttr : public Attr { protected: StmtAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) - : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} + bool IsLateParsed) + : Attr(AK, R, SpellingListIndex, IsLateParsed) {} public: static bool classof(const Attr *A) { @@ -132,12 +129,20 @@ public: class InheritableAttr : public Attr { protected: InheritableAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) - : Attr(AK, R, SpellingListIndex, IsLateParsed, DuplicatesAllowed) {} + bool IsLateParsed, bool InheritEvenIfAlreadyPresent) + : Attr(AK, R, SpellingListIndex, IsLateParsed) { + this->InheritEvenIfAlreadyPresent = InheritEvenIfAlreadyPresent; + } public: void setInherited(bool I) { Inherited = I; } + /// Should this attribute be inherited from a prior declaration even if it's + /// explicitly provided in the current declaration? + bool shouldInheritEvenIfAlreadyPresent() const { + return InheritEvenIfAlreadyPresent; + } + // Implement isa/cast/dyncast/etc. static bool classof(const Attr *A) { return A->getKind() >= attr::FirstInheritableAttr && @@ -148,9 +153,9 @@ public: class InheritableParamAttr : public InheritableAttr { protected: InheritableParamAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, - bool IsLateParsed, bool DuplicatesAllowed) + bool IsLateParsed, bool InheritEvenIfAlreadyPresent) : InheritableAttr(AK, R, SpellingListIndex, IsLateParsed, - DuplicatesAllowed) {} + InheritEvenIfAlreadyPresent) {} public: // Implement isa/cast/dyncast/etc. @@ -166,9 +171,9 @@ class ParameterABIAttr : public InheritableParamAttr { protected: ParameterABIAttr(attr::Kind AK, SourceRange R, unsigned SpellingListIndex, bool IsLateParsed, - bool DuplicatesAllowed) + bool InheritEvenIfAlreadyPresent) : InheritableParamAttr(AK, R, SpellingListIndex, IsLateParsed, - DuplicatesAllowed) {} + InheritEvenIfAlreadyPresent) {} public: ParameterABI getABI() const { @@ -190,6 +195,128 @@ public: } }; +/// A single parameter index whose accessors require each use to make explicit +/// the parameter index encoding needed. +class ParamIdx { + // Idx is exposed only via accessors that specify specific encodings. + unsigned Idx : 30; + unsigned HasThis : 1; + unsigned IsValid : 1; + + void assertComparable(const ParamIdx &I) const { + assert(isValid() && I.isValid() && + "ParamIdx must be valid to be compared"); + // It's possible to compare indices from separate functions, but so far + // it's not proven useful. Moreover, it might be confusing because a + // comparison on the results of getASTIndex might be inconsistent with a + // comparison on the ParamIdx objects themselves. + assert(HasThis == I.HasThis && + "ParamIdx must be for the same function to be compared"); + } + +public: + /// Construct an invalid parameter index (\c isValid returns false and + /// accessors fail an assert). + ParamIdx() : Idx(0), HasThis(false), IsValid(false) {} + + /// \param Idx is the parameter index as it is normally specified in + /// attributes in the source: one-origin including any C++ implicit this + /// parameter. + /// + /// \param D is the declaration containing the parameters. It is used to + /// determine if there is a C++ implicit this parameter. + ParamIdx(unsigned Idx, const Decl *D) + : Idx(Idx), HasThis(false), IsValid(true) { + assert(Idx >= 1 && "Idx must be one-origin"); + if (const auto *FD = dyn_cast<FunctionDecl>(D)) + HasThis = FD->isCXXInstanceMember(); + } + + /// A type into which \c ParamIdx can be serialized. + /// + /// A static assertion that it's of the correct size follows the \c ParamIdx + /// class definition. + typedef uint32_t SerialType; + + /// Produce a representation that can later be passed to \c deserialize to + /// construct an equivalent \c ParamIdx. + SerialType serialize() const { + return *reinterpret_cast<const SerialType *>(this); + } + + /// Construct from a result from \c serialize. + static ParamIdx deserialize(SerialType S) { + ParamIdx P(*reinterpret_cast<ParamIdx *>(&S)); + assert((!P.IsValid || P.Idx >= 1) && "valid Idx must be one-origin"); + return P; + } + + /// Is this parameter index valid? + bool isValid() const { return IsValid; } + + /// Get the parameter index as it would normally be encoded for attributes at + /// the source level of representation: one-origin including any C++ implicit + /// this parameter. + /// + /// This encoding thus makes sense for diagnostics, pretty printing, and + /// constructing new attributes from a source-like specification. + unsigned getSourceIndex() const { + assert(isValid() && "ParamIdx must be valid"); + return Idx; + } + + /// Get the parameter index as it would normally be encoded at the AST level + /// of representation: zero-origin not including any C++ implicit this + /// parameter. + /// + /// This is the encoding primarily used in Sema. However, in diagnostics, + /// Sema uses \c getSourceIndex instead. + unsigned getASTIndex() const { + assert(isValid() && "ParamIdx must be valid"); + assert(Idx >= 1 + HasThis && + "stored index must be base-1 and not specify C++ implicit this"); + return Idx - 1 - HasThis; + } + + /// Get the parameter index as it would normally be encoded at the LLVM level + /// of representation: zero-origin including any C++ implicit this parameter. + /// + /// This is the encoding primarily used in CodeGen. + unsigned getLLVMIndex() const { + assert(isValid() && "ParamIdx must be valid"); + assert(Idx >= 1 && "stored index must be base-1"); + return Idx - 1; + } + + bool operator==(const ParamIdx &I) const { + assertComparable(I); + return Idx == I.Idx; + } + bool operator!=(const ParamIdx &I) const { + assertComparable(I); + return Idx != I.Idx; + } + bool operator<(const ParamIdx &I) const { + assertComparable(I); + return Idx < I.Idx; + } + bool operator>(const ParamIdx &I) const { + assertComparable(I); + return Idx > I.Idx; + } + bool operator<=(const ParamIdx &I) const { + assertComparable(I); + return Idx <= I.Idx; + } + bool operator>=(const ParamIdx &I) const { + assertComparable(I); + return Idx >= I.Idx; + } +}; + +static_assert(sizeof(ParamIdx) == sizeof(ParamIdx::SerialType), + "ParamIdx does not fit its serialization type"); + #include "clang/AST/Attrs.inc" inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, diff --git a/include/clang/AST/Availability.h b/include/clang/AST/Availability.h index 5ed8313784567..28f3c3c01d200 100644 --- a/include/clang/AST/Availability.h +++ b/include/clang/AST/Availability.h @@ -15,12 +15,12 @@ #define LLVM_CLANG_AST_AVAILABILITY_H #include "clang/Basic/SourceLocation.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/VersionTuple.h" namespace clang { -/// \brief One specifier in an @available expression. +/// One specifier in an @available expression. /// /// \code /// @available(macos 10.10, *) diff --git a/include/clang/AST/BuiltinTypes.def b/include/clang/AST/BuiltinTypes.def index e4f5f7db2f73c..400efcb1981f1 100644 --- a/include/clang/AST/BuiltinTypes.def +++ b/include/clang/AST/BuiltinTypes.def @@ -72,6 +72,9 @@ UNSIGNED_TYPE(UChar, UnsignedCharTy) // 'wchar_t' for targets where it's unsigned SHARED_SINGLETON_TYPE(UNSIGNED_TYPE(WChar_U, WCharTy)) +// 'char8_t' in C++20 (proposed) +UNSIGNED_TYPE(Char8, Char8Ty) + // 'char16_t' in C++ UNSIGNED_TYPE(Char16, Char16Ty) @@ -119,6 +122,80 @@ SIGNED_TYPE(LongLong, LongLongTy) // '__int128_t' SIGNED_TYPE(Int128, Int128Ty) +//===- Fixed point types --------------------------------------------------===// + +// 'short _Accum' +SIGNED_TYPE(ShortAccum, ShortAccumTy) + +// '_Accum' +SIGNED_TYPE(Accum, AccumTy) + +// 'long _Accum' +SIGNED_TYPE(LongAccum, LongAccumTy) + +// 'unsigned short _Accum' +UNSIGNED_TYPE(UShortAccum, UnsignedShortAccumTy) + +// 'unsigned _Accum' +UNSIGNED_TYPE(UAccum, UnsignedAccumTy) + +// 'unsigned long _Accum' +UNSIGNED_TYPE(ULongAccum, UnsignedLongAccumTy) + +// 'short _Fract' +SIGNED_TYPE(ShortFract, ShortFractTy) + +// '_Fract' +SIGNED_TYPE(Fract, FractTy) + +// 'long _Fract' +SIGNED_TYPE(LongFract, LongFractTy) + +// 'unsigned short _Fract' +UNSIGNED_TYPE(UShortFract, UnsignedShortFractTy) + +// 'unsigned _Fract' +UNSIGNED_TYPE(UFract, UnsignedFractTy) + +// 'unsigned long _Fract' +UNSIGNED_TYPE(ULongFract, UnsignedLongFractTy) + +// '_Sat short _Accum' +SIGNED_TYPE(SatShortAccum, SatShortAccumTy) + +// '_Sat _Accum' +SIGNED_TYPE(SatAccum, SatAccumTy) + +// '_Sat long _Accum' +SIGNED_TYPE(SatLongAccum, SatLongAccumTy) + +// '_Sat unsigned short _Accum' +UNSIGNED_TYPE(SatUShortAccum, SatUnsignedShortAccumTy) + +// '_Sat unsigned _Accum' +UNSIGNED_TYPE(SatUAccum, SatUnsignedAccumTy) + +// '_Sat unsigned long _Accum' +UNSIGNED_TYPE(SatULongAccum, SatUnsignedLongAccumTy) + +// '_Sat short _Fract' +SIGNED_TYPE(SatShortFract, SatShortFractTy) + +// '_Sat _Fract' +SIGNED_TYPE(SatFract, SatFractTy) + +// '_Sat long _Fract' +SIGNED_TYPE(SatLongFract, SatLongFractTy) + +// '_Sat unsigned short _Fract' +UNSIGNED_TYPE(SatUShortFract, SatUnsignedShortFractTy) + +// '_Sat unsigned _Fract' +UNSIGNED_TYPE(SatUFract, SatUnsignedFractTy) + +// '_Sat unsigned long _Fract' +UNSIGNED_TYPE(SatULongFract, SatUnsignedLongFractTy) + //===- Floating point types -----------------------------------------------===// // 'half' in OpenCL, '__fp16' in ARM NEON. diff --git a/include/clang/AST/CXXInheritance.h b/include/clang/AST/CXXInheritance.h index 11fb229f0c091..2ae1d8b25823b 100644 --- a/include/clang/AST/CXXInheritance.h +++ b/include/clang/AST/CXXInheritance.h @@ -35,7 +35,7 @@ namespace clang { class ASTContext; class NamedDecl; -/// \brief Represents an element in a path from a derived class to a +/// Represents an element in a path from a derived class to a /// base class. /// /// Each step in the path references the link from a @@ -43,15 +43,15 @@ class NamedDecl; /// base "number" that identifies which base subobject of the /// original derived class we are referencing. struct CXXBasePathElement { - /// \brief The base specifier that states the link from a derived + /// The base specifier that states the link from a derived /// class to a base class, which will be followed by this base /// path element. const CXXBaseSpecifier *Base; - /// \brief The record decl of the class that the base is a base of. + /// The record decl of the class that the base is a base of. const CXXRecordDecl *Class; - /// \brief Identifies which base class subobject (of type + /// Identifies which base class subobject (of type /// \c Base->getType()) this base path element refers to. /// /// This value is only valid if \c !Base->isVirtual(), because there @@ -60,7 +60,7 @@ struct CXXBasePathElement { int SubobjectNumber; }; -/// \brief Represents a path from a specific derived class +/// Represents a path from a specific derived class /// (which is not represented as part of the path) to a particular /// (direct or indirect) base class subobject. /// @@ -70,14 +70,14 @@ struct CXXBasePathElement { /// subobject is being used. class CXXBasePath : public SmallVector<CXXBasePathElement, 4> { public: - /// \brief The access along this inheritance path. This is only + /// The access along this inheritance path. This is only /// calculated when recording paths. AS_none is a special value /// used to indicate a path which permits no legal access. AccessSpecifier Access = AS_public; CXXBasePath() = default; - /// \brief The set of declarations found inside this base class + /// The set of declarations found inside this base class /// subobject. DeclContext::lookup_result Decls; @@ -119,24 +119,42 @@ public: class CXXBasePaths { friend class CXXRecordDecl; - /// \brief The type from which this search originated. + /// The type from which this search originated. CXXRecordDecl *Origin = nullptr; /// Paths - The actual set of paths that can be taken from the /// derived class to the same base class. std::list<CXXBasePath> Paths; - + /// ClassSubobjects - Records the class subobjects for each class - /// type that we've seen. The first element in the pair says + /// type that we've seen. The first element IsVirtBase says /// whether we found a path to a virtual base for that class type, - /// while the element contains the number of non-virtual base + /// while NumberOfNonVirtBases contains the number of non-virtual base /// class subobjects for that class type. The key of the map is /// the cv-unqualified canonical type of the base class subobject. - llvm::SmallDenseMap<QualType, std::pair<bool, unsigned>, 8> ClassSubobjects; + struct IsVirtBaseAndNumberNonVirtBases { + unsigned IsVirtBase : 1; + unsigned NumberOfNonVirtBases : 31; + }; + llvm::SmallDenseMap<QualType, IsVirtBaseAndNumberNonVirtBases, 8> + ClassSubobjects; /// VisitedDependentRecords - Records the dependent records that have been /// already visited. - llvm::SmallDenseSet<const CXXRecordDecl *, 4> VisitedDependentRecords; + llvm::SmallPtrSet<const CXXRecordDecl *, 4> VisitedDependentRecords; + + /// DetectedVirtual - The base class that is virtual. + const RecordType *DetectedVirtual = nullptr; + + /// ScratchPath - A BasePath that is used by Sema::lookupInBases + /// to help build the set of paths. + CXXBasePath ScratchPath; + + /// Array of the declarations that have been found. This + /// array is constructed only if needed, e.g., to iterate over the + /// results within LookupResult. + std::unique_ptr<NamedDecl *[]> DeclsFound; + unsigned NumDeclsFound = 0; /// FindAmbiguities - Whether Sema::IsDerivedFrom should try find /// ambiguous paths while it is looking for a path from a derived @@ -152,20 +170,7 @@ class CXXBasePaths { /// if it finds a path that goes across a virtual base. The virtual class /// is also recorded. bool DetectVirtual; - - /// ScratchPath - A BasePath that is used by Sema::lookupInBases - /// to help build the set of paths. - CXXBasePath ScratchPath; - /// DetectedVirtual - The base class that is virtual. - const RecordType *DetectedVirtual = nullptr; - - /// \brief Array of the declarations that have been found. This - /// array is constructed only if needed, e.g., to iterate over the - /// results within LookupResult. - std::unique_ptr<NamedDecl *[]> DeclsFound; - unsigned NumDeclsFound = 0; - void ComputeDeclsFound(); bool lookupInBases(ASTContext &Context, const CXXRecordDecl *Record, @@ -196,53 +201,53 @@ public: decl_range found_decls(); - /// \brief Determine whether the path from the most-derived type to the + /// Determine whether the path from the most-derived type to the /// given base type is ambiguous (i.e., it refers to multiple subobjects of /// the same base type). bool isAmbiguous(CanQualType BaseType); - /// \brief Whether we are finding multiple paths to detect ambiguities. + /// Whether we are finding multiple paths to detect ambiguities. bool isFindingAmbiguities() const { return FindAmbiguities; } - /// \brief Whether we are recording paths. + /// Whether we are recording paths. bool isRecordingPaths() const { return RecordPaths; } - /// \brief Specify whether we should be recording paths or not. + /// Specify whether we should be recording paths or not. void setRecordingPaths(bool RP) { RecordPaths = RP; } - /// \brief Whether we are detecting virtual bases. + /// Whether we are detecting virtual bases. bool isDetectingVirtual() const { return DetectVirtual; } - /// \brief The virtual base discovered on the path (if we are merely + /// The virtual base discovered on the path (if we are merely /// detecting virtuals). const RecordType* getDetectedVirtual() const { return DetectedVirtual; } - /// \brief Retrieve the type from which this base-paths search + /// Retrieve the type from which this base-paths search /// began CXXRecordDecl *getOrigin() const { return Origin; } void setOrigin(CXXRecordDecl *Rec) { Origin = Rec; } - /// \brief Clear the base-paths results. + /// Clear the base-paths results. void clear(); - /// \brief Swap this data structure's contents with another CXXBasePaths + /// Swap this data structure's contents with another CXXBasePaths /// object. void swap(CXXBasePaths &Other); }; -/// \brief Uniquely identifies a virtual method within a class +/// Uniquely identifies a virtual method within a class /// hierarchy by the method itself and a class subobject number. struct UniqueVirtualMethod { - /// \brief The overriding virtual method. + /// The overriding virtual method. CXXMethodDecl *Method = nullptr; - /// \brief The subobject in which the overriding virtual method + /// The subobject in which the overriding virtual method /// resides. unsigned Subobject = 0; - /// \brief The virtual base class subobject of which this overridden + /// The virtual base class subobject of which this overridden /// virtual method is a part. Note that this records the closest /// derived virtual base class subobject. const CXXRecordDecl *InVirtualSubobject = nullptr; @@ -266,7 +271,7 @@ struct UniqueVirtualMethod { } }; -/// \brief The set of methods that override a given virtual method in +/// The set of methods that override a given virtual method in /// each subobject where it occurs. /// /// The first part of the pair is the subobject in which the @@ -310,7 +315,7 @@ public: void replaceAll(UniqueVirtualMethod Overriding); }; -/// \brief A mapping from each virtual member function to its set of +/// A mapping from each virtual member function to its set of /// final overriders. /// /// Within a class hierarchy for a given derived class, each virtual @@ -364,7 +369,7 @@ public: class CXXFinalOverriderMap : public llvm::MapVector<const CXXMethodDecl *, OverridingMethods> {}; -/// \brief A set of all the primary bases for a class. +/// A set of all the primary bases for a class. class CXXIndirectPrimaryBaseSet : public llvm::SmallSet<const CXXRecordDecl*, 32> {}; diff --git a/include/clang/AST/CanonicalType.h b/include/clang/AST/CanonicalType.h index 6487613200de3..63a0af66eec37 100644 --- a/include/clang/AST/CanonicalType.h +++ b/include/clang/AST/CanonicalType.h @@ -44,7 +44,7 @@ class TemplateTypeParmDecl; // Canonical, qualified type template //----------------------------------------------------------------------------// -/// \brief Represents a canonical, potentially-qualified type. +/// Represents a canonical, potentially-qualified type. /// /// The CanQual template is a lightweight smart pointer that provides access /// to the canonical representation of a type, where all typedefs and other @@ -64,35 +64,35 @@ class TemplateTypeParmDecl; /// a call to ASTContext::getCanonicalType(). template<typename T = Type> class CanQual { - /// \brief The actual, canonical type. + /// The actual, canonical type. QualType Stored; public: - /// \brief Constructs a NULL canonical type. + /// Constructs a NULL canonical type. CanQual() = default; - /// \brief Converting constructor that permits implicit upcasting of + /// Converting constructor that permits implicit upcasting of /// canonical type pointers. template <typename U> CanQual(const CanQual<U> &Other, typename std::enable_if<std::is_base_of<T, U>::value, int>::type = 0); - /// \brief Retrieve the underlying type pointer, which refers to a + /// Retrieve the underlying type pointer, which refers to a /// canonical type. /// /// The underlying pointer must not be nullptr. const T *getTypePtr() const { return cast<T>(Stored.getTypePtr()); } - /// \brief Retrieve the underlying type pointer, which refers to a + /// Retrieve the underlying type pointer, which refers to a /// canonical type, or nullptr. const T *getTypePtrOrNull() const { return cast_or_null<T>(Stored.getTypePtrOrNull()); } - /// \brief Implicit conversion to a qualified type. + /// Implicit conversion to a qualified type. operator QualType() const { return Stored; } - /// \brief Implicit conversion to bool. + /// Implicit conversion to bool. explicit operator bool() const { return !isNull(); } bool isNull() const { @@ -101,7 +101,7 @@ public: SplitQualType split() const { return Stored.split(); } - /// \brief Retrieve a canonical type pointer with a different static type, + /// Retrieve a canonical type pointer with a different static type, /// upcasting or downcasting as needed. /// /// The getAs() function is typically used to try to downcast to a @@ -122,17 +122,17 @@ public: template<typename U> CanProxy<U> castAs() const; - /// \brief Overloaded arrow operator that produces a canonical type + /// Overloaded arrow operator that produces a canonical type /// proxy. CanProxy<T> operator->() const; - /// \brief Retrieve all qualifiers. + /// Retrieve all qualifiers. Qualifiers getQualifiers() const { return Stored.getLocalQualifiers(); } - /// \brief Retrieve the const/volatile/restrict qualifiers. + /// Retrieve the const/volatile/restrict qualifiers. unsigned getCVRQualifiers() const { return Stored.getLocalCVRQualifiers(); } - /// \brief Determines whether this type has any qualifiers + /// Determines whether this type has any qualifiers bool hasQualifiers() const { return Stored.hasLocalQualifiers(); } bool isConstQualified() const { @@ -147,45 +147,45 @@ public: return Stored.isLocalRestrictQualified(); } - /// \brief Determines if this canonical type is furthermore + /// Determines if this canonical type is furthermore /// canonical as a parameter. The parameter-canonicalization /// process decays arrays to pointers and drops top-level qualifiers. bool isCanonicalAsParam() const { return Stored.isCanonicalAsParam(); } - /// \brief Retrieve the unqualified form of this type. + /// Retrieve the unqualified form of this type. CanQual<T> getUnqualifiedType() const; - /// \brief Retrieves a version of this type with const applied. + /// Retrieves a version of this type with const applied. /// Note that this does not always yield a canonical type. QualType withConst() const { return Stored.withConst(); } - /// \brief Determines whether this canonical type is more qualified than + /// Determines whether this canonical type is more qualified than /// the @p Other canonical type. bool isMoreQualifiedThan(CanQual<T> Other) const { return Stored.isMoreQualifiedThan(Other.Stored); } - /// \brief Determines whether this canonical type is at least as qualified as + /// Determines whether this canonical type is at least as qualified as /// the @p Other canonical type. bool isAtLeastAsQualifiedAs(CanQual<T> Other) const { return Stored.isAtLeastAsQualifiedAs(Other.Stored); } - /// \brief If the canonical type is a reference type, returns the type that + /// If the canonical type is a reference type, returns the type that /// it refers to; otherwise, returns the type itself. CanQual<Type> getNonReferenceType() const; - /// \brief Retrieve the internal representation of this canonical type. + /// Retrieve the internal representation of this canonical type. void *getAsOpaquePtr() const { return Stored.getAsOpaquePtr(); } - /// \brief Construct a canonical type from its internal representation. + /// Construct a canonical type from its internal representation. static CanQual<T> getFromOpaquePtr(void *Ptr); - /// \brief Builds a canonical type from a QualType. + /// Builds a canonical type from a QualType. /// /// This routine is inherently unsafe, because it requires the user to /// ensure that the given type is a canonical type with the correct @@ -209,7 +209,7 @@ inline bool operator!=(CanQual<T> x, CanQual<U> y) { return x.getAsOpaquePtr() != y.getAsOpaquePtr(); } -/// \brief Represents a canonical, potentially-qualified type. +/// Represents a canonical, potentially-qualified type. using CanQualType = CanQual<Type>; inline CanQualType Type::getCanonicalTypeUnqualified() const { @@ -234,7 +234,7 @@ return CanQualType::CreateUnsafe(this->getTypePtr()->Accessor()); \ #define LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(Type, Accessor) \ Type Accessor() const { return this->getTypePtr()->Accessor(); } -/// \brief Base class of all canonical proxy types, which is responsible for +/// Base class of all canonical proxy types, which is responsible for /// storing the underlying canonical type and providing basic conversions. template<typename T> class CanProxyBase { @@ -242,10 +242,10 @@ protected: CanQual<T> Stored; public: - /// \brief Retrieve the pointer to the underlying Type + /// Retrieve the pointer to the underlying Type const T *getTypePtr() const { return Stored.getTypePtr(); } - /// \brief Implicit conversion to the underlying pointer. + /// Implicit conversion to the underlying pointer. /// /// Also provides the ability to use canonical type proxies in a Boolean // context,e.g., @@ -254,7 +254,7 @@ public: /// @endcode operator const T*() const { return this->Stored.getTypePtrOrNull(); } - /// \brief Try to convert the given canonical type to a specific structural + /// Try to convert the given canonical type to a specific structural /// type. template<typename U> CanProxy<U> getAs() const { return this->Stored.template getAs<U>(); @@ -313,7 +313,7 @@ public: LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(bool, isSpecifierType) LLVM_CLANG_CANPROXY_SIMPLE_ACCESSOR(CXXRecordDecl*, getAsCXXRecordDecl) - /// \brief Retrieve the proxy-adaptor type. + /// Retrieve the proxy-adaptor type. /// /// This arrow operator is used when CanProxyAdaptor has been specialized /// for the given type T. In that case, we reference members of the @@ -324,7 +324,7 @@ public: } }; -/// \brief Replacable canonical proxy adaptor class that provides the link +/// Replaceable canonical proxy adaptor class that provides the link /// between a canonical type and the accessors of the type. /// /// The CanProxyAdaptor is a replaceable class template that is instantiated @@ -337,7 +337,7 @@ public: template<typename T> struct CanProxyAdaptor : CanProxyBase<T> {}; -/// \brief Canonical proxy type returned when retrieving the members of a +/// Canonical proxy type returned when retrieving the members of a /// canonical type or as the result of the @c CanQual<T>::getAs member /// function. /// @@ -347,13 +347,13 @@ struct CanProxyAdaptor : CanProxyBase<T> {}; template<typename T> class CanProxy : public CanProxyAdaptor<T> { public: - /// \brief Build a NULL proxy. + /// Build a NULL proxy. CanProxy() = default; - /// \brief Build a proxy to the given canonical type. + /// Build a proxy to the given canonical type. CanProxy(CanQual<T> Stored) { this->Stored = Stored; } - /// \brief Implicit conversion to the stored canonical type. + /// Implicit conversion to the stored canonical type. operator CanQual<T>() const { return this->Stored; } }; @@ -396,7 +396,7 @@ namespace clang { // Canonical proxy adaptors for canonical type nodes. //----------------------------------------------------------------------------// -/// \brief Iterator adaptor that turns an iterator over canonical QualTypes +/// Iterator adaptor that turns an iterator over canonical QualTypes /// into an iterator over CanQualTypes. template <typename InputIterator> struct CanTypeIterator diff --git a/include/clang/AST/Comment.h b/include/clang/AST/Comment.h index 94470cbf305f6..e3a427d8aa0d8 100644 --- a/include/clang/AST/Comment.h +++ b/include/clang/AST/Comment.h @@ -990,7 +990,7 @@ struct DeclInfo { /// CurrentDecl is the declaration with which the FullComment is associated. /// - /// It can be different from \c CommentDecl. It happens when we we decide + /// It can be different from \c CommentDecl. It happens when we decide /// that the comment originally attached to \c CommentDecl is fine for /// \c CurrentDecl too (for example, for a redeclaration or an overrider of /// \c CommentDecl). diff --git a/include/clang/AST/CommentBriefParser.h b/include/clang/AST/CommentBriefParser.h index be5b8eeb80c34..baa22930539e5 100644 --- a/include/clang/AST/CommentBriefParser.h +++ b/include/clang/AST/CommentBriefParser.h @@ -24,7 +24,7 @@ namespace comments { /// /// Due to a variety of comment styles, it considers the following as "a brief /// description", in order of priority: -/// \li a \\brief or \\short command, +/// \li a \or \\short command, /// \li the first paragraph, /// \li a \\result or \\return or \\returns paragraph. class BriefParser { diff --git a/include/clang/AST/CommentCommandTraits.h b/include/clang/AST/CommentCommandTraits.h index 289f2fd345afa..bac4e99dc7a4c 100644 --- a/include/clang/AST/CommentCommandTraits.h +++ b/include/clang/AST/CommentCommandTraits.h @@ -26,7 +26,7 @@ namespace clang { namespace comments { -/// \brief Information about a single command. +/// Information about a single command. /// /// When reordering, adding or removing members please update the corresponding /// TableGen backend. @@ -57,7 +57,7 @@ struct CommandInfo { unsigned IsBlockCommand : 1; /// True if this command is introducing a brief documentation - /// paragraph (\\brief or an alias). + /// paragraph (\or an alias). unsigned IsBriefCommand : 1; /// True if this command is \\returns or an alias. @@ -77,29 +77,29 @@ struct CommandInfo { /// True if this command is \\deprecated or an alias. unsigned IsDeprecatedCommand : 1; - /// \brief True if this is a \\headerfile-like command. + /// True if this is a \\headerfile-like command. unsigned IsHeaderfileCommand : 1; /// True if we don't want to warn about this command being passed an empty /// paragraph. Meaningful only for block commands. unsigned IsEmptyParagraphAllowed : 1; - /// \brief True if this command is a verbatim-like block command. + /// True if this command is a verbatim-like block command. /// /// A verbatim-like block command eats every character (except line starting /// decorations) until matching end command is seen or comment end is hit. unsigned IsVerbatimBlockCommand : 1; - /// \brief True if this command is an end command for a verbatim-like block. + /// True if this command is an end command for a verbatim-like block. unsigned IsVerbatimBlockEndCommand : 1; - /// \brief True if this command is a verbatim line command. + /// True if this command is a verbatim line command. /// /// A verbatim-like line command eats everything until a newline is seen or /// comment end is hit. unsigned IsVerbatimLineCommand : 1; - /// \brief True if this command contains a declaration for the entity being + /// True if this command contains a declaration for the entity being /// documented. /// /// For example: @@ -108,17 +108,17 @@ struct CommandInfo { /// \endcode unsigned IsDeclarationCommand : 1; - /// \brief True if verbatim-like line command is a function declaration. + /// True if verbatim-like line command is a function declaration. unsigned IsFunctionDeclarationCommand : 1; - /// \brief True if block command is further describing a container API; such + /// True if block command is further describing a container API; such /// as \@coclass, \@classdesign, etc. unsigned IsRecordLikeDetailCommand : 1; - /// \brief True if block command is a container API; such as \@interface. + /// True if block command is a container API; such as \@interface. unsigned IsRecordLikeDeclarationCommand : 1; - /// \brief True if this command is unknown. This \c CommandInfo object was + /// True if this command is unknown. This \c CommandInfo object was /// created during parsing. unsigned IsUnknownCommand : 1; }; diff --git a/include/clang/AST/CommentLexer.h b/include/clang/AST/CommentLexer.h index 5bb075807be59..52c4eb9e309a1 100644 --- a/include/clang/AST/CommentLexer.h +++ b/include/clang/AST/CommentLexer.h @@ -52,7 +52,7 @@ enum TokenKind { }; } // end namespace tok -/// \brief Comment token. +/// Comment token. class Token { friend class Lexer; friend class TextTokenRetokenizer; @@ -72,7 +72,7 @@ class Token { /// Integer value associated with a token. /// - /// If the token is a konwn command, contains command ID and TextPtr is + /// If the token is a known command, contains command ID and TextPtr is /// unused (command spelling can be found with CommandTraits). Otherwise, /// contains the length of the string that starts at TextPtr. unsigned IntVal; @@ -217,7 +217,7 @@ public: void dump(const Lexer &L, const SourceManager &SM) const; }; -/// \brief Comment lexer. +/// Comment lexer. class Lexer { private: Lexer(const Lexer &) = delete; @@ -281,6 +281,11 @@ private: /// command, including command marker. SmallString<16> VerbatimBlockEndCommandName; + /// If true, the commands, html tags, etc will be parsed and reported as + /// separate tokens inside the comment body. If false, the comment text will + /// be parsed into text and newline tokens. + bool ParseCommands; + /// Given a character reference name (e.g., "lt"), return the character that /// it stands for (e.g., "<"). StringRef resolveHTMLNamedCharacterReference(StringRef Name) const; @@ -315,12 +320,11 @@ private: /// Eat string matching regexp \code \s*\* \endcode. void skipLineStartingDecorations(); - /// Lex stuff inside comments. CommentEnd should be set correctly. + /// Lex comment text, including commands if ParseCommands is set to true. void lexCommentText(Token &T); - void setupAndLexVerbatimBlock(Token &T, - const char *TextBegin, - char Marker, const CommandInfo *Info); + void setupAndLexVerbatimBlock(Token &T, const char *TextBegin, char Marker, + const CommandInfo *Info); void lexVerbatimBlockFirstLine(Token &T); @@ -343,14 +347,13 @@ private: public: Lexer(llvm::BumpPtrAllocator &Allocator, DiagnosticsEngine &Diags, - const CommandTraits &Traits, - SourceLocation FileLoc, - const char *BufferStart, const char *BufferEnd); + const CommandTraits &Traits, SourceLocation FileLoc, + const char *BufferStart, const char *BufferEnd, + bool ParseCommands = true); void lex(Token &T); - StringRef getSpelling(const Token &Tok, - const SourceManager &SourceMgr, + StringRef getSpelling(const Token &Tok, const SourceManager &SourceMgr, bool *Invalid = nullptr) const; }; diff --git a/include/clang/AST/CommentSema.h b/include/clang/AST/CommentSema.h index 230e52739f24c..0e94c33970caf 100644 --- a/include/clang/AST/CommentSema.h +++ b/include/clang/AST/CommentSema.h @@ -55,7 +55,7 @@ class Sema { /// Contains a valid value if \c DeclInfo->IsFilled is true. llvm::StringMap<TParamCommandComment *> TemplateParameterDocs; - /// AST node for the \\brief command and its aliases. + /// AST node for the \command and its aliases. const BlockCommandComment *BriefCommand; /// AST node for the \\headerfile command. @@ -187,7 +187,7 @@ public: void checkReturnsCommand(const BlockCommandComment *Command); /// Emit diagnostics about duplicate block commands that should be - /// used only once per comment, e.g., \\brief and \\returns. + /// used only once per comment, e.g., \and \\returns. void checkBlockCommandDuplicate(const BlockCommandComment *Command); void checkDeprecatedCommand(const BlockCommandComment *Comment); diff --git a/include/clang/AST/ComparisonCategories.h b/include/clang/AST/ComparisonCategories.h new file mode 100644 index 0000000000000..23bfd708e7eb4 --- /dev/null +++ b/include/clang/AST/ComparisonCategories.h @@ -0,0 +1,243 @@ +//===- ComparisonCategories.h - Three Way Comparison Data -------*- 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 Comparison Category enum and data types, which +// store the types and expressions needed to support operator<=> +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_AST_COMPARISONCATEGORIES_H +#define LLVM_CLANG_AST_COMPARISONCATEGORIES_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/DenseMap.h" +#include <array> +#include <cassert> + +namespace llvm { + class StringRef; + class APSInt; +} + +namespace clang { + +class ASTContext; +class VarDecl; +class CXXRecordDecl; +class Sema; +class QualType; +class NamespaceDecl; + +/// An enumeration representing the different comparison categories +/// types. +/// +/// C++2a [cmp.categories.pre] The types weak_equality, strong_equality, +/// partial_ordering, weak_ordering, and strong_ordering are collectively +/// termed the comparison category types. +enum class ComparisonCategoryType : unsigned char { + WeakEquality, + StrongEquality, + PartialOrdering, + WeakOrdering, + StrongOrdering, + First = WeakEquality, + Last = StrongOrdering +}; + +/// An enumeration representing the possible results of a three-way +/// comparison. These values map onto instances of comparison category types +/// defined in the standard library. e.g. 'std::strong_ordering::less'. +enum class ComparisonCategoryResult : unsigned char { + Equal, + Equivalent, + Nonequivalent, + Nonequal, + Less, + Greater, + Unordered, + Last = Unordered +}; + +class ComparisonCategoryInfo { + friend class ComparisonCategories; + friend class Sema; + +public: + ComparisonCategoryInfo(const ASTContext &Ctx, CXXRecordDecl *RD, + ComparisonCategoryType Kind) + : Ctx(Ctx), Record(RD), Kind(Kind) {} + + struct ValueInfo { + ComparisonCategoryResult Kind; + VarDecl *VD; + + ValueInfo(ComparisonCategoryResult Kind, VarDecl *VD) + : Kind(Kind), VD(VD) {} + + /// True iff we've successfully evaluated the variable as a constant + /// expression and extracted its integer value. + bool hasValidIntValue() const; + + /// Get the constant integer value used by this variable to represent + /// the comparison category result type. + llvm::APSInt getIntValue() const; + }; +private: + const ASTContext &Ctx; + + /// A map containing the comparison category result decls from the + /// standard library. The key is a value of ComparisonCategoryResult. + mutable llvm::SmallVector< + ValueInfo, static_cast<unsigned>(ComparisonCategoryResult::Last) + 1> + Objects; + + /// Lookup the ValueInfo struct for the specified ValueKind. If the + /// VarDecl for the value cannot be found, nullptr is returned. + /// + /// If the ValueInfo does not have a valid integer value the variable + /// is evaluated as a constant expression to determine that value. + ValueInfo *lookupValueInfo(ComparisonCategoryResult ValueKind) const; + +public: + /// The declaration for the comparison category type from the + /// standard library. + // FIXME: Make this const + CXXRecordDecl *Record = nullptr; + + /// The Kind of the comparison category type + ComparisonCategoryType Kind; + +public: + QualType getType() const; + + const ValueInfo *getValueInfo(ComparisonCategoryResult ValueKind) const { + ValueInfo *Info = lookupValueInfo(ValueKind); + assert(Info && + "comparison category does not contain the specified result kind"); + assert(Info->hasValidIntValue() && + "couldn't determine the integer constant for this value"); + return Info; + } + + /// True iff the comparison category is an equality comparison. + bool isEquality() const { return !isOrdered(); } + + /// True iff the comparison category is a relational comparison. + bool isOrdered() const { + using CCK = ComparisonCategoryType; + return Kind == CCK::PartialOrdering || Kind == CCK::WeakOrdering || + Kind == CCK::StrongOrdering; + } + + /// True iff the comparison is "strong". i.e. it checks equality and + /// not equivalence. + bool isStrong() const { + using CCK = ComparisonCategoryType; + return Kind == CCK::StrongEquality || Kind == CCK::StrongOrdering; + } + + /// True iff the comparison is not totally ordered. + bool isPartial() const { + using CCK = ComparisonCategoryType; + return Kind == CCK::PartialOrdering; + } + + /// Converts the specified result kind into the the correct result kind + /// for this category. Specifically it lowers strong equality results to + /// weak equivalence if needed. + ComparisonCategoryResult makeWeakResult(ComparisonCategoryResult Res) const { + using CCR = ComparisonCategoryResult; + if (!isStrong()) { + if (Res == CCR::Equal) + return CCR::Equivalent; + if (Res == CCR::Nonequal) + return CCR::Nonequivalent; + } + return Res; + } + + const ValueInfo *getEqualOrEquiv() const { + return getValueInfo(makeWeakResult(ComparisonCategoryResult::Equal)); + } + const ValueInfo *getNonequalOrNonequiv() const { + assert(isEquality()); + return getValueInfo(makeWeakResult(ComparisonCategoryResult::Nonequal)); + } + const ValueInfo *getLess() const { + assert(isOrdered()); + return getValueInfo(ComparisonCategoryResult::Less); + } + const ValueInfo *getGreater() const { + assert(isOrdered()); + return getValueInfo(ComparisonCategoryResult::Greater); + } + const ValueInfo *getUnordered() const { + assert(isPartial()); + return getValueInfo(ComparisonCategoryResult::Unordered); + } +}; + +class ComparisonCategories { +public: + static StringRef getCategoryString(ComparisonCategoryType Kind); + static StringRef getResultString(ComparisonCategoryResult Kind); + + /// Return the list of results which are valid for the specified + /// comparison category type. + static std::vector<ComparisonCategoryResult> + getPossibleResultsForType(ComparisonCategoryType Type); + + /// Return the comparison category information for the category + /// specified by 'Kind'. + const ComparisonCategoryInfo &getInfo(ComparisonCategoryType Kind) const { + const ComparisonCategoryInfo *Result = lookupInfo(Kind); + assert(Result != nullptr && + "information for specified comparison category has not been built"); + return *Result; + } + + /// Return the comparison category information as specified by + /// `getCategoryForType(Ty)`. If the information is not already cached, + /// the declaration is looked up and a cache entry is created. + /// NOTE: Lookup is expected to succeed. Use lookupInfo if failure is + /// possible. + const ComparisonCategoryInfo &getInfoForType(QualType Ty) const; + +public: + /// Return the cached comparison category information for the + /// specified 'Kind'. If no cache entry is present the comparison category + /// type is looked up. If lookup fails nullptr is returned. Otherwise, a + /// new cache entry is created and returned + const ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) const; + + ComparisonCategoryInfo *lookupInfo(ComparisonCategoryType Kind) { + const auto &This = *this; + return const_cast<ComparisonCategoryInfo *>(This.lookupInfo(Kind)); + } + +private: + const ComparisonCategoryInfo *lookupInfoForType(QualType Ty) const; + +private: + friend class ASTContext; + + explicit ComparisonCategories(const ASTContext &Ctx) : Ctx(Ctx) {} + + const ASTContext &Ctx; + + /// A map from the ComparisonCategoryType (represented as 'char') to the + /// cached information for the specified category. + mutable llvm::DenseMap<char, ComparisonCategoryInfo> Data; + mutable NamespaceDecl *StdNS = nullptr; +}; + +} // namespace clang + +#endif diff --git a/include/clang/AST/DataCollection.h b/include/clang/AST/DataCollection.h index 229ac2bd0f22d..8b2a8345d9415 100644 --- a/include/clang/AST/DataCollection.h +++ b/include/clang/AST/DataCollection.h @@ -7,12 +7,12 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief This file declares helper methods for collecting data from AST nodes. +/// This file declares helper methods for collecting data from AST nodes. /// /// To collect data from Stmt nodes, subclass ConstStmtVisitor and include /// StmtDataCollectors.inc after defining the macros that you need. This /// provides data collection implementations for most Stmt kinds. Note -/// that that code requires some conditions to be met: +/// that the code requires some conditions to be met: /// /// - There must be a method addData(const T &Data) that accepts strings, /// integral types as well as QualType. All data is forwarded using diff --git a/include/clang/AST/Decl.h b/include/clang/AST/Decl.h index 04a832e552a4a..dde94599636f0 100644 --- a/include/clang/AST/Decl.h +++ b/include/clang/AST/Decl.h @@ -76,14 +76,14 @@ class TypeLoc; class UnresolvedSetImpl; class VarTemplateDecl; -/// \brief A container of type source information. +/// A container of type source information. /// /// A client can read the relevant info using TypeLoc wrappers, e.g: /// @code /// TypeLoc TL = TypeSourceInfo->getTypeLoc(); /// TL.getStartLoc().print(OS, SrcMgr); /// @endcode -class TypeSourceInfo { +class alignas(8) TypeSourceInfo { // Contains a memory block after the class, used for type source information, // allocated by ASTContext. friend class ASTContext; @@ -93,17 +93,17 @@ class TypeSourceInfo { TypeSourceInfo(QualType ty) : Ty(ty) {} public: - /// \brief Return the type wrapped by this type source info. + /// Return the type wrapped by this type source info. QualType getType() const { return Ty; } - /// \brief Return the TypeLoc wrapper for the type source info. + /// 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! + /// Override the type stored in this TypeSourceInfo. Use with caution! void overrideType(QualType T) { Ty = T; } }; -/// TranslationUnitDecl - The top declaration context. +/// The top declaration context. class TranslationUnitDecl : public Decl, public DeclContext { ASTContext &Ctx; @@ -134,7 +134,7 @@ public: } }; -/// \brief Represents a `#pragma comment` line. Always a child of +/// Represents a `#pragma comment` line. Always a child of /// TranslationUnitDecl. class PragmaCommentDecl final : public Decl, @@ -168,7 +168,7 @@ public: static bool classofKind(Kind K) { return K == PragmaComment; } }; -/// \brief Represents a `#pragma detect_mismatch` line. Always a child of +/// Represents a `#pragma detect_mismatch` line. Always a child of /// TranslationUnitDecl. class PragmaDetectMismatchDecl final : public Decl, @@ -201,7 +201,7 @@ public: static bool classofKind(Kind K) { return K == PragmaDetectMismatch; } }; -/// \brief Declaration context for names declared as extern "C" in C++. This +/// Declaration context for names declared as extern "C" in C++. This /// is neither the semantic nor lexical context for such declarations, but is /// used to check for conflicts with other extern "C" declarations. Example: /// @@ -240,10 +240,13 @@ public: } }; -/// NamedDecl - This represents a decl with a name. Many decls have names such +/// This represents a decl that may have a name. Many decls have names such /// as ObjCMethodDecl, but not \@class, etc. +/// +/// Note that not every NamedDecl is actually named (e.g., a struct might +/// be anonymous), and not every name is an identifier. class NamedDecl : public Decl { - /// Name - The name of this declaration, which is typically a normal + /// The name of this declaration, which is typically a normal /// identifier but may also be a special kind of name (C++ /// constructor, Objective-C selector, etc.) DeclarationName Name; @@ -258,13 +261,15 @@ protected: : Decl(DK, DC, L), Name(N) {} public: - /// getIdentifier - Get the identifier that names this declaration, - /// if there is one. This will return NULL if this declaration has - /// no name (e.g., for an unnamed class) or if the name is a special - /// name (C++ constructor, Objective-C selector, etc.). + /// Get the identifier that names this declaration, if there is one. + /// + /// This will return NULL if this declaration has no name (e.g., for + /// an unnamed class) or if the name is a special name (C++ constructor, + /// Objective-C selector, etc.). IdentifierInfo *getIdentifier() const { return Name.getAsIdentifierInfo(); } - /// getName - Get the name of identifier for this declaration as a StringRef. + /// Get the name of identifier for this declaration as a StringRef. + /// /// This requires that the declaration have a name and that it be a simple /// identifier. StringRef getName() const { @@ -272,11 +277,12 @@ public: return getIdentifier() ? getIdentifier()->getName() : ""; } - /// getNameAsString - Get a human-readable name for the declaration, even if - /// it is one of the special kinds of names (C++ constructor, Objective-C - /// selector, etc). Creating this name requires expensive string - /// manipulation, so it should be called only when performance doesn't matter. - /// For simple declarations, getNameAsCString() should suffice. + /// Get a human-readable name for the declaration, even if it is one of the + /// special kinds of names (C++ constructor, Objective-C selector, etc). + /// + /// Creating this name requires expensive string manipulation, so it should + /// be called only when performance doesn't matter. For simple declarations, + /// getNameAsCString() should suffice. // // FIXME: This function should be renamed to indicate that it is not just an // alternate form of getName(), and clients should move as appropriate. @@ -286,17 +292,19 @@ public: virtual void printName(raw_ostream &os) const; - /// getDeclName - Get the actual, stored name of the declaration, - /// which may be a special name. + /// Get the actual, stored name of the declaration, which may be a special + /// name. DeclarationName getDeclName() const { return Name; } - /// \brief Set the name of this declaration. + /// Set the name of this declaration. void setDeclName(DeclarationName N) { Name = N; } - /// printQualifiedName - Returns human-readable qualified name for - /// declaration, like A::B::i, for i being member of namespace A::B. - /// If declaration is not member of context which can be named (record, - /// namespace), it will return same result as printName(). + /// Returns a human-readable qualified name for this declaration, like + /// A::B::i, for i being member of namespace A::B. + /// + /// If the declaration is not a member of context which can be named (record, + /// namespace), it will return the same result as printName(). + /// /// Creating this name is expensive, so it should be called only when /// performance doesn't matter. void printQualifiedName(raw_ostream &OS) const; @@ -315,25 +323,25 @@ public: const PrintingPolicy &Policy, bool Qualified) const; - /// \brief Determine whether this declaration, if - /// known to be well-formed within its context, will replace the - /// declaration OldD if introduced into scope. A declaration will - /// replace another declaration if, for example, it is a - /// redeclaration of the same variable or function, but not if it is - /// a declaration of a different kind (function vs. class) or an - /// overloaded function. + /// Determine whether this declaration, if known to be well-formed within + /// its context, will replace the declaration OldD if introduced into scope. + /// + /// A declaration will replace another declaration if, for example, it is + /// a redeclaration of the same variable or function, but not if it is a + /// declaration of a different kind (function vs. class) or an overloaded + /// function. /// /// \param IsKnownNewer \c true if this declaration is known to be newer /// than \p OldD (for instance, if this declaration is newly-created). bool declarationReplaces(NamedDecl *OldD, bool IsKnownNewer = true) const; - /// \brief Determine whether this declaration has linkage. + /// Determine whether this declaration has linkage. bool hasLinkage() const; using Decl::isModulePrivate; using Decl::setModulePrivate; - /// \brief Determine whether this declaration is a C++ class member. + /// Determine whether this declaration is a C++ class member. bool isCXXClassMember() const { const DeclContext *DC = getDeclContext(); @@ -346,23 +354,24 @@ public: return DC->isRecord(); } - /// \brief Determine whether the given declaration is an instance member of + /// Determine whether the given declaration is an instance member of /// a C++ class. bool isCXXInstanceMember() const; - /// \brief Determine what kind of linkage this entity has. + /// Determine what kind of linkage this entity has. + /// /// This is not the linkage as defined by the standard or the codegen notion /// of linkage. It is just an implementation detail that is used to compute /// those. Linkage getLinkageInternal() const; - /// \brief Get the linkage from a semantic point of view. Entities in + /// Get the linkage from a semantic point of view. Entities in /// anonymous namespaces are external (in c++98). Linkage getFormalLinkage() const { return clang::getFormalLinkage(getLinkageInternal()); } - /// \brief True if this decl has external linkage. + /// True if this decl has external linkage. bool hasExternalFormalLinkage() const { return isExternalFormalLinkage(getLinkageInternal()); } @@ -377,12 +386,12 @@ public: return isExternallyVisible() && !getOwningModuleForLinkage(); } - /// \brief Determines the visibility of this entity. + /// Determines the visibility of this entity. Visibility getVisibility() const { return getLinkageAndVisibility().getVisibility(); } - /// \brief Determines the linkage and visibility of this entity. + /// Determines the linkage and visibility of this entity. LinkageInfo getLinkageAndVisibility() const; /// Kinds of explicit visibility. @@ -398,16 +407,16 @@ public: VisibilityForValue }; - /// \brief If visibility was explicitly specified for this + /// If visibility was explicitly specified for this /// declaration, return that visibility. Optional<Visibility> getExplicitVisibility(ExplicitVisibilityKind kind) const; - /// \brief True if the computed linkage is valid. Used for consistency + /// True if the computed linkage is valid. Used for consistency /// checking. Should always return true. bool isLinkageValid() const; - /// \brief True if something has required us to compute the linkage + /// True if something has required us to compute the linkage /// of this declaration. /// /// Language features which can retroactively change linkage (like a @@ -417,7 +426,7 @@ public: return hasCachedLinkage(); } - /// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for + /// Looks through UsingDecls and ObjCCompatibleAliasDecls for /// the underlying named decl. NamedDecl *getUnderlyingDecl() { // Fast-path the common case. @@ -451,7 +460,7 @@ inline raw_ostream &operator<<(raw_ostream &OS, const NamedDecl &ND) { return OS; } -/// LabelDecl - Represents the declaration of a label. Labels also have a +/// Represents the declaration of a label. Labels also have a /// corresponding LabelStmt, which indicates the position that the label was /// defined at. For normal labels, the location of the decl is the same as the /// location of the statement. For GNU local labels (__label__), the decl @@ -461,7 +470,7 @@ class LabelDecl : public NamedDecl { StringRef MSAsmName; bool MSAsmNameResolved = false; - /// LocStart - For normal labels, this is the same as the main declaration + /// 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. SourceLocation LocStart; @@ -501,18 +510,18 @@ public: static bool classofKind(Kind K) { return K == Label; } }; -/// NamespaceDecl - Represent a C++ namespace. +/// Represent a C++ namespace. class NamespaceDecl : public NamedDecl, public DeclContext, public Redeclarable<NamespaceDecl> { - /// LocStart - The starting location of the source range, pointing + /// The starting location of the source range, pointing /// to either the namespace or the inline keyword. SourceLocation LocStart; - /// RBraceLoc - The ending location of the source range. + /// The ending location of the source range. SourceLocation RBraceLoc; - /// \brief A pointer to either the anonymous namespace that lives just inside + /// A pointer to either the anonymous namespace that lives just inside /// this namespace or to the first namespace in the chain (the latter case /// only when this is not the first in the chain), along with a /// boolean value indicating whether this is an inline namespace. @@ -549,7 +558,7 @@ public: using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; - /// \brief Returns true if this is an anonymous namespace declaration. + /// Returns true if this is an anonymous namespace declaration. /// /// For example: /// \code @@ -562,28 +571,28 @@ public: return !getIdentifier(); } - /// \brief Returns true if this is an inline namespace declaration. + /// Returns true if this is an inline namespace declaration. bool isInline() const { return AnonOrFirstNamespaceAndInline.getInt(); } - /// \brief Set whether this is an inline namespace declaration. + /// Set whether this is an inline namespace declaration. void setInline(bool Inline) { AnonOrFirstNamespaceAndInline.setInt(Inline); } - /// \brief Get the original (first) namespace declaration. + /// Get the original (first) namespace declaration. NamespaceDecl *getOriginalNamespace(); - /// \brief Get the original (first) namespace declaration. + /// Get the original (first) namespace declaration. const NamespaceDecl *getOriginalNamespace() const; - /// \brief Return true if this declaration is an original (first) declaration + /// Return true if this declaration is an original (first) declaration /// of the namespace. This is false for non-original (subsequent) namespace /// declarations and anonymous namespaces. bool isOriginalNamespace() const; - /// \brief Retrieve the anonymous namespace nested inside this namespace, + /// Retrieve the anonymous namespace nested inside this namespace, /// if any. NamespaceDecl *getAnonymousNamespace() const { return getOriginalNamespace()->AnonOrFirstNamespaceAndInline.getPointer(); @@ -621,7 +630,7 @@ public: } }; -/// ValueDecl - Represent the declaration of a variable (in which case it is +/// Represent the declaration of a variable (in which case it is /// an lvalue) a function (in which case it is a function designator) or /// an enum constant. class ValueDecl : public NamedDecl { @@ -638,7 +647,7 @@ public: QualType getType() const { return DeclType; } void setType(QualType newType) { DeclType = newType; } - /// \brief Determine whether this symbol is weakly-imported, + /// Determine whether this symbol is weakly-imported, /// or declared with the weak or weak-ref attr. bool isWeak() const; @@ -647,18 +656,18 @@ public: static bool classofKind(Kind K) { return K >= firstValue && K <= lastValue; } }; -/// QualifierInfo - A struct with extended info about a syntactic +/// A struct with extended info about a syntactic /// name qualifier, to be used for the case of out-of-line declarations. struct QualifierInfo { NestedNameSpecifierLoc QualifierLoc; - /// NumTemplParamLists - The number of "outer" template parameter lists. + /// The number of "outer" template parameter lists. /// The count includes all of the template parameter lists that were matched /// against the template-ids occurring into the NNS and possibly (in the /// case of an explicit specialization) a final "template <>". unsigned NumTemplParamLists = 0; - /// TemplParamLists - A new-allocated array of size NumTemplParamLists, + /// A new-allocated array of size NumTemplParamLists, /// containing pointers to the "outer" template parameter lists. /// It includes all of the template parameter lists that were matched /// against the template-ids occurring into the NNS and possibly (in the @@ -669,13 +678,12 @@ struct QualifierInfo { QualifierInfo(const QualifierInfo &) = delete; QualifierInfo& operator=(const QualifierInfo &) = delete; - /// setTemplateParameterListsInfo - Sets info about "outer" template - /// parameter lists. + /// Sets info about "outer" template parameter lists. void setTemplateParameterListsInfo(ASTContext &Context, ArrayRef<TemplateParameterList *> TPLists); }; -/// \brief Represents a ValueDecl that came out of a declarator. +/// Represents a ValueDecl that came out of a declarator. /// Contains type source information through TypeSourceInfo. class DeclaratorDecl : public ValueDecl { // A struct representing both a TInfo and a syntactic qualifier, @@ -686,7 +694,7 @@ class DeclaratorDecl : public ValueDecl { llvm::PointerUnion<TypeSourceInfo *, ExtInfo *> DeclInfo; - /// InnerLocStart - The start of the source range for this declaration, + /// The start of the source range for this declaration, /// ignoring outer template declarations. SourceLocation InnerLocStart; @@ -717,13 +725,12 @@ public: DeclInfo = TI; } - /// getInnerLocStart - Return SourceLocation representing start of source - /// range ignoring outer template declarations. + /// Return start of source range ignoring outer template declarations. SourceLocation getInnerLocStart() const { return InnerLocStart; } void setInnerLocStart(SourceLocation L) { InnerLocStart = L; } - /// getOuterLocStart - Return SourceLocation representing start of source - /// range taking into account any outer template declarations. + /// Return start of source range taking into account any outer template + /// declarations. SourceLocation getOuterLocStart() const; SourceRange getSourceRange() const override LLVM_READONLY; @@ -732,14 +739,14 @@ public: return getOuterLocStart(); } - /// \brief Retrieve the nested-name-specifier that qualifies the name of this + /// Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() : nullptr; } - /// \brief Retrieve the nested-name-specifier (with source-location + /// Retrieve the nested-name-specifier (with source-location /// information) that qualifies the name of this declaration, if it was /// present in the source. NestedNameSpecifierLoc getQualifierLoc() const { @@ -770,25 +777,25 @@ public: } }; -/// \brief Structure used to store a statement, the constant value to +/// Structure used to store a statement, the constant value to /// which it was evaluated (if any), and whether or not the statement /// is an integral constant expression (if known). struct EvaluatedStmt { - /// \brief Whether this statement was already evaluated. + /// Whether this statement was already evaluated. bool WasEvaluated : 1; - /// \brief Whether this statement is being evaluated. + /// Whether this statement is being evaluated. bool IsEvaluating : 1; - /// \brief Whether we already checked whether this statement was an + /// Whether we already checked whether this statement was an /// integral constant expression. bool CheckedICE : 1; - /// \brief Whether we are checking whether this statement is an + /// Whether we are checking whether this statement is an /// integral constant expression. bool CheckingICE : 1; - /// \brief Whether this statement is an integral constant expression, + /// Whether this statement is an integral constant expression, /// or in C++11, whether the statement is a constant expression. Only /// valid if CheckedICE is true. bool IsICE : 1; @@ -801,11 +808,10 @@ struct EvaluatedStmt { }; -/// VarDecl - An instance of this class is created to represent a variable -/// declaration or definition. +/// Represents a variable declaration or definition. class VarDecl : public DeclaratorDecl, public Redeclarable<VarDecl> { public: - /// \brief Initialization styles. + /// Initialization styles. enum InitializationStyle { /// C-style initialization with assignment CInit, @@ -817,7 +823,7 @@ public: ListInit }; - /// \brief Kinds of thread-local storage. + /// Kinds of thread-local storage. enum TLSKind { /// Not a TLS variable. TLS_None, @@ -829,8 +835,7 @@ public: TLS_Dynamic }; - /// getStorageClassSpecifierString - Return the string used to - /// specify the storage class \p SC. + /// Return the string used to specify the storage class \p SC. /// /// It is illegal to call this function with SC == None. static const char *getStorageClassSpecifierString(StorageClass SC); @@ -845,7 +850,7 @@ protected: // allocated in trailing space when necessary. using InitType = llvm::PointerUnion<Stmt *, EvaluatedStmt *>; - /// \brief The initializer for this variable or, for a ParmVarDecl, the + /// The initializer for this variable or, for a ParmVarDecl, the /// C++ default argument. mutable InitType Init; @@ -915,41 +920,44 @@ protected: unsigned : NumVarDeclBits; // FIXME: We need something similar to CXXRecordDecl::DefinitionData. - /// \brief Whether this variable is a definition which was demoted due to + /// Whether this variable is a definition which was demoted due to /// module merge. unsigned IsThisDeclarationADemotedDefinition : 1; - /// \brief Whether this variable is the exception variable in a C++ catch + /// Whether this variable is the exception variable in a C++ catch /// or an Objective-C @catch statement. unsigned ExceptionVar : 1; - /// \brief Whether this local variable could be allocated in the return + /// Whether this local variable could be allocated in the return /// slot of its function, enabling the named return value optimization /// (NRVO). unsigned NRVOVariable : 1; - /// \brief Whether this variable is the for-range-declaration in a C++0x + /// Whether this variable is the for-range-declaration in a C++0x /// for-range statement. unsigned CXXForRangeDecl : 1; - /// \brief Whether this variable is an ARC pseudo-__strong + /// Whether this variable is the for-in loop declaration in Objective-C. + unsigned ObjCForDecl : 1; + + /// Whether this variable is an ARC pseudo-__strong /// variable; see isARCPseudoStrong() for details. unsigned ARCPseudoStrong : 1; - /// \brief Whether this variable is (C++1z) inline. + /// Whether this variable is (C++1z) inline. unsigned IsInline : 1; - /// \brief Whether this variable has (C++1z) inline explicitly specified. + /// Whether this variable has (C++1z) inline explicitly specified. unsigned IsInlineSpecified : 1; - /// \brief Whether this variable is (C++0x) constexpr. + /// Whether this variable is (C++0x) constexpr. unsigned IsConstexpr : 1; - /// \brief Whether this variable is the implicit variable for a lambda + /// Whether this variable is the implicit variable for a lambda /// init-capture. unsigned IsInitCapture : 1; - /// \brief Whether this local extern variable's previous declaration was + /// Whether this local extern variable's previous declaration was /// declared in the same block scope. This controls whether we should merge /// the type of this declaration with its previous declaration. unsigned PreviousDeclInSameBlockScope : 1; @@ -1004,7 +1012,7 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; - /// \brief Returns the storage class as written in the source. For the + /// Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return (StorageClass) VarDeclBits.SClass; @@ -1020,8 +1028,8 @@ public: } TLSKind getTLSKind() const; - /// hasLocalStorage - Returns true if a variable with function scope - /// is a non-static local variable. + /// Returns true if a variable with function scope is a non-static local + /// variable. bool hasLocalStorage() const { if (getStorageClass() == SC_None) { // OpenCL v1.2 s6.5.3: The __constant or constant address space name is @@ -1044,8 +1052,8 @@ public: return getStorageClass() >= SC_Auto; } - /// isStaticLocal - Returns true if a variable with function scope is a - /// static local variable. + /// Returns true if a variable with function scope is a static local + /// variable. bool isStaticLocal() const { return (getStorageClass() == SC_Static || // C++11 [dcl.stc]p4 @@ -1053,43 +1061,42 @@ public: && !isFileVarDecl(); } - /// \brief Returns true if a variable has extern or __private_extern__ + /// Returns true if a variable has extern or __private_extern__ /// storage. bool hasExternalStorage() const { return getStorageClass() == SC_Extern || getStorageClass() == SC_PrivateExtern; } - /// \brief Returns true for all variables that do not have local storage. + /// Returns true for all variables that do not have local storage. /// /// This includes all global variables as well as static variables declared /// within a function. bool hasGlobalStorage() const { return !hasLocalStorage(); } - /// \brief Get the storage duration of this variable, per C++ [basic.stc]. + /// Get the storage duration of this variable, per C++ [basic.stc]. StorageDuration getStorageDuration() const { return hasLocalStorage() ? SD_Automatic : getTSCSpec() ? SD_Thread : SD_Static; } - /// \brief Compute the language linkage. + /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; - /// \brief Determines whether this variable is a variable with - /// external, C linkage. + /// Determines whether this variable is a variable with external, C linkage. bool isExternC() const; - /// \brief Determines whether this variable's context is, or is nested within, + /// Determines whether this variable's context is, or is nested within, /// a C++ extern "C" linkage spec. bool isInExternCContext() const; - /// \brief Determines whether this variable's context is, or is nested within, + /// Determines whether this variable's context is, or is nested within, /// a C++ extern "C++" linkage spec. bool isInExternCXXContext() const; - /// isLocalVarDecl - Returns true for local variable declarations - /// other than parameters. Note that this includes static variables - /// inside of functions. It also includes variables inside blocks. + /// Returns true for local variable declarations other than parameters. + /// Note that this includes static variables inside of functions. It also + /// includes variables inside blocks. /// /// void foo() { int x; static int y; extern int z; } bool isLocalVarDecl() const { @@ -1100,13 +1107,12 @@ public: return false; } - /// \brief Similar to isLocalVarDecl but also includes parameters. + /// 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. + /// Similar to isLocalVarDecl, but excludes variables declared in blocks. bool isFunctionOrMethodVarDecl() const { if (getKind() != Decl::Var && getKind() != Decl::Decomposition) return false; @@ -1114,7 +1120,7 @@ public: return DC->isFunctionOrMethod() && DC->getDeclKind() != Decl::Block; } - /// \brief Determines whether this is a static data member. + /// Determines whether this is a static data member. /// /// This will only be true in C++, and applies to, e.g., the /// variable 'x' in: @@ -1144,7 +1150,7 @@ public: Definition }; - /// \brief Check whether this declaration is a definition. If this could be + /// Check whether this declaration is a definition. If this could be /// a tentative definition (in C), don't check whether there's an overriding /// definition. DefinitionKind isThisDeclarationADefinition(ASTContext &) const; @@ -1152,21 +1158,20 @@ public: return isThisDeclarationADefinition(getASTContext()); } - /// \brief Check whether this variable is defined in this - /// translation unit. + /// Check whether this variable is defined in this translation unit. DefinitionKind hasDefinition(ASTContext &) const; DefinitionKind hasDefinition() const { return hasDefinition(getASTContext()); } - /// \brief Get the tentative definition that acts as the real definition in - /// a TU. Returns null if there is a proper definition available. + /// Get the tentative definition that acts as the real definition in a TU. + /// Returns null if there is a proper definition available. VarDecl *getActingDefinition(); const VarDecl *getActingDefinition() const { return const_cast<VarDecl*>(this)->getActingDefinition(); } - /// \brief Get the real (not just tentative) definition for this declaration. + /// Get the real (not just tentative) definition for this declaration. VarDecl *getDefinition(ASTContext &); const VarDecl *getDefinition(ASTContext &C) const { return const_cast<VarDecl*>(this)->getDefinition(C); @@ -1178,11 +1183,11 @@ public: return const_cast<VarDecl*>(this)->getDefinition(); } - /// \brief Determine whether this is or was instantiated from an out-of-line + /// Determine whether this is or was instantiated from an out-of-line /// definition of a static data member. bool isOutOfLine() const override; - /// isFileVarDecl - Returns true for file scoped variable declaration. + /// Returns true for file scoped variable declaration. bool isFileVarDecl() const { Kind K = getKind(); if (K == ParmVar || K == ImplicitParam) @@ -1197,14 +1202,14 @@ public: return false; } - /// getAnyInitializer - Get the initializer for this variable, no matter which + /// Get the initializer for this variable, no matter which /// declaration it is attached to. const Expr *getAnyInitializer() const { const VarDecl *D; return getAnyInitializer(D); } - /// getAnyInitializer - Get the initializer for this variable, no matter which + /// Get the initializer for this variable, no matter which /// declaration it is attached to. Also get that declaration. const Expr *getAnyInitializer(const VarDecl *&D) const; @@ -1214,12 +1219,12 @@ public: } Expr *getInit(); - /// \brief Retrieve the address of the initializer expression. + /// Retrieve the address of the initializer expression. Stmt **getInitAddress(); void setInit(Expr *I); - /// \brief Determine whether this variable's value can be used in a + /// Determine whether this variable's value can be used in a /// constant expression, according to the relevant language standard. /// This only checks properties of the declaration, and does not check /// whether the initializer is in fact a constant expression. @@ -1227,30 +1232,30 @@ public: EvaluatedStmt *ensureEvaluatedStmt() const; - /// \brief Attempt to evaluate the value of the initializer attached to this + /// Attempt to evaluate the value of the initializer attached to this /// declaration, and produce notes explaining why it cannot be evaluated or is /// not a constant expression. Returns a pointer to the value if evaluation /// succeeded, 0 otherwise. APValue *evaluateValue() const; APValue *evaluateValue(SmallVectorImpl<PartialDiagnosticAt> &Notes) const; - /// \brief Return the already-evaluated value of this variable's + /// Return the already-evaluated value of this variable's /// initializer, or NULL if the value is not yet known. Returns pointer /// to untyped APValue if the value could not be evaluated. APValue *getEvaluatedValue() const; - /// \brief Determines whether it is already known whether the + /// Determines whether it is already known whether the /// initializer is an integral constant expression or not. bool isInitKnownICE() const; - /// \brief Determines whether the initializer is an integral constant + /// Determines whether the initializer is an integral constant /// expression, or in C++11, whether the initializer is a constant /// expression. /// /// \pre isInitKnownICE() bool isInitICE() const; - /// \brief Determine whether the value of the initializer attached to this + /// Determine whether the value of the initializer attached to this /// declaration is an integral constant expression. bool checkInitIsICE() const; @@ -1258,7 +1263,7 @@ public: VarDeclBits.InitStyle = Style; } - /// \brief The style of initialization for this declaration. + /// The style of initialization for this declaration. /// /// C-style initialization is "int x = 1;". Call-style initialization is /// a C++98 direct-initializer, e.g. "int x(1);". The Init expression will be @@ -1272,18 +1277,18 @@ public: return static_cast<InitializationStyle>(VarDeclBits.InitStyle); } - /// \brief Whether the initializer is a direct-initializer (list or call). + /// Whether the initializer is a direct-initializer (list or call). bool isDirectInit() const { return getInitStyle() != CInit; } - /// \brief If this definition should pretend to be a declaration. + /// If this definition should pretend to be a declaration. bool isThisDeclarationADemotedDefinition() const { return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.IsThisDeclarationADemotedDefinition; } - /// \brief This is a definition which should be demoted to a declaration. + /// This is a definition which should be demoted to a declaration. /// /// In some cases (mostly module merging) we can end up with two visible /// definitions one of which needs to be demoted to a declaration to keep @@ -1294,7 +1299,7 @@ public: NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = 1; } - /// \brief Determine whether this variable is the exception variable in a + /// Determine whether this variable is the exception variable in a /// C++ catch statememt or an Objective-C \@catch statement. bool isExceptionVariable() const { return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.ExceptionVar; @@ -1304,7 +1309,7 @@ public: NonParmVarDeclBits.ExceptionVar = EV; } - /// \brief Determine whether this local variable can be used with the named + /// Determine whether this local variable can be used with the named /// return value optimization (NRVO). /// /// The named return value optimization (NRVO) works by marking certain @@ -1322,7 +1327,7 @@ public: NonParmVarDeclBits.NRVOVariable = NRVO; } - /// \brief Determine whether this variable is the for-range-declaration in + /// Determine whether this variable is the for-range-declaration in /// a C++0x for-range statement. bool isCXXForRangeDecl() const { return isa<ParmVarDecl>(this) ? false : NonParmVarDeclBits.CXXForRangeDecl; @@ -1332,7 +1337,17 @@ public: NonParmVarDeclBits.CXXForRangeDecl = FRD; } - /// \brief Determine whether this variable is an ARC pseudo-__strong + /// Determine whether this variable is a for-loop declaration for a + /// for-in statement in Objective-C. + bool isObjCForDecl() const { + return NonParmVarDeclBits.ObjCForDecl; + } + + void setObjCForDecl(bool FRD) { + NonParmVarDeclBits.ObjCForDecl = FRD; + } + + /// Determine whether this variable is an ARC pseudo-__strong /// variable. A pseudo-__strong variable has a __strong-qualified /// type but does not actually retain the object written into it. /// Generally such variables are also 'const' for safety. @@ -1392,41 +1407,41 @@ public: NonParmVarDeclBits.PreviousDeclInSameBlockScope = Same; } - /// \brief Retrieve the variable declaration from which this variable could + /// Retrieve the variable declaration from which this variable could /// be instantiated, if it is an instantiation (rather than a non-template). VarDecl *getTemplateInstantiationPattern() const; - /// \brief If this variable is an instantiated static data member of a + /// If this variable is an instantiated static data member of a /// class template specialization, returns the templated static data member /// from which it was instantiated. VarDecl *getInstantiatedFromStaticDataMember() const; - /// \brief If this variable is an instantiation of a variable template or a + /// If this variable is an instantiation of a variable template or a /// static data member of a class template, determine what kind of /// template specialization or instantiation this is. TemplateSpecializationKind getTemplateSpecializationKind() const; - /// \brief If this variable is an instantiation of a variable template or a + /// If this variable is an instantiation of a variable template or a /// static data member of a class template, determine its point of /// instantiation. SourceLocation getPointOfInstantiation() const; - /// \brief If this variable is an instantiation of a static data member of a + /// If this variable is an instantiation of a static data member of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - /// \brief For a static data member that was instantiated from a static + /// For a static data member that was instantiated from a static /// data member of a class template, set the template specialiation kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); - /// \brief Specify that this variable is an instantiation of the + /// Specify that this variable is an instantiation of the /// static data member VD. void setInstantiationOfStaticDataMember(VarDecl *VD, TemplateSpecializationKind TSK); - /// \brief Retrieves the variable template that is described by this + /// Retrieves the variable template that is described by this /// variable declaration. /// /// Every variable template is represented as a VarTemplateDecl and a @@ -1441,6 +1456,11 @@ public: void setDescribedVarTemplate(VarTemplateDecl *Template); + // Is this variable known to have a definition somewhere in the complete + // program? This may be true even if the declaration has internal linkage and + // has no definition within this source file. + bool isKnownToBeDefined() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K >= firstVar && K <= lastVar; } @@ -1509,7 +1529,7 @@ public: static bool classofKind(Kind K) { return K == ImplicitParam; } }; -/// ParmVarDecl - Represents a parameter to a function. +/// Represents a parameter to a function. class ParmVarDecl : public VarDecl { public: enum { MaxFunctionScopeDepth = 255 }; @@ -1598,7 +1618,7 @@ public: void setDefaultArg(Expr *defarg); - /// \brief Retrieve the source range that covers the entire default + /// Retrieve the source range that covers the entire default /// argument. SourceRange getDefaultArgRange() const; void setUninstantiatedDefaultArg(Expr *arg); @@ -1607,14 +1627,13 @@ public: return const_cast<ParmVarDecl *>(this)->getUninstantiatedDefaultArg(); } - /// hasDefaultArg - Determines whether this parameter has a default argument, + /// Determines whether this parameter has a default argument, /// either parsed or not. bool hasDefaultArg() const; - /// hasUnparsedDefaultArg - Determines whether this parameter has a - /// default argument that has not yet been parsed. This will occur - /// during the processing of a C++ class whose member functions have - /// default arguments, e.g., + /// Determines whether this parameter has a default argument that has not + /// yet been parsed. This will occur during the processing of a C++ class + /// whose member functions have default arguments, e.g., /// @code /// class X { /// public: @@ -1629,11 +1648,10 @@ public: return ParmVarDeclBits.DefaultArgKind == DAK_Uninstantiated; } - /// setUnparsedDefaultArg - Specify that this parameter has an - /// unparsed default argument. The argument will be replaced with a - /// real default argument via setDefaultArg when the class - /// definition enclosing the function declaration that owns this - /// default argument is completed. + /// Specify that this parameter has an unparsed default argument. + /// The argument will be replaced with a real default argument via + /// setDefaultArg when the class definition enclosing the function + /// declaration that owns this default argument is completed. void setUnparsedDefaultArg() { ParmVarDeclBits.DefaultArgKind = DAK_Unparsed; } @@ -1648,11 +1666,11 @@ public: QualType getOriginalType() const; - /// \brief Determine whether this parameter is actually a function + /// Determine whether this parameter is actually a function /// parameter pack. bool isParameterPack() const; - /// setOwningFunction - Sets the function declaration that owns this + /// Sets the function declaration that owns this /// ParmVarDecl. Since ParmVarDecls are often created before the /// FunctionDecls that own them, this routine is required to update /// the DeclContext appropriately. @@ -1683,8 +1701,7 @@ private: unsigned getParameterIndexLarge() const; }; -/// An instance of this class is created to represent a function declaration or -/// definition. +/// Represents a function declaration or definition. /// /// Since a given function can be declared several times in a program, /// there may be several FunctionDecls that correspond to that @@ -1697,7 +1714,7 @@ private: class FunctionDecl : public DeclaratorDecl, public DeclContext, public Redeclarable<FunctionDecl> { public: - /// \brief The kind of templated function a FunctionDecl can be. + /// The kind of templated function a FunctionDecl can be. enum TemplatedKind { TK_NonTemplate, TK_FunctionTemplate, @@ -1707,7 +1724,7 @@ public: }; private: - /// ParamInfo - new[]'d array of pointers to VarDecls for the formal + /// A new[]'d array of pointers to VarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. ParmVarDecl **ParamInfo = nullptr; @@ -1732,6 +1749,12 @@ private: unsigned HasWrittenPrototype : 1; unsigned IsDeleted : 1; unsigned IsTrivial : 1; // sunk from CXXMethodDecl + + /// This flag indicates whether this function is trivial for the purpose of + /// calls. This is meaningful only when this function is a copy/move + /// constructor or a destructor. + unsigned IsTrivialForCall : 1; + unsigned IsDefaulted : 1; // sunk from CXXMethoDecl unsigned IsExplicitlyDefaulted : 1; //sunk from CXXMethodDecl unsigned HasImplicitReturnZero : 1; @@ -1739,10 +1762,10 @@ private: unsigned IsConstexpr : 1; unsigned InstantiationIsPending : 1; - /// \brief Indicates if the function uses __try. + /// Indicates if the function uses __try. unsigned UsesSEHTry : 1; - /// \brief Indicates if the function was a definition but its body was + /// Indicates if the function was a definition but its body was /// skipped. unsigned HasSkippedBody : 1; @@ -1750,6 +1773,10 @@ private: /// parsing it. unsigned WillHaveBody : 1; + /// Indicates that this function is a multiversioned function using attribute + /// 'target'. + unsigned IsMultiVersion : 1; + protected: /// [C++17] Only used by CXXDeductionGuideDecl. Declared here to avoid /// increasing the size of CXXDeductionGuideDecl by the size of an unsigned @@ -1764,7 +1791,7 @@ private: unsigned HasODRHash : 1; unsigned ODRHash; - /// \brief End part of this FunctionDecl's source range. + /// End part of this FunctionDecl's source range. /// /// We could compute the full range in getSourceRange(). However, when we're /// dealing with a function definition deserialized from a PCH/AST file, @@ -1773,7 +1800,7 @@ private: /// EndRangeLoc. SourceLocation EndRangeLoc; - /// \brief The template or declaration that this declaration + /// The template or declaration that this declaration /// describes or was instantiated from, respectively. /// /// For non-templates, this value will be NULL. For function @@ -1795,7 +1822,7 @@ private: /// the DeclaratorDecl base class. DeclarationNameLoc DNLoc; - /// \brief Specify that this function declaration is actually a function + /// Specify that this function declaration is actually a function /// template specialization. /// /// \param C the ASTContext. @@ -1824,7 +1851,7 @@ private: const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation PointOfInstantiation); - /// \brief Specify that this record is an instantiation of the + /// Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(ASTContext &C, FunctionDecl *FD, TemplateSpecializationKind TSK); @@ -1842,13 +1869,14 @@ protected: IsInline(isInlineSpecified), IsInlineSpecified(isInlineSpecified), IsExplicitSpecified(false), IsVirtualAsWritten(false), IsPure(false), HasInheritedPrototype(false), HasWrittenPrototype(true), - IsDeleted(false), IsTrivial(false), IsDefaulted(false), + IsDeleted(false), IsTrivial(false), IsTrivialForCall(false), + IsDefaulted(false), IsExplicitlyDefaulted(false), HasImplicitReturnZero(false), IsLateTemplateParsed(false), IsConstexpr(isConstexprSpecified), InstantiationIsPending(false), UsesSEHTry(false), HasSkippedBody(false), - WillHaveBody(false), IsCopyDeductionCandidate(false), HasODRHash(false), - ODRHash(0), EndRangeLoc(NameInfo.getEndLoc()), - DNLoc(NameInfo.getInfo()) {} + WillHaveBody(false), IsMultiVersion(false), + IsCopyDeductionCandidate(false), HasODRHash(false), ODRHash(0), + EndRangeLoc(NameInfo.getEndLoc()), DNLoc(NameInfo.getInfo()) {} using redeclarable_base = Redeclarable<FunctionDecl>; @@ -1915,11 +1943,25 @@ public: SourceRange getSourceRange() const override LLVM_READONLY; - /// \brief Returns true if the function has a body (definition). The - /// function body might be in any of the (re-)declarations of this - /// function. The variant that accepts a FunctionDecl pointer will - /// set that function declaration to the actual declaration - /// containing the body (if there is one). + // Function definitions. + // + // A function declaration may be: + // - a non defining declaration, + // - a definition. A function may be defined because: + // - it has a body, or will have it in the case of late parsing. + // - it has an uninstantiated body. The body does not exist because the + // function is not used yet, but the declaration is considered a + // definition and does not allow other definition of this function. + // - it does not have a user specified body, but it does not allow + // redefinition, because it is deleted/defaulted or is defined through + // some other mechanism (alias, ifunc). + + /// Returns true if the function has a body. + /// + /// The function body might be in any of the (re-)declarations of this + /// function. The variant that accepts a FunctionDecl pointer will set that + /// function declaration to the actual declaration containing the body (if + /// there is one). bool hasBody(const FunctionDecl *&Definition) const; bool hasBody() const override { @@ -1931,9 +1973,11 @@ public: /// specific codegen. bool hasTrivialBody() const; - /// Returns true if the function is defined at all, including a deleted - /// definition. Except for the behavior when the function is deleted, behaves - /// like hasBody. + /// Returns true if the function has a definition that does not need to be + /// instantiated. + /// + /// The variant that accepts a FunctionDecl pointer will set that function + /// declaration to the declaration that is a definition (if there is one). bool isDefined(const FunctionDecl *&Definition) const; virtual bool isDefined() const { @@ -1941,7 +1985,7 @@ public: return isDefined(Definition); } - /// \brief Get the definition for this declaration. + /// Get the definition for this declaration. FunctionDecl *getDefinition() { const FunctionDecl *Definition; if (isDefined(Definition)) @@ -1975,8 +2019,7 @@ public: IsLateTemplateParsed || WillHaveBody || hasDefiningAttr(); } - /// Returns whether this specific declaration of the function has a body - - /// that is, if it is a non-deleted definition. + /// Returns whether this specific declaration of the function has a body. bool doesThisDeclarationHaveABody() const { return Body || IsLateTemplateParsed; } @@ -2007,6 +2050,9 @@ public: bool isTrivial() const { return IsTrivial; } void setTrivial(bool IT) { IsTrivial = IT; } + bool isTrivialForCall() const { return IsTrivialForCall; } + void setTrivialForCall(bool IT) { IsTrivialForCall = IT; } + /// Whether this function is defaulted per C++0x. Only valid for /// special member functions. bool isDefaulted() const { return IsDefaulted; } @@ -2023,7 +2069,7 @@ public: bool hasImplicitReturnZero() const { return HasImplicitReturnZero; } void setHasImplicitReturnZero(bool IRZ) { HasImplicitReturnZero = IRZ; } - /// \brief Whether this function has a prototype, either because one + /// Whether this function has a prototype, either because one /// was explicitly written or because it was "inherited" by merging /// a declaration without a prototype with a declaration that has a /// prototype. @@ -2033,7 +2079,7 @@ public: bool hasWrittenPrototype() const { return HasWrittenPrototype; } - /// \brief Whether this function inherited its prototype from a + /// Whether this function inherited its prototype from a /// previous declaration. bool hasInheritedPrototype() const { return HasInheritedPrototype; } void setHasInheritedPrototype(bool P = true) { HasInheritedPrototype = P; } @@ -2042,7 +2088,7 @@ public: bool isConstexpr() const { return IsConstexpr; } void setConstexpr(bool IC) { IsConstexpr = IC; } - /// \brief Whether the instantiation of this function is pending. + /// Whether the instantiation of this function is pending. /// This bit is set when the decision to instantiate this function is made /// and unset if and when the function body is created. That leaves out /// cases where instantiation did not happen because the template definition @@ -2051,11 +2097,11 @@ public: bool instantiationIsPending() const { return InstantiationIsPending; } void setInstantiationIsPending(bool IC) { InstantiationIsPending = IC; } - /// \brief Indicates the function uses __try. + /// Indicates the function uses __try. bool usesSEHTry() const { return UsesSEHTry; } void setUsesSEHTry(bool UST) { UsesSEHTry = UST; } - /// \brief Whether this function has been deleted. + /// Whether this function has been deleted. /// /// A function that is "deleted" (via the C++0x "= delete" syntax) /// acts like a normal function, except that it cannot actually be @@ -2078,15 +2124,15 @@ public: bool isDeletedAsWritten() const { return IsDeleted && !IsDefaulted; } void setDeletedAsWritten(bool D = true) { IsDeleted = D; } - /// \brief Determines whether this function is "main", which is the + /// Determines whether this function is "main", which is the /// entry point into an executable program. bool isMain() const; - /// \brief Determines whether this function is a MSVCRT user defined entry + /// Determines whether this function is a MSVCRT user defined entry /// point. bool isMSVCRTEntryPoint() const; - /// \brief Determines whether this operator new or delete is one + /// Determines whether this operator new or delete is one /// of the reserved global placement operators: /// void *operator new(size_t, void *); /// void *operator new[](size_t, void *); @@ -2101,7 +2147,7 @@ public: /// This function must be an allocation or deallocation function. bool isReservedGlobalPlacementOperator() const; - /// \brief Determines whether this function is one of the replaceable + /// Determines whether this function is one of the replaceable /// global allocation functions: /// void *operator new(size_t); /// void *operator new(size_t, const std::nothrow_t &) noexcept; @@ -2121,32 +2167,32 @@ public: /// true through IsAligned. bool isReplaceableGlobalAllocationFunction(bool *IsAligned = nullptr) const; - /// \brief Determine whether this is a destroying operator delete. + /// Determine whether this is a destroying operator delete. bool isDestroyingOperatorDelete() const; /// Compute the language linkage. LanguageLinkage getLanguageLinkage() const; - /// \brief Determines whether this function is a function with + /// Determines whether this function is a function with /// external, C linkage. bool isExternC() const; - /// \brief Determines whether this function's context is, or is nested within, + /// Determines whether this function's context is, or is nested within, /// a C++ extern "C" linkage spec. bool isInExternCContext() const; - /// \brief Determines whether this function's context is, or is nested within, + /// Determines whether this function's context is, or is nested within, /// a C++ extern "C++" linkage spec. bool isInExternCXXContext() const; - /// \brief Determines whether this is a global function. + /// Determines whether this is a global function. bool isGlobal() const; - /// \brief Determines whether this function is known to be 'noreturn', through + /// Determines whether this function is known to be 'noreturn', through /// an attribute on its declaration or its type. bool isNoReturn() const; - /// \brief True if the function was a definition but its body was skipped. + /// True if the function was a definition but its body was skipped. bool hasSkippedBody() const { return HasSkippedBody; } void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; } @@ -2154,6 +2200,22 @@ public: bool willHaveBody() const { return WillHaveBody; } void setWillHaveBody(bool V = true) { WillHaveBody = V; } + /// True if this function is considered a multiversioned function. + bool isMultiVersion() const { return getCanonicalDecl()->IsMultiVersion; } + + /// Sets the multiversion state for this declaration and all of its + /// redeclarations. + void setIsMultiVersion(bool V = true) { + getCanonicalDecl()->IsMultiVersion = V; + } + + /// True if this function is a multiversioned dispatch function as a part of + /// the cpu_specific/cpu_dispatch functionality. + bool isCPUDispatchMultiVersion() const; + /// True if this function is a multiversioned processor specific function as a + /// part of the cpu_specific/cpu_dispatch functionality. + bool isCPUSpecificMultiVersion() const; + void setPreviousDeclaration(FunctionDecl * PrevDecl); FunctionDecl *getCanonicalDecl() override; @@ -2209,34 +2271,34 @@ public: return getType()->getAs<FunctionType>()->getReturnType(); } - /// \brief Attempt to compute an informative source range covering the + /// Attempt to compute an informative source range covering the /// function return type. This may omit qualifiers and other information with /// limited representation in the AST. SourceRange getReturnTypeSourceRange() const; - /// \brief Attempt to compute an informative source range covering the + /// Attempt to compute an informative source range covering the /// function exception specification, if any. SourceRange getExceptionSpecSourceRange() const; - /// \brief Determine the type of an expression that calls this function. + /// Determine the type of an expression that calls this function. QualType getCallResultType() const { assert(getType()->getAs<FunctionType>() && "Expected a FunctionType!"); return getType()->getAs<FunctionType>()->getCallResultType(getASTContext()); } - /// \brief Returns the WarnUnusedResultAttr that is either declared on this + /// Returns the WarnUnusedResultAttr that is either declared on this /// function, or its return type declaration. const Attr *getUnusedResultAttr() const; - /// \brief Returns true if this function or its return type has the + /// Returns true if this function or its return type has the /// warn_unused_result attribute. bool hasUnusedResultAttr() const { return getUnusedResultAttr() != nullptr; } - /// \brief Returns the storage class as written in the source. For the + /// Returns the storage class as written in the source. For the /// computed linkage of symbol, see getLinkage. StorageClass getStorageClass() const { return StorageClass(SClass); } - /// \brief Determine whether the "inline" keyword was specified for this + /// Determine whether the "inline" keyword was specified for this /// function. bool isInlineSpecified() const { return IsInlineSpecified; } @@ -2251,7 +2313,7 @@ public: IsInline = true; } - /// \brief Determine whether this function should be inlined, because it is + /// Determine whether this function should be inlined, because it is /// either marked "inline" or "constexpr" or is a member function of a class /// that was defined in the class body. bool isInlined() const { return IsInline; } @@ -2262,8 +2324,8 @@ public: bool doesDeclarationForceExternallyVisibleDefinition() const; - /// isOverloadedOperator - Whether this function declaration - /// represents an C++ overloaded operator, e.g., "operator+". + /// Whether this function declaration represents an C++ overloaded + /// operator, e.g., "operator+". bool isOverloadedOperator() const { return getOverloadedOperator() != OO_None; } @@ -2272,7 +2334,7 @@ public: const IdentifierInfo *getLiteralIdentifier() const; - /// \brief If this function is an instantiation of a member function + /// If this function is an instantiation of a member function /// of a class template specialization, retrieves the function from /// which it was instantiated. /// @@ -2295,22 +2357,22 @@ public: /// declaration returned by getInstantiatedFromMemberFunction(). FunctionDecl *getInstantiatedFromMemberFunction() const; - /// \brief What kind of templated function this is. + /// What kind of templated function this is. TemplatedKind getTemplatedKind() const; - /// \brief If this function is an instantiation of a member function of a + /// If this function is an instantiation of a member function of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - /// \brief Specify that this record is an instantiation of the + /// Specify that this record is an instantiation of the /// member function FD. void setInstantiationOfMemberFunction(FunctionDecl *FD, TemplateSpecializationKind TSK) { setInstantiationOfMemberFunction(getASTContext(), FD, TSK); } - /// \brief Retrieves the function template that is described by this + /// Retrieves the function template that is described by this /// function declaration. /// /// Every function template is represented as a FunctionTemplateDecl @@ -2326,50 +2388,50 @@ public: void setDescribedFunctionTemplate(FunctionTemplateDecl *Template); - /// \brief Determine whether this function is a function template + /// Determine whether this function is a function template /// specialization. bool isFunctionTemplateSpecialization() const { return getPrimaryTemplate() != nullptr; } - /// \brief Retrieve the class scope template pattern that this function + /// Retrieve the class scope template pattern that this function /// template specialization is instantiated from. FunctionDecl *getClassScopeSpecializationPattern() const; - /// \brief If this function is actually a function template specialization, + /// If this function is actually a function template specialization, /// retrieve information about this function template specialization. /// Otherwise, returns NULL. FunctionTemplateSpecializationInfo *getTemplateSpecializationInfo() const; - /// \brief Determines whether this function is a function template + /// Determines whether this function is a function template /// specialization or a member of a class template specialization that can /// be implicitly instantiated. bool isImplicitlyInstantiable() const; - /// \brief Determines if the given function was instantiated from a + /// Determines if the given function was instantiated from a /// function template. bool isTemplateInstantiation() const; - /// \brief Retrieve the function declaration from which this function could + /// Retrieve the function declaration from which this function could /// be instantiated, if it is an instantiation (rather than a non-template /// or a specialization, for example). FunctionDecl *getTemplateInstantiationPattern() const; - /// \brief Retrieve the primary template that this function template + /// Retrieve the primary template that this function template /// specialization either specializes or was instantiated from. /// /// If this function declaration is not a function template specialization, /// returns NULL. FunctionTemplateDecl *getPrimaryTemplate() const; - /// \brief Retrieve the template arguments used to produce this function + /// Retrieve the template arguments used to produce this function /// template specialization from the primary template. /// /// If this function declaration is not a function template specialization, /// returns NULL. const TemplateArgumentList *getTemplateSpecializationArgs() const; - /// \brief Retrieve the template argument list as written in the sources, + /// Retrieve the template argument list as written in the sources, /// if any. /// /// If this function declaration is not a function template specialization @@ -2379,7 +2441,7 @@ public: const ASTTemplateArgumentListInfo* getTemplateSpecializationArgsAsWritten() const; - /// \brief Specify that this function declaration is actually a function + /// Specify that this function declaration is actually a function /// template specialization. /// /// \param Template the function template that this function template @@ -2409,7 +2471,7 @@ public: PointOfInstantiation); } - /// \brief Specifies that this function declaration is actually a + /// Specifies that this function declaration is actually a /// dependent function template specialization. void setDependentTemplateSpecialization(ASTContext &Context, const UnresolvedSetImpl &Templates, @@ -2418,16 +2480,16 @@ public: DependentFunctionTemplateSpecializationInfo * getDependentSpecializationInfo() const; - /// \brief Determine what kind of template instantiation this function + /// Determine what kind of template instantiation this function /// represents. TemplateSpecializationKind getTemplateSpecializationKind() const; - /// \brief Determine what kind of template instantiation this function + /// Determine what kind of template instantiation this function /// represents. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); - /// \brief Retrieve the (first) point of instantiation of a function template + /// Retrieve the (first) point of instantiation of a function template /// specialization or a member of a class template specialization. /// /// \returns the first point of instantiation, if this function was @@ -2435,20 +2497,24 @@ public: /// location. SourceLocation getPointOfInstantiation() const; - /// \brief Determine whether this is or was instantiated from an out-of-line + /// Determine whether this is or was instantiated from an out-of-line /// definition of a member function. bool isOutOfLine() const override; - /// \brief Identify a memory copying or setting function. + /// Identify a memory copying or setting function. /// If the given function is a memory copy or setting function, returns /// the corresponding Builtin ID. If the function is not a memory function, /// returns 0. unsigned getMemoryFunctionKind() const; - /// \brief Returns ODRHash of the function. This value is calculated and + /// Returns ODRHash of the function. This value is calculated and /// stored on first call, then the stored value returned on the other calls. unsigned getODRHash(); + /// Returns cached ODRHash of the function. This must have been previously + /// computed and stored. + unsigned getODRHash() const; + // Implement isa/cast/dyncast/etc. static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { @@ -2462,8 +2528,7 @@ public: } }; -/// FieldDecl - An instance of this class is created by Sema::ActOnField to -/// represent a member of a struct/union/class. +/// Represents a member of a struct/union/class. class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { unsigned BitField : 1; unsigned Mutable : 1; @@ -2499,7 +2564,7 @@ class FieldDecl : public DeclaratorDecl, public Mergeable<FieldDecl> { Expr *BitWidth; }; - /// \brief Storage for either the bit-width, the in-class initializer, or + /// Storage for either the bit-width, the in-class initializer, or /// both (via InitAndBitWidth), or the captured variable length array bound. /// /// If the storage kind is ISK_InClassCopyInit or @@ -2534,20 +2599,20 @@ public: static FieldDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// getFieldIndex - Returns the index of this field within its record, + /// Returns the index of this field within its record, /// as appropriate for passing to ASTRecordLayout::getFieldOffset. unsigned getFieldIndex() const; - /// isMutable - Determines whether this field is mutable (C++ only). + /// Determines whether this field is mutable (C++ only). bool isMutable() const { return Mutable; } - /// \brief Determines whether this field is a bitfield. + /// Determines whether this field is a bitfield. bool isBitField() const { return BitField; } - /// @brief Determines whether this is an unnamed bitfield. + /// Determines whether this is an unnamed bitfield. bool isUnnamedBitfield() const { return isBitField() && !getDeclName(); } - /// isAnonymousStructOrUnion - Determines whether this field is a + /// Determines whether this field is a /// representative for an anonymous struct or union. Such fields are /// unnamed and are implicitly generated by the implementation to /// store the data for the anonymous union or struct. @@ -2564,7 +2629,7 @@ public: unsigned getBitWidthValue(const ASTContext &Ctx) const; - /// setBitWidth - Set the bit-field width for this member. + /// Set the bit-field width for this member. // Note: used by some clients (i.e., do not remove it). void setBitWidth(Expr *Width) { assert(!hasCapturedVLAType() && !BitField && @@ -2578,7 +2643,7 @@ public: BitField = true; } - /// removeBitWidth - Remove the bit-field width from this member. + /// 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"); @@ -2586,6 +2651,11 @@ public: BitField = false; } + /// Is this a zero-length bit-field? Such bit-fields aren't really bit-fields + /// at all and instead act as a separator between contiguous runs of other + /// bit-fields. + bool isZeroLengthBitField(const ASTContext &Ctx) const; + /// Get the kind of (C++11) default member initializer that this field has. InClassInitStyle getInClassInitStyle() const { InitStorageKind storageKind = InitStorage.getInt(); @@ -2610,8 +2680,7 @@ public: return static_cast<Expr*>(Ptr); } - /// setInClassInitializer - Set the C++11 in-class initializer for this - /// member. + /// Set the C++11 in-class initializer for this member. void setInClassInitializer(Expr *Init) { assert(hasInClassInitializer() && !getInClassInitializer()); if (BitField) @@ -2620,30 +2689,29 @@ public: InitStorage.setPointer(Init); } - /// removeInClassInitializer - Remove the C++11 in-class initializer from this - /// member. + /// Remove the C++11 in-class initializer from this member. void removeInClassInitializer() { assert(hasInClassInitializer() && "no initializer to remove"); InitStorage.setPointerAndInt(getBitWidth(), ISK_NoInit); } - /// \brief Determine whether this member captures the variable length array + /// 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. + /// 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. + /// Set the captured variable length array type for this field. void setCapturedVLAType(const VariableArrayType *VLAType); - /// getParent - Returns the parent of this field declaration, which + /// Returns the parent of this field declaration, which /// is the struct in which this field is defined. const RecordDecl *getParent() const { return cast<RecordDecl>(getDeclContext()); @@ -2664,7 +2732,7 @@ public: static bool classofKind(Kind K) { return K >= firstField && K <= lastField; } }; -/// EnumConstantDecl - An instance of this object exists for each enum constant +/// An instance of this object exists for each enum constant /// that is defined. For example, in "enum X {a,b}", each of a/b are /// EnumConstantDecl's, X is an instance of EnumDecl, and the type of a/b is a /// TagType for the X EnumDecl. @@ -2705,9 +2773,8 @@ public: static bool classofKind(Kind K) { return K == EnumConstant; } }; -/// IndirectFieldDecl - An instance of this class is created to represent a -/// field injected from an anonymous union/struct into the parent scope. -/// IndirectFieldDecl are always implicit. +/// Represents a field injected from an anonymous union/struct into the parent +/// scope. These are always implicit. class IndirectFieldDecl : public ValueDecl, public Mergeable<IndirectFieldDecl> { NamedDecl **Chaining; @@ -2756,17 +2823,17 @@ public: static bool classofKind(Kind K) { return K == IndirectField; } }; -/// TypeDecl - Represents a declaration of a type. +/// Represents a declaration of a type. class TypeDecl : public NamedDecl { friend class ASTContext; - /// TypeForDecl - This indicates the Type object that represents + /// This indicates the Type object that represents /// this TypeDecl. It is a cache maintained by /// ASTContext::getTypedefType, ASTContext::getTagDeclType, and /// ASTContext::getTemplateTypeParmType, and TemplateTypeParmDecl. mutable const Type *TypeForDecl = nullptr; - /// LocStart - The start of the source range for this declaration. + /// The start of the source range for this declaration. SourceLocation LocStart; void anchor() override; @@ -2800,13 +2867,16 @@ public: /// Base class for declarations which introduce a typedef-name. class TypedefNameDecl : public TypeDecl, public Redeclarable<TypedefNameDecl> { - using ModedTInfo = std::pair<TypeSourceInfo *, QualType>; - llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *> MaybeModedTInfo; + struct alignas(8) ModedTInfo { + TypeSourceInfo *first; + QualType second; + }; - // FIXME: This can be packed into the bitfields in Decl. - /// If 0, we have not computed IsTransparentTag. - /// Otherwise, IsTransparentTag is (CacheIsTransparentTag >> 1). - mutable unsigned CacheIsTransparentTag : 2; + /// If int part is 0, we have not computed IsTransparentTag. + /// Otherwise, IsTransparentTag is (getInt() >> 1). + mutable llvm::PointerIntPair< + llvm::PointerUnion<TypeSourceInfo *, ModedTInfo *>, 2> + MaybeModedTInfo; void anchor() override; @@ -2815,7 +2885,7 @@ protected: SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, TypeSourceInfo *TInfo) : TypeDecl(DK, DC, IdLoc, Id, StartLoc), redeclarable_base(C), - MaybeModedTInfo(TInfo), CacheIsTransparentTag(0) {} + MaybeModedTInfo(TInfo, 0) {} using redeclarable_base = Redeclarable<TypedefNameDecl>; @@ -2842,26 +2912,29 @@ public: using redeclarable_base::getMostRecentDecl; using redeclarable_base::isFirstDecl; - bool isModed() const { return MaybeModedTInfo.is<ModedTInfo*>(); } + bool isModed() const { + return MaybeModedTInfo.getPointer().is<ModedTInfo *>(); + } TypeSourceInfo *getTypeSourceInfo() const { - return isModed() - ? MaybeModedTInfo.get<ModedTInfo*>()->first - : MaybeModedTInfo.get<TypeSourceInfo*>(); + return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->first + : MaybeModedTInfo.getPointer().get<TypeSourceInfo *>(); } QualType getUnderlyingType() const { - return isModed() - ? MaybeModedTInfo.get<ModedTInfo*>()->second - : MaybeModedTInfo.get<TypeSourceInfo*>()->getType(); + return isModed() ? MaybeModedTInfo.getPointer().get<ModedTInfo *>()->second + : MaybeModedTInfo.getPointer() + .get<TypeSourceInfo *>() + ->getType(); } void setTypeSourceInfo(TypeSourceInfo *newType) { - MaybeModedTInfo = newType; + MaybeModedTInfo.setPointer(newType); } void setModedTypeSourceInfo(TypeSourceInfo *unmodedTSI, QualType modedTy) { - MaybeModedTInfo = new (getASTContext()) ModedTInfo(unmodedTSI, modedTy); + MaybeModedTInfo.setPointer(new (getASTContext(), 8) + ModedTInfo({unmodedTSI, modedTy})); } /// Retrieves the canonical declaration of this typedef-name. @@ -2878,8 +2951,8 @@ public: /// Determines if this typedef shares a name and spelling location with its /// underlying tag type, as is the case with the NS_ENUM macro. bool isTransparentTag() const { - if (CacheIsTransparentTag) - return CacheIsTransparentTag & 0x2; + if (MaybeModedTInfo.getInt()) + return MaybeModedTInfo.getInt() & 0x2; return isTransparentTagSlow(); } @@ -2893,7 +2966,7 @@ private: bool isTransparentTagSlow() const; }; -/// TypedefDecl - Represents the declaration of a typedef-name via the 'typedef' +/// Represents the declaration of a typedef-name via the 'typedef' /// type specifier. class TypedefDecl : public TypedefNameDecl { TypedefDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, @@ -2913,7 +2986,7 @@ public: static bool classofKind(Kind K) { return K == Typedef; } }; -/// TypeAliasDecl - Represents the declaration of a typedef-name via a C++0x +/// Represents the declaration of a typedef-name via a C++11 /// alias-declaration. class TypeAliasDecl : public TypedefNameDecl { /// The template for which this is the pattern, if any. @@ -2940,7 +3013,7 @@ public: static bool classofKind(Kind K) { return K == TypeAlias; } }; -/// TagDecl - Represents the declaration of a struct/union/class/enum. +/// Represents the declaration of a struct/union/class/enum. class TagDecl : public TypeDecl, public DeclContext, public Redeclarable<TagDecl> { public: @@ -2949,25 +3022,24 @@ public: private: // FIXME: This can be packed into the bitfields in Decl. - /// TagDeclKind - The TagKind enum. + /// The TagKind enum. unsigned TagDeclKind : 3; - /// IsCompleteDefinition - True if this is a definition ("struct foo - /// {};"), false if it is a declaration ("struct foo;"). It is not - /// a definition until the definition has been fully processed. + /// True if this is a definition ("struct foo {};"), false if it is a + /// declaration ("struct foo;"). It is not considered a definition + /// until the definition has been fully processed. unsigned IsCompleteDefinition : 1; protected: - /// IsBeingDefined - True if this is currently being defined. + /// True if this is currently being defined. unsigned IsBeingDefined : 1; private: - /// IsEmbeddedInDeclarator - True if this tag declaration is - /// "embedded" (i.e., defined or declared for the very first time) - /// in the syntax of a declarator. + /// True if this tag declaration is "embedded" (i.e., defined or declared + /// for the very first time) in the syntax of a declarator. unsigned IsEmbeddedInDeclarator : 1; - /// \brief True if this tag is free standing, e.g. "struct foo;". + /// True if this tag is free standing, e.g. "struct foo;". unsigned IsFreeStanding : 1; protected: @@ -2975,21 +3047,21 @@ protected: unsigned NumPositiveBits : 8; unsigned NumNegativeBits : 8; - /// IsScoped - True if this tag declaration is a scoped enumeration. Only + /// True if this tag declaration is a scoped enumeration. Only /// possible in C++11 mode. unsigned IsScoped : 1; - /// IsScopedUsingClassTag - If this tag declaration is a scoped enum, + /// If this tag declaration is a scoped enum, /// then this is true if the scoped enum was declared using the class /// tag, false if it was declared with the struct tag. No meaning is /// associated if this tag declaration is not a scoped enum. unsigned IsScopedUsingClassTag : 1; - /// IsFixed - True if this is an enumeration with fixed underlying type. Only + /// True if this is an enumeration with fixed underlying type. Only /// possible in C++11, Microsoft extensions, or Objective C mode. unsigned IsFixed : 1; - /// \brief Indicates whether it is possible for declarations of this kind + /// Indicates whether it is possible for declarations of this kind /// to have an out-of-date definition. /// /// This option is only enabled when modules are enabled. @@ -3006,7 +3078,7 @@ private: // to be used for the (uncommon) case of out-of-line declarations. using ExtInfo = QualifierInfo; - /// \brief If the (out-of-line) tag declaration name + /// If the (out-of-line) tag declaration name /// is qualified, it points to the qualifier info (nns and range); /// otherwise, if the tag declaration is anonymous and it is part of /// a typedef or alias, it points to the TypedefNameDecl (used for mangling); @@ -3050,7 +3122,7 @@ protected: return getMostRecentDecl(); } - /// @brief Completes the definition of this tag declaration. + /// Completes the definition of this tag declaration. /// /// This is a helper function for derived classes. void completeDefinition(); @@ -3072,11 +3144,11 @@ public: SourceRange getBraceRange() const { return BraceRange; } void setBraceRange(SourceRange R) { BraceRange = R; } - /// getInnerLocStart - Return SourceLocation representing start of source + /// Return SourceLocation representing start of source /// range ignoring outer template declarations. SourceLocation getInnerLocStart() const { return getLocStart(); } - /// getOuterLocStart - Return SourceLocation representing start of source + /// Return SourceLocation representing start of source /// range taking into account any outer template declarations. SourceLocation getOuterLocStart() const; SourceRange getSourceRange() const override LLVM_READONLY; @@ -3086,25 +3158,24 @@ public: return const_cast<TagDecl*>(this)->getCanonicalDecl(); } - /// isThisDeclarationADefinition() - Return true if this declaration - /// is a completion definition of the type. Provided for consistency. + /// Return true if this declaration is a completion definition of the type. + /// Provided for consistency. bool isThisDeclarationADefinition() const { return isCompleteDefinition(); } - /// isCompleteDefinition - Return true if this decl has its body - /// fully specified. + /// Return true if this decl has its body fully specified. bool isCompleteDefinition() const { return IsCompleteDefinition; } - /// \brief Return true if this complete decl is + /// Return true if this complete decl is /// required to be complete for some existing use. bool isCompleteDefinitionRequired() const { return IsCompleteDefinitionRequired; } - /// isBeingDefined - Return true if this decl is currently being defined. + /// Return true if this decl is currently being defined. bool isBeingDefined() const { return IsBeingDefined; } @@ -3121,19 +3192,19 @@ public: IsFreeStanding = isFreeStanding; } - /// \brief Whether this declaration declares a type that is + /// Whether this declaration declares a type that is /// dependent, i.e., a type that somehow depends on template /// parameters. bool isDependentType() const { return isDependentContext(); } - /// @brief Starts the definition of this tag declaration. + /// Starts the definition of this tag declaration. /// /// This method should be invoked at the beginning of the definition /// of this tag declaration. It will set the tag type into a state /// where it is in the process of being defined. void startDefinition(); - /// getDefinition - Returns the TagDecl that actually defines this + /// Returns the TagDecl that actually defines this /// struct/union/class/enum. When determining whether or not a /// struct/union/class/enum has a definition, one should use this /// method as opposed to 'isDefinition'. 'isDefinition' indicates @@ -3191,14 +3262,14 @@ public: void setTypedefNameForAnonDecl(TypedefNameDecl *TDD); - /// \brief Retrieve the nested-name-specifier that qualifies the name of this + /// Retrieve the nested-name-specifier that qualifies the name of this /// declaration, if it was present in the source. NestedNameSpecifier *getQualifier() const { return hasExtInfo() ? getExtInfo()->QualifierLoc.getNestedNameSpecifier() : nullptr; } - /// \brief Retrieve the nested-name-specifier (with source-location + /// Retrieve the nested-name-specifier (with source-location /// information) that qualifies the name of this declaration, if it was /// present in the source. NestedNameSpecifierLoc getQualifierLoc() const { @@ -3233,11 +3304,11 @@ public: } }; -/// EnumDecl - Represents an enum. In C++11, enums can be forward-declared +/// Represents an enum. In C++11, enums can be forward-declared /// with a fixed underlying type, and in C we allow them to be forward-declared /// with no underlying type as an extension. class EnumDecl : public TagDecl { - /// IntegerType - This represent the integer type that the enum corresponds + /// This represent the integer type that the enum corresponds /// to for code generation purposes. Note that the enumerator constants may /// have a different type than this does. /// @@ -3253,17 +3324,21 @@ class EnumDecl : public TagDecl { /// extra pointer when TypeSourceInfo is needed. llvm::PointerUnion<const Type *, TypeSourceInfo *> IntegerType; - /// PromotionType - The integer type that values of this type should + /// The integer type that values of this type should /// promote to. In C, enumerators are generally of an integer type /// directly, but gcc-style large enumerators (and all enumerators /// in C++) are of the enum type instead. QualType PromotionType; - /// \brief If this enumeration is an instantiation of a member enumeration + /// If this enumeration is an instantiation of a member enumeration /// of a class template specialization, this is the member specialization /// information. MemberSpecializationInfo *SpecializationInfo = nullptr; + /// Store the ODRHash after first calculation. + unsigned HasODRHash : 1; + unsigned ODRHash; + EnumDecl(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, EnumDecl *PrevDecl, bool Scoped, bool ScopedUsingClassTag, bool Fixed) @@ -3275,6 +3350,8 @@ class EnumDecl : public TagDecl { IsScoped = Scoped; IsScopedUsingClassTag = ScopedUsingClassTag; IsFixed = Fixed; + HasODRHash = false; + ODRHash = 0; } void anchor() override; @@ -3317,9 +3394,9 @@ public: bool IsFixed); static EnumDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// completeDefinition - When created, the EnumDecl corresponds to a + /// When created, the EnumDecl corresponds to a /// forward-declared enum. This method is used to mark the - /// declaration as being defined; it's enumerators have already been + /// declaration as being defined; its enumerators have already been /// added (via DeclContext::addDecl). NewType is the new underlying /// type of the enumeration type. void completeDefinition(QualType NewType, @@ -3327,8 +3404,7 @@ public: unsigned NumPositiveBits, unsigned NumNegativeBits); - // enumerator_iterator - Iterates through the enumerators of this - // enumeration. + // Iterates through the enumerators of this enumeration. using enumerator_iterator = specific_decl_iterator<EnumConstantDecl>; using enumerator_range = llvm::iterator_range<specific_decl_iterator<EnumConstantDecl>>; @@ -3351,14 +3427,13 @@ public: return enumerator_iterator(E->decls_end()); } - /// getPromotionType - Return the integer type that enumerators - /// should promote to. + /// Return the integer type that enumerators should promote to. QualType getPromotionType() const { return PromotionType; } - /// \brief Set the promotion type. + /// Set the promotion type. void setPromotionType(QualType T) { PromotionType = T; } - /// getIntegerType - Return the integer type this enum decl corresponds to. + /// Return the integer type this enum decl corresponds to. /// This returns a null QualType for an enum forward definition with no fixed /// underlying type. QualType getIntegerType() const { @@ -3369,23 +3444,23 @@ public: return IntegerType.get<TypeSourceInfo*>()->getType().getUnqualifiedType(); } - /// \brief Set the underlying integer type. + /// Set the underlying integer type. void setIntegerType(QualType T) { IntegerType = T.getTypePtrOrNull(); } - /// \brief Set the underlying integer type source info. + /// Set the underlying integer type source info. void setIntegerTypeSourceInfo(TypeSourceInfo *TInfo) { IntegerType = TInfo; } - /// \brief Return the type source info for the underlying integer type, + /// Return the type source info for the underlying integer type, /// if no type source info exists, return 0. TypeSourceInfo *getIntegerTypeSourceInfo() const { return IntegerType.dyn_cast<TypeSourceInfo*>(); } - /// \brief Retrieve the source range that covers the underlying type if + /// Retrieve the source range that covers the underlying type if /// specified. SourceRange getIntegerTypeRange() const LLVM_READONLY; - /// \brief Returns the width in bits required to store all the + /// Returns the width in bits required to store all the /// non-negative enumerators of this enum. unsigned getNumPositiveBits() const { return NumPositiveBits; @@ -3395,7 +3470,7 @@ public: assert(NumPositiveBits == Num && "can't store this bitcount"); } - /// \brief Returns the width in bits required to store all the + /// Returns the width in bits required to store all the /// negative enumerators of this enum. These widths include /// the rightmost leading 1; that is: /// @@ -3411,25 +3486,29 @@ public: NumNegativeBits = Num; } - /// \brief Returns true if this is a C++11 scoped enumeration. + /// Returns true if this is a C++11 scoped enumeration. bool isScoped() const { return IsScoped; } - /// \brief Returns true if this is a C++11 scoped enumeration. + /// Returns true if this is a C++11 scoped enumeration. bool isScopedUsingClassTag() const { return IsScopedUsingClassTag; } - /// \brief Returns true if this is an Objective-C, C++11, or + /// Returns true if this is an Objective-C, C++11, or /// Microsoft-style enumeration with a fixed underlying type. bool isFixed() const { return IsFixed; } - /// \brief Returns true if this can be considered a complete type. + unsigned getODRHash(); + + /// Returns true if this can be considered a complete type. bool isComplete() const { - return isCompleteDefinition() || isFixed(); + // IntegerType is set for fixed type enums and non-fixed but implicitly + // int-sized Microsoft enums. + return isCompleteDefinition() || IntegerType; } /// Returns true if this enum is either annotated with @@ -3444,33 +3523,33 @@ public: /// enum_extensibility(open). bool isClosedNonFlag() const; - /// \brief Retrieve the enum definition from which this enumeration could + /// Retrieve the enum definition from which this enumeration could /// be instantiated, if it is an instantiation (rather than a non-template). EnumDecl *getTemplateInstantiationPattern() const; - /// \brief Returns the enumeration (declared within the template) + /// Returns the enumeration (declared within the template) /// from which this enumeration type was instantiated, or NULL if /// this enumeration was not instantiated from any template. EnumDecl *getInstantiatedFromMemberEnum() const; - /// \brief If this enumeration is a member of a specialization of a + /// If this enumeration is a member of a specialization of a /// templated class, determine what kind of template specialization /// or instantiation this is. TemplateSpecializationKind getTemplateSpecializationKind() const; - /// \brief For an enumeration member that was instantiated from a member + /// For an enumeration member that was instantiated from a member /// enumeration of a templated class, set the template specialiation kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK, SourceLocation PointOfInstantiation = SourceLocation()); - /// \brief If this enumeration is an instantiation of a member enumeration of + /// If this enumeration is an instantiation of a member enumeration of /// a class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const { return SpecializationInfo; } - /// \brief Specify that this enumeration is an instantiation of the + /// Specify that this enumeration is an instantiation of the /// member enumeration ED. void setInstantiationOfMemberEnum(EnumDecl *ED, TemplateSpecializationKind TSK) { @@ -3481,36 +3560,74 @@ public: static bool classofKind(Kind K) { return K == Enum; } }; -/// RecordDecl - Represents a struct/union/class. For example: +/// Represents a struct/union/class. For example: /// struct X; // Forward declaration, no "body". /// union Y { int A, B; }; // Has body with members A and B (FieldDecls). /// This decl will be marked invalid if *any* members are invalid. class RecordDecl : public TagDecl { +public: + /// Enum that represents the different ways arguments are passed to and + /// returned from function calls. This takes into account the target-specific + /// and version-specific rules along with the rules determined by the + /// language. + enum ArgPassingKind : unsigned { + /// The argument of this type can be passed directly in registers. + APK_CanPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are not forced to be passed + /// indirectly. This value is used only in C++. This value is required by + /// C++ because, in uncommon situations, it is possible for a class to have + /// only trivial copy/move constructors even when one of its subobjects has + /// a non-trivial copy/move constructor (if e.g. the corresponding copy/move + /// constructor in the derived class is deleted). + APK_CannotPassInRegs, + + /// The argument of this type cannot be passed directly in registers. + /// Records containing this type as a subobject are forced to be passed + /// indirectly. + APK_CanNeverPassInRegs + }; + +private: friend class DeclContext; // FIXME: This can be packed into the bitfields in Decl. - /// HasFlexibleArrayMember - This is true if this struct ends with a flexible + /// This is true if this struct ends with a flexible /// array member (e.g. int X[]) or if this union contains a struct that does. /// If so, this cannot be contained in arrays or other structs as a member. - bool HasFlexibleArrayMember : 1; + unsigned HasFlexibleArrayMember : 1; - /// AnonymousStructOrUnion - Whether this is the type of an anonymous struct - /// or union. - bool AnonymousStructOrUnion : 1; + /// Whether this is the type of an anonymous struct or union. + unsigned AnonymousStructOrUnion : 1; - /// HasObjectMember - This is true if this struct has at least one member + /// This is true if this struct has at least one member /// containing an Objective-C object pointer type. - bool HasObjectMember : 1; - - /// HasVolatileMember - This is true if struct has at least one member of + unsigned HasObjectMember : 1; + + /// This is true if struct has at least one member of /// 'volatile' type. - bool HasVolatileMember : 1; + unsigned HasVolatileMember : 1; - /// \brief Whether the field declarations of this record have been loaded + /// Whether the field declarations of this record have been loaded /// from external storage. To avoid unnecessary deserialization of /// methods/nested types we allow deserialization of just the fields /// when needed. - mutable bool LoadedFieldsFromExternalStorage : 1; + mutable unsigned LoadedFieldsFromExternalStorage : 1; + + /// Basic properties of non-trivial C structs. + unsigned NonTrivialToPrimitiveDefaultInitialize : 1; + unsigned NonTrivialToPrimitiveCopy : 1; + unsigned NonTrivialToPrimitiveDestroy : 1; + + /// Indicates whether this struct is destroyed in the callee. + /// + /// Please note that MSVC won't merge adjacent bitfields if they don't have + /// the same type. + unsigned ParamDestroyedInCallee : 1; + + /// Represents the way this type is passed to a function. + unsigned ArgPassingRestrictions : 2; protected: RecordDecl(Kind DK, TagKind TK, const ASTContext &C, DeclContext *DC, @@ -3541,10 +3658,9 @@ public: bool hasFlexibleArrayMember() const { return HasFlexibleArrayMember; } void setHasFlexibleArrayMember(bool V) { HasFlexibleArrayMember = V; } - /// isAnonymousStructOrUnion - Whether this is an anonymous struct - /// or union. To be an anonymous struct or union, it must have been - /// declared without a name and there must be no objects of this - /// type declared, e.g., + /// Whether this is an anonymous struct or union. To be an anonymous + /// struct or union, it must have been declared without a name and + /// there must be no objects of this type declared, e.g., /// @code /// union { int i; float f; }; /// @endcode @@ -3571,7 +3687,55 @@ public: LoadedFieldsFromExternalStorage = val; } - /// \brief Determines whether this declaration represents the + /// Functions to query basic properties of non-trivial C structs. + bool isNonTrivialToPrimitiveDefaultInitialize() const { + return NonTrivialToPrimitiveDefaultInitialize; + } + + void setNonTrivialToPrimitiveDefaultInitialize(bool V) { + NonTrivialToPrimitiveDefaultInitialize = V; + } + + bool isNonTrivialToPrimitiveCopy() const { + return NonTrivialToPrimitiveCopy; + } + + void setNonTrivialToPrimitiveCopy(bool V) { + NonTrivialToPrimitiveCopy = V; + } + + bool isNonTrivialToPrimitiveDestroy() const { + return NonTrivialToPrimitiveDestroy; + } + + void setNonTrivialToPrimitiveDestroy(bool V) { + NonTrivialToPrimitiveDestroy = V; + } + + /// Determine whether this class can be passed in registers. In C++ mode, + /// it must have at least one trivial, non-deleted copy or move constructor. + /// FIXME: This should be set as part of completeDefinition. + bool canPassInRegisters() const { + return getArgPassingRestrictions() == APK_CanPassInRegs; + } + + ArgPassingKind getArgPassingRestrictions() const { + return static_cast<ArgPassingKind>(ArgPassingRestrictions); + } + + void setArgPassingRestrictions(ArgPassingKind Kind) { + ArgPassingRestrictions = static_cast<uint8_t>(Kind); + } + + bool isParamDestroyedInCallee() const { + return ParamDestroyedInCallee; + } + + void setParamDestroyedInCallee(bool V) { + ParamDestroyedInCallee = V; + } + + /// Determines whether this declaration represents the /// injected class name. /// /// The injected class name in C++ is the name of the class that @@ -3586,19 +3750,19 @@ public: /// \endcode bool isInjectedClassName() const; - /// \brief Determine whether this record is a class describing a lambda + /// 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 + /// 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 + /// Mark the record as a record for captured variables in CapturedStmt /// construct. void setCapturedRecord(); - /// getDefinition - Returns the RecordDecl that actually defines + /// 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 /// method as opposed to 'isCompleteDefinition'. @@ -3623,14 +3787,12 @@ public: return field_iterator(decl_iterator()); } - // field_empty - Whether there are any fields (non-static data - // members) in this record. + // Whether there are any fields (non-static data members) in this record. bool field_empty() const { return field_begin() == field_end(); } - /// completeDefinition - Notes that the definition of this type is - /// now complete. + /// Note that the definition of this type is now complete. virtual void completeDefinition(); static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -3638,12 +3800,12 @@ public: return K >= firstRecord && K <= lastRecord; } - /// \brief Get whether or not this is an ms_struct which can + /// Get whether or not this is an ms_struct which can /// be turned on with an attribute, pragma, or -mms-bitfields /// commandline option. bool isMsStruct(const ASTContext &C) const; - /// \brief Whether we are allowed to insert extra padding between fields. + /// 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; @@ -3653,7 +3815,7 @@ public: const FieldDecl *findFirstNamedDataMember() const; private: - /// \brief Deserialize just the fields. + /// Deserialize just the fields. void LoadFieldsFromExternalStorage() const; }; @@ -3689,7 +3851,7 @@ public: static bool classofKind(Kind K) { return K == FileScopeAsm; } }; -/// BlockDecl - This represents a block literal declaration, which is like an +/// Pepresents a block literal declaration, which is like an /// unnamed FunctionDecl. For example: /// ^{ statement-body } or ^(int arg1, float arg2){ statement-body } class BlockDecl : public Decl, public DeclContext { @@ -3739,7 +3901,11 @@ private: bool BlockMissingReturnType : 1; bool IsConversionFromLambda : 1; - /// ParamInfo - new[]'d array of pointers to ParmVarDecls for the formal + /// A bit that indicates this block is passed directly to a function as a + /// non-escaping parameter. + bool DoesNotEscape : 1; + + /// A new[]'d array of pointers to ParmVarDecls for the formal /// parameters of this function. This is null if a prototype or if there are /// no formals. ParmVarDecl **ParamInfo = nullptr; @@ -3758,7 +3924,7 @@ protected: BlockDecl(DeclContext *DC, SourceLocation CaretLoc) : Decl(Block, DC, CaretLoc), DeclContext(Block), IsVariadic(false), CapturesCXXThis(false), BlockMissingReturnType(true), - IsConversionFromLambda(false) {} + IsConversionFromLambda(false), DoesNotEscape(false) {} public: static BlockDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L); @@ -3808,11 +3974,11 @@ public: void setParams(ArrayRef<ParmVarDecl *> NewParamInfo); - /// hasCaptures - True if this block (or its nested blocks) captures + /// True if this block (or its nested blocks) captures /// anything of local storage from its enclosing scopes. bool hasCaptures() const { return NumCaptures != 0 || CapturesCXXThis; } - /// getNumCaptures - Returns the number of captured variables. + /// Returns the number of captured variables. /// Does not include an entry for 'this'. unsigned getNumCaptures() const { return NumCaptures; } @@ -3830,6 +3996,9 @@ public: bool isConversionFromLambda() const { return IsConversionFromLambda; } void setIsConversionFromLambda(bool val) { IsConversionFromLambda = val; } + bool doesNotEscape() const { return DoesNotEscape; } + void setDoesNotEscape() { DoesNotEscape = true; } + bool capturesVariable(const VarDecl *var) const; void setCaptures(ASTContext &Context, ArrayRef<Capture> Captures, @@ -3861,8 +4030,7 @@ public: } }; -/// \brief This represents the body of a CapturedStmt, and serves as its -/// DeclContext. +/// Represents the body of a CapturedStmt, and serves as its DeclContext. class CapturedDecl final : public Decl, public DeclContext, @@ -3873,13 +4041,13 @@ protected: } private: - /// \brief The number of parameters to the outlined function. + /// The number of parameters to the outlined function. unsigned NumParams; - /// \brief The position of context parameter in list of parameters. + /// The position of context parameter in list of parameters. unsigned ContextParam; - /// \brief The body of the outlined function. + /// The body of the outlined function. llvm::PointerIntPair<Stmt *, 1, bool> BodyAndNothrow; explicit CapturedDecl(DeclContext *DC, unsigned NumParams); @@ -3927,7 +4095,7 @@ public: return {getParams(), getNumParams()}; } - /// \brief Retrieve the parameter containing captured variables. + /// Retrieve the parameter containing captured variables. ImplicitParamDecl *getContextParam() const { assert(ContextParam < NumParams); return getParam(ContextParam); @@ -3942,9 +4110,9 @@ public: using param_iterator = ImplicitParamDecl *const *; using param_range = llvm::iterator_range<param_iterator>; - /// \brief Retrieve an iterator pointing to the first parameter decl. + /// Retrieve an iterator pointing to the first parameter decl. param_iterator param_begin() const { return getParams(); } - /// \brief Retrieve an iterator one past the last parameter decl. + /// Retrieve an iterator one past the last parameter decl. param_iterator param_end() const { return getParams() + NumParams; } // Implement isa/cast/dyncast/etc. @@ -3958,7 +4126,7 @@ public: } }; -/// \brief Describes a module import declaration, which makes the contents +/// Describes a module import declaration, which makes the contents /// of the named module visible in the current translation unit. /// /// An import declaration imports the named module (or submodule). For example: @@ -3975,7 +4143,7 @@ class ImportDecl final : public Decl, friend class ASTReader; friend TrailingObjects; - /// \brief The imported module, along with a bit that indicates whether + /// The imported module, along with a bit that indicates whether /// we have source-location information for each identifier in the module /// name. /// @@ -3983,7 +4151,7 @@ class ImportDecl final : public Decl, /// end of the import declaration. llvm::PointerIntPair<Module *, 1, bool> ImportedAndComplete; - /// \brief The next import in the list of imports local to the translation + /// The next import in the list of imports local to the translation /// unit being parsed (not loaded from an AST file). ImportDecl *NextLocalImport = nullptr; @@ -3996,25 +4164,25 @@ class ImportDecl final : public Decl, ImportDecl(EmptyShell Empty) : Decl(Import, Empty) {} public: - /// \brief Create a new module import declaration. + /// Create a new module import declaration. static ImportDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, ArrayRef<SourceLocation> IdentifierLocs); - /// \brief Create a new module import declaration for an implicitly-generated + /// Create a new module import declaration for an implicitly-generated /// import. static ImportDecl *CreateImplicit(ASTContext &C, DeclContext *DC, SourceLocation StartLoc, Module *Imported, SourceLocation EndLoc); - /// \brief Create a new, deserialized module import declaration. + /// Create a new, deserialized module import declaration. static ImportDecl *CreateDeserialized(ASTContext &C, unsigned ID, unsigned NumLocations); - /// \brief Retrieve the module that was imported by the import declaration. + /// Retrieve the module that was imported by the import declaration. Module *getImportedModule() const { return ImportedAndComplete.getPointer(); } - /// \brief Retrieves the locations of each of the identifiers that make up + /// Retrieves the locations of each of the identifiers that make up /// the complete module name in the import declaration. /// /// This will return an empty array if the locations of the individual @@ -4027,7 +4195,7 @@ public: static bool classofKind(Kind K) { return K == Import; } }; -/// \brief Represents a C++ Modules TS module export declaration. +/// Represents a C++ Modules TS module export declaration. /// /// For example: /// \code @@ -4039,7 +4207,7 @@ class ExportDecl final : public Decl, public DeclContext { private: friend class ASTDeclReader; - /// \brief The source location for the right brace (if valid). + /// The source location for the right brace (if valid). SourceLocation RBraceLoc; ExportDecl(DeclContext *DC, SourceLocation ExportLoc) @@ -4077,7 +4245,7 @@ public: } }; -/// \brief Represents an empty-declaration. +/// Represents an empty-declaration. class EmptyDecl : public Decl { EmptyDecl(DeclContext *DC, SourceLocation L) : Decl(Empty, DC, L) {} @@ -4111,7 +4279,7 @@ template<typename decl_type> void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { // Note: This routine is implemented here because we need both NamedDecl // and Redeclarable to be defined. - assert(RedeclLink.NextIsLatest() && + assert(RedeclLink.isFirst() && "setPreviousDecl on a decl already in a redeclaration chain"); if (PrevDecl) { @@ -4119,7 +4287,7 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { // redeclaration, or we can build invalid chains. If the most recent // redeclaration is invalid, it won't be PrevDecl, but we want it anyway. First = PrevDecl->getFirstDecl(); - assert(First->RedeclLink.NextIsLatest() && "Expected first"); + assert(First->RedeclLink.isFirst() && "Expected first"); decl_type *MostRecent = First->getNextRedeclaration(); RedeclLink = PreviousDeclLink(cast<decl_type>(MostRecent)); @@ -4142,7 +4310,7 @@ void Redeclarable<decl_type>::setPreviousDecl(decl_type *PrevDecl) { // Inline function definitions. -/// \brief Check if the given decl is complete. +/// Check if the given decl is complete. /// /// We use this function to break a cycle between the inline definitions in /// Type.h and Decl.h. @@ -4150,7 +4318,7 @@ inline bool IsEnumDeclComplete(EnumDecl *ED) { return ED->isComplete(); } -/// \brief Check if the given decl is scoped. +/// Check if the given decl is scoped. /// /// We use this function to break a cycle between the inline definitions in /// Type.h and Decl.h. diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index f93c9f0b9aaa1..f99bd627877c5 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -19,7 +19,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/PointerUnion.h" @@ -28,6 +27,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/VersionTuple.h" #include <algorithm> #include <cassert> #include <cstddef> @@ -67,7 +67,7 @@ class TemplateDecl; class TranslationUnitDecl; class UsingDirectiveDecl; -/// \brief Captures the result of checking the availability of a +/// Captures the result of checking the availability of a /// declaration. enum AvailabilityResult { AR_Available = 0, @@ -83,9 +83,9 @@ enum AvailabilityResult { /// (and its subclasses) in its Decl::operator new(). Proper alignment /// of all subclasses (not requiring more than the alignment of Decl) is /// asserted in DeclBase.cpp. -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) Decl { +class alignas(8) Decl { public: - /// \brief Lists the kind of concrete classes of Decl. + /// Lists the kind of concrete classes of Decl. enum Kind { #define DECL(DERIVED, BASE) DERIVED, #define ABSTRACT_DECL(DECL) @@ -96,7 +96,7 @@ public: #include "clang/AST/DeclNodes.inc" }; - /// \brief A placeholder type used to construct an empty shell of a + /// A placeholder type used to construct an empty shell of a /// decl-derived type that will be filled in later (e.g., by some /// deserialization method). struct EmptyShell {}; @@ -231,7 +231,7 @@ public: }; protected: - /// \brief The next declaration within the same lexical + /// The next declaration within the same lexical /// DeclContext. These pointers form the linked list that is /// traversed via DeclContext's decls_begin()/decls_end(). /// @@ -288,27 +288,28 @@ private: /// the implementation rather than explicitly written by the user. unsigned Implicit : 1; - /// \brief Whether this declaration was "used", meaning that a definition is + /// Whether this declaration was "used", meaning that a definition is /// required. unsigned Used : 1; - /// \brief Whether this declaration was "referenced". + /// Whether this declaration was "referenced". /// The difference with 'Used' is whether the reference appears in a /// evaluated context or not, e.g. functions used in uninstantiated templates /// are regarded as "referenced" but not "used". unsigned Referenced : 1; - /// \brief Whether this declaration is a top-level declaration (function, + /// Whether this declaration is a top-level declaration (function, /// global variable, etc.) that is lexically inside an objc container /// definition. unsigned TopLevelDeclInObjCContainer : 1; - /// \brief Whether statistic collection is enabled. + /// Whether statistic collection is enabled. static bool StatisticsEnabled; protected: friend class ASTDeclReader; friend class ASTDeclWriter; + friend class ASTNodeImporter; friend class ASTReader; friend class CXXClassMemberWrapper; friend class LinkageComputer; @@ -318,17 +319,17 @@ protected: // NOTE: VC++ treats enums as signed, avoid using the AccessSpecifier enum unsigned Access : 2; - /// \brief Whether this declaration was loaded from an AST file. + /// Whether this declaration was loaded from an AST file. unsigned FromASTFile : 1; /// IdentifierNamespace - This specifies what IDNS_* namespace this lives in. unsigned IdentifierNamespace : 13; - /// \brief If 0, we have not computed the linkage of this declaration. + /// If 0, we have not computed the linkage of this declaration. /// Otherwise, it is the linkage + 1. mutable unsigned CacheValidAndLinkage : 3; - /// \brief Allocate memory for a deserialized declaration. + /// Allocate memory for a deserialized declaration. /// /// This routine must be used to allocate memory for any declaration that is /// deserialized from a module file. @@ -340,7 +341,7 @@ protected: void *operator new(std::size_t Size, const ASTContext &Ctx, unsigned ID, std::size_t Extra = 0); - /// \brief Allocate memory for a non-deserialized declaration. + /// Allocate memory for a non-deserialized declaration. void *operator new(std::size_t Size, const ASTContext &Ctx, DeclContext *Parent, std::size_t Extra = 0); @@ -384,7 +385,7 @@ protected: virtual ~Decl(); - /// \brief Update a potentially out-of-date declaration. + /// Update a potentially out-of-date declaration. void updateOutOfDate(IdentifierInfo &II) const; Linkage getCachedLinkage() const { @@ -400,7 +401,7 @@ protected: } public: - /// \brief Source range that this declaration covers. + /// Source range that this declaration covers. virtual SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getLocation(), getLocation()); } @@ -462,7 +463,7 @@ public: return AccessSpecifier(Access); } - /// \brief Retrieve the access specifier for this declaration, even though + /// Retrieve the access specifier for this declaration, even though /// it may not yet have been properly set. AccessSpecifier getAccessUnsafe() const { return AccessSpecifier(Access); @@ -551,7 +552,7 @@ public: bool isImplicit() const { return Implicit; } void setImplicit(bool I = true) { Implicit = I; } - /// \brief Whether *any* (re-)declaration of the entity was used, meaning that + /// Whether *any* (re-)declaration of the entity was used, meaning that /// a definition is required. /// /// \param CheckUsedAttr When true, also consider the "used" attribute @@ -559,28 +560,28 @@ public: /// whether the function is used. bool isUsed(bool CheckUsedAttr = true) const; - /// \brief Set whether the declaration is used, in the sense of odr-use. + /// Set whether the declaration is used, in the sense of odr-use. /// /// This should only be used immediately after creating a declaration. /// It intentionally doesn't notify any listeners. void setIsUsed() { getCanonicalDecl()->Used = true; } - /// \brief Mark the declaration used, in the sense of odr-use. + /// Mark the declaration used, in the sense of odr-use. /// /// This notifies any mutation listeners in addition to setting a bit /// indicating the declaration is used. void markUsed(ASTContext &C); - /// \brief Whether any declaration of this entity was referenced. + /// Whether any declaration of this entity was referenced. bool isReferenced() const; - /// \brief Whether this declaration was referenced. This should not be relied + /// 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, + /// Whether this declaration is a top-level declaration (function, /// global variable, etc.) that is lexically inside an objc container /// definition. bool isTopLevelDeclInObjCContainer() const { @@ -591,17 +592,17 @@ public: TopLevelDeclInObjCContainer = V; } - /// \brief Looks on this and related declarations for an applicable + /// Looks on this and related declarations for an applicable /// external source symbol attribute. ExternalSourceSymbolAttr *getExternalSourceSymbolAttr() const; - /// \brief Whether this declaration was marked as being private to the + /// Whether this declaration was marked as being private to the /// module in which it was defined. bool isModulePrivate() const { return getModuleOwnershipKind() == ModuleOwnershipKind::ModulePrivate; } - /// \brief Whether this declaration is exported (by virtue of being lexically + /// Whether this declaration is exported (by virtue of being lexically /// within an ExportDecl or by being a NamespaceDecl). bool isExported() const; @@ -613,7 +614,7 @@ public: const Attr *getDefiningAttr() const; protected: - /// \brief Specify that this declaration was marked as being private + /// Specify that this declaration was marked as being private /// to the module in which it was defined. void setModulePrivate() { // The module-private specifier has no effect on unowned declarations. @@ -623,14 +624,14 @@ protected: setModuleOwnershipKind(ModuleOwnershipKind::ModulePrivate); } - /// \brief Set the owning module ID. + /// Set the owning module ID. void setOwningModuleID(unsigned ID) { assert(isFromASTFile() && "Only works on a deserialized declaration"); *((unsigned*)this - 2) = ID; } public: - /// \brief Determine the availability of the given declaration. + /// Determine the availability of the given declaration. /// /// This routine will determine the most restrictive availability of /// the given declaration (e.g., preferring 'unavailable' to @@ -643,11 +644,16 @@ public: /// /// \param EnclosingVersion The version to compare with. If empty, assume the /// deployment target version. + /// + /// \param RealizedPlatform If non-NULL and the availability result is found + /// in an available attribute it will set to the platform which is written in + /// the available attribute. AvailabilityResult getAvailability(std::string *Message = nullptr, - VersionTuple EnclosingVersion = VersionTuple()) const; + VersionTuple EnclosingVersion = VersionTuple(), + StringRef *RealizedPlatform = nullptr) const; - /// \brief Retrieve the version of the target platform in which this + /// Retrieve the version of the target platform in which this /// declaration was introduced. /// /// \returns An empty version tuple if this declaration has no 'introduced' @@ -655,7 +661,7 @@ public: /// attribute otherwise. VersionTuple getVersionIntroduced() const; - /// \brief Determine whether this declaration is marked 'deprecated'. + /// Determine whether this declaration is marked 'deprecated'. /// /// \param Message If non-NULL and the declaration is deprecated, /// this will be set to the message describing why the declaration @@ -664,7 +670,7 @@ public: return getAvailability(Message) == AR_Deprecated; } - /// \brief Determine whether this declaration is marked 'unavailable'. + /// Determine whether this declaration is marked 'unavailable'. /// /// \param Message If non-NULL and the declaration is unavailable, /// this will be set to the message describing why the declaration @@ -673,7 +679,7 @@ public: return getAvailability(Message) == AR_Unavailable; } - /// \brief Determine whether this is a weak-imported symbol. + /// Determine whether this is a weak-imported symbol. /// /// Weak-imported symbols are typically marked with the /// 'weak_import' attribute, but may also be marked with an @@ -681,7 +687,7 @@ public: /// the introduction of this feature. bool isWeakImported() const; - /// \brief Determines whether this symbol can be weak-imported, + /// Determines whether this symbol can be weak-imported, /// e.g., whether it would be well-formed to add the weak_import /// attribute. /// @@ -689,11 +695,11 @@ public: /// declaration cannot be weak-imported because it has a definition. bool canBeWeakImported(bool &IsDefinition) const; - /// \brief Determine whether this declaration came from an AST file (such as + /// Determine whether this declaration came from an AST file (such as /// a precompiled header or module) rather than having been parsed. bool isFromASTFile() const { return FromASTFile; } - /// \brief Retrieve the global declaration ID associated with this + /// Retrieve the global declaration ID associated with this /// declaration, which specifies where this Decl was loaded from. unsigned getGlobalID() const { if (isFromASTFile()) @@ -701,7 +707,7 @@ public: return 0; } - /// \brief Retrieve the global ID of the module that owns this particular + /// Retrieve the global ID of the module that owns this particular /// declaration. unsigned getOwningModuleID() const { if (isFromASTFile()) @@ -716,7 +722,7 @@ protected: bool hasLocalOwningModuleStorage() const; public: - /// \brief Get the imported owning module, if this decl is from an imported + /// Get the imported owning module, if this decl is from an imported /// (non-local) module. Module *getImportedOwningModule() const { if (!isFromASTFile() || !hasOwningModule()) @@ -725,7 +731,7 @@ public: return getOwningModuleSlow(); } - /// \brief Get the local owning module, if known. Returns nullptr if owner is + /// Get the local owning module, if known. Returns nullptr if owner is /// not yet known or declaration is not from a module. Module *getLocalOwningModule() const { if (isFromASTFile() || !hasOwningModule()) @@ -759,7 +765,7 @@ public: /// all declarations in a global module fragment are unowned. Module *getOwningModuleForLinkage(bool IgnoreLinkage = false) const; - /// \brief Determine whether this declaration might be hidden from name + /// Determine whether this declaration might be hidden from name /// lookup. Note that the declaration might be visible even if this returns /// \c false, if the owning module is visible within the query context. // FIXME: Rename this to make it clearer what it does. @@ -774,12 +780,12 @@ public: setModuleOwnershipKind(ModuleOwnershipKind::Visible); } - /// \brief Get the kind of module ownership for this declaration. + /// Get the kind of module ownership for this declaration. ModuleOwnershipKind getModuleOwnershipKind() const { return NextInContextAndBits.getInt(); } - /// \brief Set whether this declaration is hidden from name lookup. + /// Set whether this declaration is hidden from name lookup. void setModuleOwnershipKind(ModuleOwnershipKind MOK) { assert(!(getModuleOwnershipKind() == ModuleOwnershipKind::Unowned && MOK != ModuleOwnershipKind::Unowned && !isFromASTFile() && @@ -836,6 +842,10 @@ public: void setLexicalDeclContext(DeclContext *DC); + /// Determine whether this declaration is a templated entity (whether it is + // within the scope of a template parameter). + bool isTemplated() const; + /// isDefinedOutsideFunctionOrMethod - This predicate returns true if this /// scoped decl is defined outside the current function or method. This is /// roughly global variables and functions, but also handles enums (which @@ -844,7 +854,7 @@ public: return getParentFunctionOrMethod() == nullptr; } - /// \brief Returns true if this declaration lexically is inside a function. + /// Returns true if this declaration lexically is inside a function. /// It recognizes non-defining declarations as well as members of local /// classes: /// \code @@ -853,7 +863,7 @@ public: /// \endcode bool isLexicallyWithinFunctionOrMethod() const; - /// \brief If this decl is defined inside a function/method/block it returns + /// If this decl is defined inside a function/method/block it returns /// the corresponding DeclContext, otherwise it returns null. const DeclContext *getParentFunctionOrMethod() const; DeclContext *getParentFunctionOrMethod() { @@ -861,32 +871,32 @@ public: const_cast<const Decl*>(this)->getParentFunctionOrMethod()); } - /// \brief Retrieves the "canonical" declaration of the given declaration. + /// Retrieves the "canonical" declaration of the given declaration. virtual Decl *getCanonicalDecl() { return this; } const Decl *getCanonicalDecl() const { return const_cast<Decl*>(this)->getCanonicalDecl(); } - /// \brief Whether this particular Decl is a canonical one. + /// Whether this particular Decl is a canonical one. bool isCanonicalDecl() const { return getCanonicalDecl() == this; } protected: - /// \brief Returns the next redeclaration or itself if this is the only decl. + /// Returns the next redeclaration or itself if this is the only decl. /// /// Decl subclasses that can be redeclared should override this method so that /// Decl::redecl_iterator can iterate over them. virtual Decl *getNextRedeclarationImpl() { return this; } - /// \brief Implementation of getPreviousDecl(), to be overridden by any + /// Implementation of getPreviousDecl(), to be overridden by any /// subclass that has a redeclaration chain. virtual Decl *getPreviousDeclImpl() { return nullptr; } - /// \brief Implementation of getMostRecentDecl(), to be overridden by any + /// Implementation of getMostRecentDecl(), to be overridden by any /// subclass that has a redeclaration chain. virtual Decl *getMostRecentDeclImpl() { return this; } public: - /// \brief Iterates through all the redeclarations of the same decl. + /// Iterates through all the redeclarations of the same decl. class redecl_iterator { /// Current - The current declaration. Decl *Current = nullptr; @@ -931,7 +941,7 @@ public: using redecl_range = llvm::iterator_range<redecl_iterator>; - /// \brief Returns an iterator range for all the redeclarations of the same + /// Returns an iterator range for all the redeclarations of the same /// decl. It will iterate at least once (when this decl is the only one). redecl_range redecls() const { return redecl_range(redecls_begin(), redecls_end()); @@ -943,26 +953,26 @@ public: redecl_iterator redecls_end() const { return redecl_iterator(); } - /// \brief Retrieve the previous declaration that declares the same entity + /// Retrieve the previous declaration that declares the same entity /// as this declaration, or NULL if there is no previous declaration. Decl *getPreviousDecl() { return getPreviousDeclImpl(); } - /// \brief Retrieve the most recent declaration that declares the same entity + /// Retrieve the most recent declaration that declares the same entity /// as this declaration, or NULL if there is no previous declaration. const Decl *getPreviousDecl() const { return const_cast<Decl *>(this)->getPreviousDeclImpl(); } - /// \brief True if this is the first declaration in its redeclaration chain. + /// True if this is the first declaration in its redeclaration chain. bool isFirstDecl() const { return getPreviousDecl() == nullptr; } - /// \brief Retrieve the most recent declaration that declares the same entity + /// Retrieve the most recent declaration that declares the same entity /// as this declaration (which may be this declaration). Decl *getMostRecentDecl() { return getMostRecentDeclImpl(); } - /// \brief Retrieve the most recent declaration that declares the same entity + /// Retrieve the most recent declaration that declares the same entity /// as this declaration (which may be this declaration). const Decl *getMostRecentDecl() const { return const_cast<Decl *>(this)->getMostRecentDeclImpl(); @@ -973,7 +983,7 @@ public: /// top-level Stmt* of that body. Otherwise this method returns null. virtual Stmt* getBody() const { return nullptr; } - /// \brief Returns true if this \c Decl represents a declaration for a body of + /// Returns true if this \c Decl represents a declaration for a body of /// code, such as a function or method definition. /// Note that \c hasBody can also return true if any redeclaration of this /// \c Decl represents a declaration for a body of code. @@ -996,24 +1006,24 @@ public: /// template parameter pack. bool isTemplateParameterPack() const; - /// \brief Whether this declaration is a parameter pack. + /// Whether this declaration is a parameter pack. bool isParameterPack() const; - /// \brief returns true if this declaration is a template + /// returns true if this declaration is a template bool isTemplateDecl() const; - /// \brief Whether this declaration is a function or function template. + /// Whether this declaration is a function or function template. bool isFunctionOrFunctionTemplate() const { return (DeclKind >= Decl::firstFunction && DeclKind <= Decl::lastFunction) || DeclKind == FunctionTemplate; } - /// \brief If this is a declaration that describes some template, this + /// If this is a declaration that describes some template, this /// method returns that template declaration. TemplateDecl *getDescribedTemplate() const; - /// \brief Returns the function itself, or the templated function if this is a + /// Returns the function itself, or the templated function if this is a /// function template. FunctionDecl *getAsFunction() LLVM_READONLY; @@ -1021,7 +1031,7 @@ public: return const_cast<Decl *>(this)->getAsFunction(); } - /// \brief Changes the namespace of this declaration to reflect that it's + /// Changes the namespace of this declaration to reflect that it's /// a function-local extern declaration. /// /// These declarations appear in the lexical context of the extern @@ -1042,14 +1052,14 @@ public: IdentifierNamespace |= IDNS_Ordinary; } - /// \brief Determine whether this is a block-scope declaration with linkage. + /// Determine whether this is a block-scope declaration with linkage. /// This will either be a local variable declaration declared 'extern', or a /// local function declaration. bool isLocalExternDecl() { return IdentifierNamespace & IDNS_LocalExtern; } - /// \brief Changes the namespace of this declaration to reflect that it's + /// Changes the namespace of this declaration to reflect that it's /// the object of a friend declaration. /// /// These declarations appear in the lexical context of the friending @@ -1091,7 +1101,7 @@ public: FOK_Undeclared ///< A friend of a previously-undeclared entity. }; - /// \brief Determines whether this declaration is the object of a + /// Determines whether this declaration is the object of a /// friend declaration and, if so, what kind. /// /// There is currently no direct way to find the associated FriendDecl. @@ -1131,7 +1141,7 @@ public: void dump(raw_ostream &Out, bool Deserialize = false) const; - /// \brief Looks through the Decl's underlying type to extract a FunctionType + /// Looks through the Decl's underlying type to extract a FunctionType /// when possible. Will return null if the type underlying the Decl does not /// have a FunctionType. const FunctionType *getFunctionType(bool BlocksToo = true) const; @@ -1145,7 +1155,7 @@ protected: ASTMutationListener *getASTMutationListener() const; }; -/// \brief Determine whether two declarations declare the same entity. +/// Determine whether two declarations declare the same entity. inline bool declaresSameEntity(const Decl *D1, const Decl *D2) { if (!D1 || !D2) return false; @@ -1172,7 +1182,7 @@ public: void print(raw_ostream &OS) const override; }; -/// \brief The results of name lookup within a DeclContext. This is either a +/// The results of name lookup within a DeclContext. This is either a /// single result (with no stable storage) or a collection of results (with /// stable storage provided by the lookup table). class DeclContextLookupResult { @@ -1253,36 +1263,36 @@ class DeclContext { /// DeclKind - This indicates which class this is. unsigned DeclKind : 8; - /// \brief Whether this declaration context also has some external + /// Whether this declaration context also has some external /// storage that contains additional declarations that are lexically /// part of this context. mutable bool ExternalLexicalStorage : 1; - /// \brief Whether this declaration context also has some external + /// Whether this declaration context also has some external /// storage that contains additional declarations that are visible /// in this context. mutable bool ExternalVisibleStorage : 1; - /// \brief Whether this declaration context has had external visible + /// Whether this declaration context has had external visible /// storage added since the last lookup. In this case, \c LookupPtr's /// invariant may not hold and needs to be fixed before we perform /// another lookup. mutable bool NeedToReconcileExternalVisibleStorage : 1; - /// \brief If \c true, this context may have local lexical declarations + /// If \c true, this context may have local lexical declarations /// that are missing from the lookup table. mutable bool HasLazyLocalLexicalLookups : 1; - /// \brief If \c true, the external source may have lexical declarations + /// If \c true, the external source may have lexical declarations /// that are missing from the lookup table. mutable bool HasLazyExternalLexicalLookups : 1; - /// \brief If \c true, lookups should only return identifier from + /// If \c true, lookups should only return identifier from /// DeclContext scope (for example TranslationUnit). Used in /// LookupQualifiedName() mutable bool UseQualifiedLookup : 1; - /// \brief Pointer to the data structure used to lookup declarations + /// Pointer to the data structure used to lookup declarations /// within this context (or a DependentStoredDeclsMap if this is a /// dependent context). We maintain the invariant that, if the map /// contains an entry for a DeclarationName (and we haven't lazily @@ -1305,7 +1315,7 @@ protected: /// another pointer. mutable Decl *LastDecl = nullptr; - /// \brief Build up a chain of declarations. + /// Build up a chain of declarations. /// /// \returns the first/last pair of declarations. static std::pair<Decl *, Decl *> @@ -1388,7 +1398,7 @@ public: } } - /// \brief Test whether the context supports looking up names. + /// Test whether the context supports looking up names. bool isLookupContext() const { return !isFunctionOrMethod() && DeclKind != Decl::LinkageSpec && DeclKind != Decl::Export; @@ -1414,7 +1424,7 @@ public: bool isInlineNamespace() const; - /// \brief Determines whether this context is dependent on a + /// Determines whether this context is dependent on a /// template parameter. bool isDependentContext() const; @@ -1435,28 +1445,28 @@ public: /// C++0x scoped enums), and C++ linkage specifications. bool isTransparentContext() const; - /// \brief Determines whether this context or some of its ancestors is a + /// Determines whether this context or some of its ancestors is a /// linkage specification context that specifies C linkage. bool isExternCContext() const; - /// \brief Retrieve the nearest enclosing C linkage specification context. + /// Retrieve the nearest enclosing C linkage specification context. const LinkageSpecDecl *getExternCContext() const; - /// \brief Determines whether this context or some of its ancestors is a + /// Determines whether this context or some of its ancestors is a /// linkage specification context that specifies C++ linkage. bool isExternCXXContext() const; - /// \brief Determine whether this declaration context is equivalent + /// Determine whether this declaration context is equivalent /// to the declaration context DC. bool Equals(const DeclContext *DC) const { return DC && this->getPrimaryContext() == DC->getPrimaryContext(); } - /// \brief Determine whether this declaration context encloses the + /// Determine whether this declaration context encloses the /// declaration context DC. bool Encloses(const DeclContext *DC) const; - /// \brief Find the nearest non-closure ancestor of this context, + /// Find the nearest non-closure ancestor of this context, /// i.e. the innermost semantic parent of this context which is not /// a closure. A context may be its own non-closure ancestor. Decl *getNonClosureAncestor(); @@ -1483,19 +1493,19 @@ public: return const_cast<DeclContext *>(this)->getRedeclContext(); } - /// \brief Retrieve the nearest enclosing namespace context. + /// Retrieve the nearest enclosing namespace context. DeclContext *getEnclosingNamespaceContext(); const DeclContext *getEnclosingNamespaceContext() const { return const_cast<DeclContext *>(this)->getEnclosingNamespaceContext(); } - /// \brief Retrieve the outermost lexically enclosing record context. + /// 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 + /// 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(). /// @@ -1503,7 +1513,7 @@ public: /// inline, its enclosing namespace, recursively. bool InEnclosingNamespaceSetOf(const DeclContext *NS) const; - /// \brief Collects all of the declaration contexts that are semantically + /// Collects all of the declaration contexts that are semantically /// connected to this declaration context. /// /// For declaration contexts that have multiple semantically connected but @@ -1659,7 +1669,7 @@ public: } }; - /// \brief Iterates over a filtered subrange of declarations stored + /// Iterates over a filtered subrange of declarations stored /// in a DeclContext. /// /// This iterator visits only those declarations that are of type @@ -1735,7 +1745,7 @@ public: } }; - /// @brief Add the declaration D into this context. + /// Add the declaration D into this context. /// /// This routine should be invoked when the declaration D has first /// been declared, to place D into the context where it was @@ -1749,7 +1759,7 @@ public: /// semantic context via makeDeclVisibleInContext. void addDecl(Decl *D); - /// @brief Add the declaration D into this context, but suppress + /// Add the declaration D into this context, but suppress /// searches for external declarations with the same name. /// /// Although analogous in function to addDecl, this removes an @@ -1759,7 +1769,7 @@ public: /// See the ASTImporter for use cases. void addDeclInternal(Decl *D); - /// @brief Add the declaration D to this context without modifying + /// Add the declaration D to this context without modifying /// any lookup tables. /// /// This is useful for some operations in dependent contexts where @@ -1767,12 +1777,16 @@ public: /// only happens with friends. void addHiddenDecl(Decl *D); - /// @brief Removes a declaration from this context. + /// Removes a declaration from this context. void removeDecl(Decl *D); - - /// @brief Checks whether a declaration is in this context. + + /// Checks whether a declaration is in this context. bool containsDecl(Decl *D) const; + /// Checks whether a declaration is in this context. + /// This also loads the Decls from the external source before the check. + bool containsDeclAndLoad(Decl *D) const; + using lookup_result = DeclContextLookupResult; using lookup_iterator = lookup_result::iterator; @@ -1783,12 +1797,12 @@ public: /// routine will not look into parent contexts. lookup_result lookup(DeclarationName Name) const; - /// \brief Find the declarations with the given name that are visible + /// Find the declarations with the given name that are visible /// within this context; don't attempt to retrieve anything from an /// external source. lookup_result noload_lookup(DeclarationName Name); - /// \brief A simplistic name lookup mechanism that performs name lookup + /// A simplistic name lookup mechanism that performs name lookup /// into this declaration context without consulting the external source. /// /// This function should almost never be used, because it subverts the @@ -1800,7 +1814,7 @@ public: void localUncachedLookup(DeclarationName Name, SmallVectorImpl<NamedDecl *> &Results); - /// @brief Makes a declaration visible within this context. + /// Makes a declaration visible within this context. /// /// This routine makes the declaration D visible to name lookup /// within this context and, if this is a transparent context, @@ -1823,13 +1837,15 @@ public: using lookups_range = llvm::iterator_range<all_lookups_iterator>; lookups_range lookups() const; - lookups_range noload_lookups() const; + // Like lookups(), but avoids loading external declarations. + // If PreserveInternalState, avoids building lookup data structures too. + lookups_range noload_lookups(bool PreserveInternalState) const; - /// \brief Iterators over all possible lookups within this context. + /// Iterators over all possible lookups within this context. all_lookups_iterator lookups_begin() const; all_lookups_iterator lookups_end() const; - /// \brief Iterators over all possible lookups within this context that are + /// Iterators over all possible lookups within this context that are /// currently loaded; don't attempt to retrieve anything from an external /// source. all_lookups_iterator noload_lookups_begin() const; @@ -1861,7 +1877,7 @@ public: // Low-level accessors - /// \brief Mark that there are external lexical declarations that we need + /// Mark that there are external lexical declarations that we need /// to include in our lookup table (and that are not available as external /// visible lookups). These extra lookup results will be found by walking /// the lexical declarations of this context. This should be used only if @@ -1873,28 +1889,28 @@ public: HasLazyExternalLexicalLookups = true; } - /// \brief Retrieve the internal representation of the lookup structure. + /// Retrieve the internal representation of the lookup structure. /// This may omit some names if we are lazily building the structure. StoredDeclsMap *getLookupPtr() const { return LookupPtr; } - /// \brief Ensure the lookup structure is fully-built and return it. + /// Ensure the lookup structure is fully-built and return it. StoredDeclsMap *buildLookup(); - /// \brief Whether this DeclContext has external storage containing + /// Whether this DeclContext has external storage containing /// additional declarations that are lexically in this context. bool hasExternalLexicalStorage() const { return ExternalLexicalStorage; } - /// \brief State whether this DeclContext has external storage for + /// State whether this DeclContext has external storage for /// declarations lexically in this context. void setHasExternalLexicalStorage(bool ES = true) { ExternalLexicalStorage = ES; } - /// \brief Whether this DeclContext has external storage containing + /// Whether this DeclContext has external storage containing /// additional declarations that are visible in this context. bool hasExternalVisibleStorage() const { return ExternalVisibleStorage; } - /// \brief State whether this DeclContext has external storage for + /// State whether this DeclContext has external storage for /// declarations visible in this context. void setHasExternalVisibleStorage(bool ES = true) { ExternalVisibleStorage = ES; @@ -1902,7 +1918,7 @@ public: NeedToReconcileExternalVisibleStorage = true; } - /// \brief Determine whether the given declaration is stored in the list of + /// Determine whether the given declaration is stored in the list of /// declarations lexically within this context. bool isDeclInLexicalTraversal(const Decl *D) const { return D && (D->NextInContextAndBits.getPointer() || D == FirstDecl || @@ -1933,7 +1949,7 @@ private: void reconcileExternalVisibleStorage() const; bool LoadLexicalDeclsFromExternalStorage() const; - /// @brief Makes a declaration visible within this context, but + /// Makes a declaration visible within this context, but /// suppresses searches for external declarations with the same /// name. /// @@ -1943,6 +1959,7 @@ private: StoredDeclsMap *CreateStoredDeclsMap(ASTContext &C) const; + void loadLazyLocalLexicalLookups(); void buildLookupImpl(DeclContext *DCtx, bool Internal); void makeDeclVisibleInContextWithFlags(NamedDecl *D, bool Internal, bool Rediscoverable); diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index 88dc9a6559172..1d0489912c6bd 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the C++ Decl subclasses, other than those for templates +/// Defines the C++ Decl subclasses, other than those for templates /// (found in DeclTemplate.h) and friends (in DeclFriend.h). // //===----------------------------------------------------------------------===// @@ -20,6 +20,7 @@ #include "clang/AST/ASTUnresolvedSet.h" #include "clang/AST/Attr.h" #include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExternalASTSource.h" @@ -72,7 +73,7 @@ class TemplateDecl; class TemplateParameterList; class UsingDecl; -/// \brief Represents any kind of function declaration, whether it is a +/// Represents any kind of function declaration, whether it is a /// concrete function or a function template. class AnyFunctionDecl { NamedDecl *Function; @@ -83,11 +84,11 @@ public: AnyFunctionDecl(FunctionDecl *FD) : Function(FD) {} AnyFunctionDecl(FunctionTemplateDecl *FTD); - /// \brief Implicily converts any function or function template into a + /// Implicily converts any function or function template into a /// named declaration. operator NamedDecl *() const { return Function; } - /// \brief Retrieve the underlying function or function template. + /// Retrieve the underlying function or function template. NamedDecl *get() const { return Function; } static AnyFunctionDecl getFromNamedDecl(NamedDecl *ND) { @@ -118,7 +119,7 @@ namespace llvm { namespace clang { -/// \brief Represents an access specifier followed by colon ':'. +/// Represents an access specifier followed by colon ':'. /// /// An objects of this class represents sugar for the syntactic occurrence /// of an access specifier followed by a colon in the list of member @@ -129,7 +130,7 @@ namespace clang { /// Also note that this class has nothing to do with so-called /// "access declarations" (C++98 11.3 [class.access.dcl]). class AccessSpecDecl : public Decl { - /// \brief The location of the ':'. + /// The location of the ':'. SourceLocation ColonLoc; AccessSpecDecl(AccessSpecifier AS, DeclContext *DC, @@ -143,16 +144,16 @@ class AccessSpecDecl : public Decl { virtual void anchor(); public: - /// \brief The location of the access specifier. + /// The location of the access specifier. SourceLocation getAccessSpecifierLoc() const { return getLocation(); } - /// \brief Sets the location of the access specifier. + /// Sets the location of the access specifier. void setAccessSpecifierLoc(SourceLocation ASLoc) { setLocation(ASLoc); } - /// \brief The location of the colon following the access specifier. + /// The location of the colon following the access specifier. SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Sets the location of the colon. + /// Sets the location of the colon. void setColonLoc(SourceLocation CLoc) { ColonLoc = CLoc; } SourceRange getSourceRange() const override LLVM_READONLY { @@ -172,7 +173,7 @@ public: static bool classofKind(Kind K) { return K == AccessSpec; } }; -/// \brief Represents a base class of a C++ class. +/// Represents a base class of a C++ class. /// /// Each CXXBaseSpecifier represents a single, direct base class (or /// struct) of a C++ class (or struct). It specifies the type of that @@ -189,35 +190,35 @@ public: /// In this code, C will have two CXXBaseSpecifiers, one for "public /// virtual A" and the other for "protected B". class CXXBaseSpecifier { - /// \brief The source code range that covers the full base + /// The source code range that covers the full base /// specifier, including the "virtual" (if present) and access /// specifier (if present). SourceRange Range; - /// \brief The source location of the ellipsis, if this is a pack + /// The source location of the ellipsis, if this is a pack /// expansion. SourceLocation EllipsisLoc; - /// \brief Whether this is a virtual base class or not. + /// Whether this is a virtual base class or not. unsigned Virtual : 1; - /// \brief Whether this is the base of a class (true) or of a struct (false). + /// Whether this is the base of a class (true) or of a struct (false). /// /// This determines the mapping from the access specifier as written in the /// source code to the access specifier used for semantic analysis. unsigned BaseOfClass : 1; - /// \brief Access specifier as written in the source code (may be AS_none). + /// Access specifier as written in the source code (may be AS_none). /// /// The actual type of data stored here is an AccessSpecifier, but we use /// "unsigned" here to work around a VC++ bug. unsigned Access : 2; - /// \brief Whether the class contains a using declaration + /// Whether the class contains a using declaration /// to inherit the named class's constructors. unsigned InheritConstructors : 1; - /// \brief The type of the base class. + /// The type of the base class. /// /// This will be a class or struct (or a typedef of such). The source code /// range does not include the \c virtual or the access specifier. @@ -230,40 +231,40 @@ public: : Range(R), EllipsisLoc(EllipsisLoc), Virtual(V), BaseOfClass(BC), Access(A), InheritConstructors(false), BaseTypeInfo(TInfo) {} - /// \brief Retrieves the source range that contains the entire base specifier. + /// Retrieves the source range that contains the entire base specifier. SourceRange getSourceRange() const LLVM_READONLY { return Range; } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } - /// \brief Get the location at which the base class type was written. + /// Get the location at which the base class type was written. SourceLocation getBaseTypeLoc() const LLVM_READONLY { return BaseTypeInfo->getTypeLoc().getLocStart(); } - /// \brief Determines whether the base class is a virtual base class (or not). + /// Determines whether the base class is a virtual base class (or not). bool isVirtual() const { return Virtual; } - /// \brief Determine whether this base class is a base of a class declared + /// Determine whether this base class is a base of a class declared /// with the 'class' keyword (vs. one declared with the 'struct' keyword). bool isBaseOfClass() const { return BaseOfClass; } - /// \brief Determine whether this base specifier is a pack expansion. + /// Determine whether this base specifier is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } - /// \brief Determine whether this base class's constructors get inherited. + /// Determine whether this base class's constructors get inherited. bool getInheritConstructors() const { return InheritConstructors; } - /// \brief Set that this base class's constructors should be inherited. + /// Set that this base class's constructors should be inherited. void setInheritConstructors(bool Inherit = true) { InheritConstructors = Inherit; } - /// \brief For a pack expansion, determine the location of the ellipsis. + /// For a pack expansion, determine the location of the ellipsis. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - /// \brief Returns the access specifier for this base specifier. + /// Returns the access specifier for this base specifier. /// /// This is the actual base specifier as used for semantic analysis, so /// the result can never be AS_none. To retrieve the access specifier as @@ -275,7 +276,7 @@ public: return (AccessSpecifier)Access; } - /// \brief Retrieves the access specifier as written in the source code + /// Retrieves the access specifier as written in the source code /// (which may mean that no access specifier was explicitly written). /// /// Use getAccessSpecifier() to retrieve the access specifier for use in @@ -284,18 +285,18 @@ public: return (AccessSpecifier)Access; } - /// \brief Retrieves the type of the base class. + /// Retrieves the type of the base class. /// /// This type will always be an unqualified class type. QualType getType() const { return BaseTypeInfo->getType().getUnqualifiedType(); } - /// \brief Retrieves the type and source location of the base class. + /// Retrieves the type and source location of the base class. TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; -/// \brief Represents a C++ struct/union/class. +/// Represents a C++ struct/union/class. class CXXRecordDecl : public RecordDecl { friend class ASTDeclReader; friend class ASTDeclWriter; @@ -321,16 +322,16 @@ class CXXRecordDecl : public RecordDecl { }; struct DefinitionData { - /// \brief True if this class has any user-declared constructors. + /// True if this class has any user-declared constructors. unsigned UserDeclaredConstructor : 1; - /// \brief The user-declared special members which this class has. + /// The user-declared special members which this class has. unsigned UserDeclaredSpecialMembers : 6; - /// \brief True when this class is an aggregate. + /// True when this class is an aggregate. unsigned Aggregate : 1; - /// \brief True when this class is a POD-type. + /// True when this class is a POD-type. unsigned PlainOldData : 1; /// true when this class is empty for traits purposes, @@ -339,15 +340,20 @@ class CXXRecordDecl : public RecordDecl { /// class. Doesn't take union-ness into account. unsigned Empty : 1; - /// \brief True when this class is polymorphic, i.e., has at + /// True when this class is polymorphic, i.e., has at /// least one virtual member or derives from a polymorphic class. unsigned Polymorphic : 1; - /// \brief True when this class is abstract, i.e., has at least + /// True when this class is abstract, i.e., has at least /// one pure virtual function, (that can come from a base class). unsigned Abstract : 1; - /// \brief True when this class has standard layout. + /// True when this class is standard-layout, per the applicable + /// language rules (including DRs). + unsigned IsStandardLayout : 1; + + /// True when this class was standard-layout under the C++11 + /// definition. /// /// C++11 [class]p7. A standard-layout class is a class that: /// * has no non-static data members of type non-standard-layout class (or @@ -361,57 +367,63 @@ class CXXRecordDecl : public RecordDecl { /// classes with non-static data members, and /// * has no base classes of the same type as the first non-static data /// member. - unsigned IsStandardLayout : 1; + unsigned IsCXX11StandardLayout : 1; - /// \brief True when there are no non-empty base classes. - /// + /// True when any base class has any declared non-static data + /// members or bit-fields. /// This is a helper bit of state used to implement IsStandardLayout more /// efficiently. - unsigned HasNoNonEmptyBases : 1; + unsigned HasBasesWithFields : 1; + + /// True when any base class has any declared non-static data + /// members. + /// This is a helper bit of state used to implement IsCXX11StandardLayout + /// more efficiently. + unsigned HasBasesWithNonStaticDataMembers : 1; - /// \brief True when there are private non-static data members. + /// True when there are private non-static data members. unsigned HasPrivateFields : 1; - /// \brief True when there are protected non-static data members. + /// True when there are protected non-static data members. unsigned HasProtectedFields : 1; - /// \brief True when there are private non-static data members. + /// True when there are private non-static data members. unsigned HasPublicFields : 1; - /// \brief True if this class (or any subobject) has mutable fields. + /// True if this class (or any subobject) has mutable fields. unsigned HasMutableFields : 1; - /// \brief True if this class (or any nested anonymous struct or union) + /// True if this class (or any nested anonymous struct or union) /// has variant members. unsigned HasVariantMembers : 1; - /// \brief True if there no non-field members declared by the user. + /// True if there no non-field members declared by the user. unsigned HasOnlyCMembers : 1; - /// \brief True if any field has an in-class initializer, including those + /// True if any field has an in-class initializer, including those /// within anonymous unions or structs. unsigned HasInClassInitializer : 1; - /// \brief True if any field is of reference type, and does not have an + /// True if any field is of reference type, and does not have an /// in-class initializer. /// /// In this case, value-initialization of this class is illegal in C++98 /// even if the class has a trivial default constructor. unsigned HasUninitializedReferenceMember : 1; - /// \brief True if any non-mutable field whose type doesn't have a user- + /// True if any non-mutable field whose type doesn't have a user- /// provided default ctor also doesn't have an in-class initializer. unsigned HasUninitializedFields : 1; - /// \brief True if there are any member using-declarations that inherit + /// True if there are any member using-declarations that inherit /// constructors from a base class. unsigned HasInheritedConstructor : 1; - /// \brief True if there are any member using-declarations named + /// True if there are any member using-declarations named /// 'operator='. unsigned HasInheritedAssignment : 1; - /// \brief These flags are \c true if a defaulted corresponding special + /// These flags are \c true if a defaulted corresponding special /// member can't be fully analyzed without performing overload resolution. /// @{ unsigned NeedOverloadResolutionForCopyConstructor : 1; @@ -420,7 +432,7 @@ class CXXRecordDecl : public RecordDecl { unsigned NeedOverloadResolutionForDestructor : 1; /// @} - /// \brief These flags are \c true if an implicit defaulted corresponding + /// These flags are \c true if an implicit defaulted corresponding /// special member would be defined as deleted. /// @{ unsigned DefaultedCopyConstructorIsDeleted : 1; @@ -429,7 +441,7 @@ class CXXRecordDecl : public RecordDecl { unsigned DefaultedDestructorIsDeleted : 1; /// @} - /// \brief The trivial special members which this class has, per + /// The trivial special members which this class has, per /// C++11 [class.ctor]p5, C++11 [class.copy]p12, C++11 [class.copy]p25, /// C++11 [class.dtor]p5, or would have if the member were not suppressed. /// @@ -437,7 +449,12 @@ class CXXRecordDecl : public RecordDecl { /// which have been declared but not yet defined. unsigned HasTrivialSpecialMembers : 6; - /// \brief The declared special members of this class which are known to be + /// These bits keep track of the triviality of special functions for the + /// purpose of calls. Only the bits corresponding to SMF_CopyConstructor, + /// SMF_MoveConstructor, and SMF_Destructor are meaningful here. + unsigned HasTrivialSpecialMembersForCall : 6; + + /// The declared special members of this class which are known to be /// non-trivial. /// /// This excludes any user-declared but not user-provided special members @@ -445,108 +462,108 @@ class CXXRecordDecl : public RecordDecl { /// members which have not yet been declared. unsigned DeclaredNonTrivialSpecialMembers : 6; - /// \brief True when this class has a destructor with no semantic effect. + /// These bits keep track of the declared special members that are + /// non-trivial for the purpose of calls. + /// Only the bits corresponding to SMF_CopyConstructor, + /// SMF_MoveConstructor, and SMF_Destructor are meaningful here. + unsigned DeclaredNonTrivialSpecialMembersForCall : 6; + + /// True when this class has a destructor with no semantic effect. unsigned HasIrrelevantDestructor : 1; - /// \brief True when this class has at least one user-declared constexpr + /// True when this class has at least one user-declared constexpr /// constructor which is neither the copy nor move constructor. unsigned HasConstexprNonCopyMoveConstructor : 1; - /// \brief True if this class has a (possibly implicit) defaulted default + /// True if this class has a (possibly implicit) defaulted default /// constructor. unsigned HasDefaultedDefaultConstructor : 1; - /// \brief True if this class can be passed in a non-address-preserving - /// fashion (such as in registers) according to the C++ language rules. - /// This does not imply anything about how the ABI in use will actually - /// pass an object of this class. - unsigned CanPassInRegisters : 1; - - /// \brief True if a defaulted default constructor for this class would + /// True if a defaulted default constructor for this class would /// be constexpr. unsigned DefaultedDefaultConstructorIsConstexpr : 1; - /// \brief True if this class has a constexpr default constructor. + /// True if this class has a constexpr default constructor. /// /// This is true for either a user-declared constexpr default constructor /// or an implicitly declared constexpr default constructor. unsigned HasConstexprDefaultConstructor : 1; - /// \brief True when this class contains at least one non-static data + /// True when this class contains at least one non-static data /// member or base class of non-literal or volatile type. unsigned HasNonLiteralTypeFieldsOrBases : 1; - /// \brief True when visible conversion functions are already computed + /// True when visible conversion functions are already computed /// and are available. unsigned ComputedVisibleConversions : 1; - /// \brief Whether we have a C++11 user-provided default constructor (not + /// Whether we have a C++11 user-provided default constructor (not /// explicitly deleted or defaulted). unsigned UserProvidedDefaultConstructor : 1; - /// \brief The special members which have been declared for this class, + /// The special members which have been declared for this class, /// either by the user or implicitly. unsigned DeclaredSpecialMembers : 6; - /// \brief Whether an implicit copy constructor could have a const-qualified + /// Whether an implicit copy constructor could have a const-qualified /// parameter, for initializing virtual bases and for other subobjects. unsigned ImplicitCopyConstructorCanHaveConstParamForVBase : 1; unsigned ImplicitCopyConstructorCanHaveConstParamForNonVBase : 1; - /// \brief Whether an implicit copy assignment operator would have a + /// Whether an implicit copy assignment operator would have a /// const-qualified parameter. unsigned ImplicitCopyAssignmentHasConstParam : 1; - /// \brief Whether any declared copy constructor has a const-qualified + /// Whether any declared copy constructor has a const-qualified /// parameter. unsigned HasDeclaredCopyConstructorWithConstParam : 1; - /// \brief Whether any declared copy assignment operator has either a + /// Whether any declared copy assignment operator has either a /// const-qualified reference parameter or a non-reference parameter. unsigned HasDeclaredCopyAssignmentWithConstParam : 1; - /// \brief Whether this class describes a C++ lambda. + /// Whether this class describes a C++ lambda. unsigned IsLambda : 1; - /// \brief Whether we are currently parsing base specifiers. + /// Whether we are currently parsing base specifiers. unsigned IsParsingBaseSpecifiers : 1; unsigned HasODRHash : 1; - /// \brief A hash of parts of the class to help in ODR checking. + /// A hash of parts of the class to help in ODR checking. unsigned ODRHash = 0; - /// \brief The number of base class specifiers in Bases. + /// The number of base class specifiers in Bases. unsigned NumBases = 0; - /// \brief The number of virtual base class specifiers in VBases. + /// The number of virtual base class specifiers in VBases. unsigned NumVBases = 0; - /// \brief Base classes of this class. + /// Base classes of this class. /// /// FIXME: This is wasted space for a union. LazyCXXBaseSpecifiersPtr Bases; - /// \brief direct and indirect virtual base classes of this class. + /// direct and indirect virtual base classes of this class. LazyCXXBaseSpecifiersPtr VBases; - /// \brief The conversion functions of this C++ class (but not its + /// The conversion functions of this C++ class (but not its /// inherited conversion functions). /// /// Each of the entries in this overload set is a CXXConversionDecl. LazyASTUnresolvedSet Conversions; - /// \brief The conversion functions of this C++ class and all those + /// The conversion functions of this C++ class and all those /// inherited conversion functions that are visible in this class. /// /// Each of the entries in this overload set is a CXXConversionDecl or a /// FunctionTemplateDecl. LazyASTUnresolvedSet VisibleConversions; - /// \brief The declaration which defines this record. + /// The declaration which defines this record. CXXRecordDecl *Definition; - /// \brief The first friend declaration in this class, or null if there + /// The first friend declaration in this class, or null if there /// aren't any. /// /// This is actually currently stored in reverse order. @@ -554,14 +571,14 @@ class CXXRecordDecl : public RecordDecl { DefinitionData(CXXRecordDecl *D); - /// \brief Retrieve the set of direct base classes. + /// Retrieve the set of direct base classes. CXXBaseSpecifier *getBases() const { if (!Bases.isOffset()) return Bases.get(nullptr); return getBasesSlowCase(); } - /// \brief Retrieve the set of virtual base classes. + /// Retrieve the set of virtual base classes. CXXBaseSpecifier *getVBases() const { if (!VBases.isOffset()) return VBases.get(nullptr); @@ -583,11 +600,11 @@ class CXXRecordDecl : public RecordDecl { struct DefinitionData *DefinitionData; - /// \brief Describes a C++ closure type (generated by a lambda expression). + /// Describes a C++ closure type (generated by a lambda expression). struct LambdaDefinitionData : public DefinitionData { using Capture = LambdaCapture; - /// \brief Whether this lambda is known to be dependent, even if its + /// Whether this lambda is known to be dependent, even if its /// context isn't dependent. /// /// A lambda with a non-dependent context can be dependent if it occurs @@ -597,33 +614,33 @@ class CXXRecordDecl : public RecordDecl { /// artifact of having to parse the default arguments before. unsigned Dependent : 1; - /// \brief Whether this lambda is a generic lambda. + /// Whether this lambda is a generic lambda. unsigned IsGenericLambda : 1; - /// \brief The Default Capture. + /// The Default Capture. unsigned CaptureDefault : 2; - /// \brief The number of captures in this lambda is limited 2^NumCaptures. + /// The number of captures in this lambda is limited 2^NumCaptures. unsigned NumCaptures : 15; - /// \brief The number of explicit captures in this lambda. + /// The number of explicit captures in this lambda. unsigned NumExplicitCaptures : 13; - /// \brief The number used to indicate this lambda expression for name + /// The number used to indicate this lambda expression for name /// mangling in the Itanium C++ ABI. unsigned ManglingNumber = 0; - /// \brief The declaration that provides context for this lambda, if the + /// The declaration that provides context for this lambda, if the /// actual DeclContext does not suffice. This is used for lambdas that /// occur within default arguments of function parameters within the class /// or within a data member initializer. LazyDeclPtr ContextDecl; - /// \brief The list of captures, both explicit and implicit, for this + /// The list of captures, both explicit and implicit, for this /// lambda. Capture *Captures = nullptr; - /// \brief The type of the call method. + /// The type of the call method. TypeSourceInfo *MethodTyInfo; LambdaDefinitionData(CXXRecordDecl *D, TypeSourceInfo *Info, @@ -661,7 +678,7 @@ class CXXRecordDecl : public RecordDecl { return static_cast<LambdaDefinitionData&>(*DD); } - /// \brief The template or declaration that this declaration + /// The template or declaration that this declaration /// describes or was instantiated from, respectively. /// /// For non-templates, this value will be null. For record @@ -673,11 +690,11 @@ class CXXRecordDecl : public RecordDecl { llvm::PointerUnion<ClassTemplateDecl *, MemberSpecializationInfo *> TemplateOrInstantiation; - /// \brief Called from setBases and addedMember to notify the class that a + /// Called from setBases and addedMember to notify the class that a /// direct or virtual base class or a member of class type has been added. void addedClassSubobject(CXXRecordDecl *Base); - /// \brief Notify the class that member has been added. + /// Notify the class that member has been added. /// /// This routine helps maintain information about the class based on which /// members have been added. It will be invoked by DeclContext::addDecl() @@ -686,20 +703,26 @@ class CXXRecordDecl : public RecordDecl { void markedVirtualFunctionPure(); - /// \brief Get the head of our list of friend declarations, possibly + /// Get the head of our list of friend declarations, possibly /// deserializing the friends from an external AST source. FriendDecl *getFirstFriend() const; + /// Determine whether this class has an empty base class subobject of type X + /// or of one of the types that might be at offset 0 within X (per the C++ + /// "standard layout" rules). + bool hasSubobjectAtOffsetZeroOfEmptyBaseType(ASTContext &Ctx, + const CXXRecordDecl *X); + protected: CXXRecordDecl(Kind K, TagKind TK, const ASTContext &C, DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, CXXRecordDecl *PrevDecl); public: - /// \brief Iterator that traverses the base classes of a class. + /// Iterator that traverses the base classes of a class. using base_class_iterator = CXXBaseSpecifier *; - /// \brief Iterator that traverses the base classes of a class. + /// Iterator that traverses the base classes of a class. using base_class_const_iterator = const CXXBaseSpecifier *; CXXRecordDecl *getCanonicalDecl() override { @@ -728,6 +751,21 @@ public: return const_cast<CXXRecordDecl*>(this)->getMostRecentDecl(); } + CXXRecordDecl *getMostRecentNonInjectedDecl() { + CXXRecordDecl *Recent = + static_cast<CXXRecordDecl *>(this)->getMostRecentDecl(); + while (Recent->isInjectedClassName()) { + // FIXME: Does injected class name need to be in the redeclarations chain? + assert(Recent->getPreviousDecl()); + Recent = Recent->getPreviousDecl(); + } + return Recent; + } + + const CXXRecordDecl *getMostRecentNonInjectedDecl() const { + return const_cast<CXXRecordDecl*>(this)->getMostRecentNonInjectedDecl(); + } + CXXRecordDecl *getDefinition() const { // We only need an update if we don't already know which // declaration is the definition. @@ -752,6 +790,18 @@ public: return data().Polymorphic || data().NumVBases != 0; } + /// @returns true if class is dynamic or might be dynamic because the + /// definition is incomplete of dependent. + bool mayBeDynamicClass() const { + return !hasDefinition() || isDynamicClass() || hasAnyDependentBases(); + } + + /// @returns true if class is non dynamic or might be non dynamic because the + /// definition is incomplete of dependent. + bool mayBeNonDynamicClass() const { + return !hasDefinition() || !isDynamicClass() || hasAnyDependentBases(); + } + void setIsParsingBaseSpecifiers() { data().IsParsingBaseSpecifiers = true; } bool isParsingBaseSpecifiers() const { @@ -760,10 +810,10 @@ public: unsigned getODRHash() const; - /// \brief Sets the base classes of this struct or class. + /// Sets the base classes of this struct or class. void setBases(CXXBaseSpecifier const * const *Bases, unsigned NumBases); - /// \brief Retrieves the number of base classes of this class. + /// Retrieves the number of base classes of this class. unsigned getNumBases() const { return data().NumBases; } using base_class_range = llvm::iterator_range<base_class_iterator>; @@ -784,7 +834,7 @@ public: return bases_begin() + data().NumBases; } - /// \brief Retrieves the number of virtual base classes of this class. + /// Retrieves the number of virtual base classes of this class. unsigned getNumVBases() const { return data().NumVBases; } base_class_range vbases() { @@ -801,7 +851,7 @@ public: return vbases_begin() + data().NumVBases; } - /// \brief Determine whether this class has any dependent base classes which + /// Determine whether this class has any dependent base classes which /// are not the current instantiation. bool hasAnyDependentBases() const; @@ -816,13 +866,13 @@ public: return method_range(method_begin(), method_end()); } - /// \brief Method begin iterator. Iterates in the order the methods + /// Method begin iterator. Iterates in the order the methods /// were declared. method_iterator method_begin() const { return method_iterator(decls_begin()); } - /// \brief Method past-the-end iterator. + /// Method past-the-end iterator. method_iterator method_end() const { return method_iterator(decls_end()); } @@ -857,7 +907,7 @@ public: return data().FirstFriend.isValid(); } - /// \brief \c true if a defaulted copy constructor for this class would be + /// \c true if a defaulted copy constructor for this class would be /// deleted. bool defaultedCopyConstructorIsDeleted() const { assert((!needsOverloadResolutionForCopyConstructor() || @@ -866,7 +916,7 @@ public: return data().DefaultedCopyConstructorIsDeleted; } - /// \brief \c true if a defaulted move constructor for this class would be + /// \c true if a defaulted move constructor for this class would be /// deleted. bool defaultedMoveConstructorIsDeleted() const { assert((!needsOverloadResolutionForMoveConstructor() || @@ -875,7 +925,7 @@ public: return data().DefaultedMoveConstructorIsDeleted; } - /// \brief \c true if a defaulted destructor for this class would be deleted. + /// \c true if a defaulted destructor for this class would be deleted. bool defaultedDestructorIsDeleted() const { assert((!needsOverloadResolutionForDestructor() || (data().DeclaredSpecialMembers & SMF_Destructor)) && @@ -883,41 +933,41 @@ public: return data().DefaultedDestructorIsDeleted; } - /// \brief \c true if we know for sure that this class has a single, + /// \c true if we know for sure that this class has a single, /// accessible, unambiguous copy constructor that is not deleted. bool hasSimpleCopyConstructor() const { return !hasUserDeclaredCopyConstructor() && !data().DefaultedCopyConstructorIsDeleted; } - /// \brief \c true if we know for sure that this class has a single, + /// \c true if we know for sure that this class has a single, /// accessible, unambiguous move constructor that is not deleted. bool hasSimpleMoveConstructor() const { return !hasUserDeclaredMoveConstructor() && hasMoveConstructor() && !data().DefaultedMoveConstructorIsDeleted; } - /// \brief \c true if we know for sure that this class has a single, + /// \c true if we know for sure that this class has a single, /// accessible, unambiguous move assignment operator that is not deleted. bool hasSimpleMoveAssignment() const { return !hasUserDeclaredMoveAssignment() && hasMoveAssignment() && !data().DefaultedMoveAssignmentIsDeleted; } - /// \brief \c true if we know for sure that this class has an accessible + /// \c true if we know for sure that this class has an accessible /// destructor that is not deleted. bool hasSimpleDestructor() const { return !hasUserDeclaredDestructor() && !data().DefaultedDestructorIsDeleted; } - /// \brief Determine whether this class has any default constructors. + /// Determine whether this class has any default constructors. bool hasDefaultConstructor() const { return (data().DeclaredSpecialMembers & SMF_DefaultConstructor) || needsImplicitDefaultConstructor(); } - /// \brief Determine if we need to declare a default constructor for + /// Determine if we need to declare a default constructor for /// this class. /// /// This value is used for lazy creation of default constructors. @@ -930,33 +980,33 @@ public: !isLambda(); } - /// \brief Determine whether this class has any user-declared constructors. + /// Determine whether this class has any user-declared constructors. /// /// When true, a default constructor will not be implicitly declared. bool hasUserDeclaredConstructor() const { return data().UserDeclaredConstructor; } - /// \brief Whether this class has a user-provided default constructor + /// Whether this class has a user-provided default constructor /// per C++11. bool hasUserProvidedDefaultConstructor() const { return data().UserProvidedDefaultConstructor; } - /// \brief Determine whether this class has a user-declared copy constructor. + /// Determine whether this class has a user-declared copy constructor. /// /// When false, a copy constructor will be implicitly declared. bool hasUserDeclaredCopyConstructor() const { return data().UserDeclaredSpecialMembers & SMF_CopyConstructor; } - /// \brief Determine whether this class needs an implicit copy + /// Determine whether this class needs an implicit copy /// constructor to be lazily declared. bool needsImplicitCopyConstructor() const { return !(data().DeclaredSpecialMembers & SMF_CopyConstructor); } - /// \brief Determine whether we need to eagerly declare a defaulted copy + /// Determine whether we need to eagerly declare a defaulted copy /// constructor for this class. bool needsOverloadResolutionForCopyConstructor() const { // C++17 [class.copy.ctor]p6: @@ -971,7 +1021,7 @@ public: return data().NeedOverloadResolutionForCopyConstructor; } - /// \brief Determine whether an implicit copy constructor for this type + /// Determine whether an implicit copy constructor for this type /// would have a parameter with a const-qualified reference type. bool implicitCopyConstructorHasConstParam() const { return data().ImplicitCopyConstructorCanHaveConstParamForNonVBase && @@ -979,7 +1029,7 @@ public: data().ImplicitCopyConstructorCanHaveConstParamForVBase); } - /// \brief Determine whether this class has a copy constructor with + /// Determine whether this class has a copy constructor with /// a parameter type which is a reference to a const-qualified type. bool hasCopyConstructorWithConstParam() const { return data().HasDeclaredCopyConstructorWithConstParam || @@ -987,7 +1037,7 @@ public: implicitCopyConstructorHasConstParam()); } - /// \brief Whether this class has a user-declared move constructor or + /// Whether this class has a user-declared move constructor or /// assignment operator. /// /// When false, a move constructor and assignment operator may be @@ -997,19 +1047,19 @@ public: (SMF_MoveConstructor | SMF_MoveAssignment); } - /// \brief Determine whether this class has had a move constructor + /// Determine whether this class has had a move constructor /// declared by the user. bool hasUserDeclaredMoveConstructor() const { return data().UserDeclaredSpecialMembers & SMF_MoveConstructor; } - /// \brief Determine whether this class has a move constructor. + /// Determine whether this class has a move constructor. bool hasMoveConstructor() const { return (data().DeclaredSpecialMembers & SMF_MoveConstructor) || needsImplicitMoveConstructor(); } - /// \brief Set that we attempted to declare an implicit copy + /// Set that we attempted to declare an implicit copy /// constructor, but overload resolution failed so we deleted it. void setImplicitCopyConstructorIsDeleted() { assert((data().DefaultedCopyConstructorIsDeleted || @@ -1018,7 +1068,7 @@ public: data().DefaultedCopyConstructorIsDeleted = true; } - /// \brief Set that we attempted to declare an implicit move + /// Set that we attempted to declare an implicit move /// constructor, but overload resolution failed so we deleted it. void setImplicitMoveConstructorIsDeleted() { assert((data().DefaultedMoveConstructorIsDeleted || @@ -1027,7 +1077,7 @@ public: data().DefaultedMoveConstructorIsDeleted = true; } - /// \brief Set that we attempted to declare an implicit destructor, + /// Set that we attempted to declare an implicit destructor, /// but overload resolution failed so we deleted it. void setImplicitDestructorIsDeleted() { assert((data().DefaultedDestructorIsDeleted || @@ -1036,7 +1086,7 @@ public: data().DefaultedDestructorIsDeleted = true; } - /// \brief Determine whether this class should get an implicit move + /// Determine whether this class should get an implicit move /// constructor or if any existing special member function inhibits this. bool needsImplicitMoveConstructor() const { return !(data().DeclaredSpecialMembers & SMF_MoveConstructor) && @@ -1046,39 +1096,39 @@ public: !hasUserDeclaredDestructor(); } - /// \brief Determine whether we need to eagerly declare a defaulted move + /// Determine whether we need to eagerly declare a defaulted move /// constructor for this class. bool needsOverloadResolutionForMoveConstructor() const { return data().NeedOverloadResolutionForMoveConstructor; } - /// \brief Determine whether this class has a user-declared copy assignment + /// Determine whether this class has a user-declared copy assignment /// operator. /// - /// When false, a copy assigment operator will be implicitly declared. + /// When false, a copy assignment operator will be implicitly declared. bool hasUserDeclaredCopyAssignment() const { return data().UserDeclaredSpecialMembers & SMF_CopyAssignment; } - /// \brief Determine whether this class needs an implicit copy + /// Determine whether this class needs an implicit copy /// assignment operator to be lazily declared. bool needsImplicitCopyAssignment() const { return !(data().DeclaredSpecialMembers & SMF_CopyAssignment); } - /// \brief Determine whether we need to eagerly declare a defaulted copy + /// Determine whether we need to eagerly declare a defaulted copy /// assignment operator for this class. bool needsOverloadResolutionForCopyAssignment() const { return data().HasMutableFields; } - /// \brief Determine whether an implicit copy assignment operator for this + /// Determine whether an implicit copy assignment operator for this /// type would have a parameter with a const-qualified reference type. bool implicitCopyAssignmentHasConstParam() const { return data().ImplicitCopyAssignmentHasConstParam; } - /// \brief Determine whether this class has a copy assignment operator with + /// Determine whether this class has a copy assignment operator with /// a parameter type which is a reference to a const-qualified type or is not /// a reference. bool hasCopyAssignmentWithConstParam() const { @@ -1087,19 +1137,19 @@ public: implicitCopyAssignmentHasConstParam()); } - /// \brief Determine whether this class has had a move assignment + /// Determine whether this class has had a move assignment /// declared by the user. bool hasUserDeclaredMoveAssignment() const { return data().UserDeclaredSpecialMembers & SMF_MoveAssignment; } - /// \brief Determine whether this class has a move assignment operator. + /// Determine whether this class has a move assignment operator. bool hasMoveAssignment() const { return (data().DeclaredSpecialMembers & SMF_MoveAssignment) || needsImplicitMoveAssignment(); } - /// \brief Set that we attempted to declare an implicit move assignment + /// Set that we attempted to declare an implicit move assignment /// operator, but overload resolution failed so we deleted it. void setImplicitMoveAssignmentIsDeleted() { assert((data().DefaultedMoveAssignmentIsDeleted || @@ -1108,7 +1158,7 @@ public: data().DefaultedMoveAssignmentIsDeleted = true; } - /// \brief Determine whether this class should get an implicit move + /// Determine whether this class should get an implicit move /// assignment operator or if any existing special member function inhibits /// this. bool needsImplicitMoveAssignment() const { @@ -1123,53 +1173,53 @@ public: !isLambda(); } - /// \brief Determine whether we need to eagerly declare a move assignment + /// Determine whether we need to eagerly declare a move assignment /// operator for this class. bool needsOverloadResolutionForMoveAssignment() const { return data().NeedOverloadResolutionForMoveAssignment; } - /// \brief Determine whether this class has a user-declared destructor. + /// Determine whether this class has a user-declared destructor. /// /// When false, a destructor will be implicitly declared. bool hasUserDeclaredDestructor() const { return data().UserDeclaredSpecialMembers & SMF_Destructor; } - /// \brief Determine whether this class needs an implicit destructor to + /// Determine whether this class needs an implicit destructor to /// be lazily declared. bool needsImplicitDestructor() const { return !(data().DeclaredSpecialMembers & SMF_Destructor); } - /// \brief Determine whether we need to eagerly declare a destructor for this + /// Determine whether we need to eagerly declare a destructor for this /// class. bool needsOverloadResolutionForDestructor() const { return data().NeedOverloadResolutionForDestructor; } - /// \brief Determine whether this class describes a lambda function object. + /// Determine whether this class describes a lambda function object. bool isLambda() const { // An update record can't turn a non-lambda into a lambda. auto *DD = DefinitionData; return DD && DD->IsLambda; } - /// \brief Determine whether this class describes a generic + /// Determine whether this class describes a generic /// lambda function object (i.e. function call operator is /// a template). bool isGenericLambda() const; - /// \brief Retrieve the lambda call operator of the closure type + /// Retrieve the lambda call operator of the closure type /// if this is a closure type. CXXMethodDecl *getLambdaCallOperator() const; - /// \brief Retrieve the lambda static invoker, the address of which + /// Retrieve the lambda static invoker, the address of which /// is returned by the conversion operator, and the body of which /// is forwarded to the lambda call operator. CXXMethodDecl *getLambdaStaticInvoker() const; - /// \brief Retrieve the generic lambda's template parameter list. + /// Retrieve the generic lambda's template parameter list. /// Returns null if the class does not represent a lambda or a generic /// lambda. TemplateParameterList *getGenericLambdaTemplateParameterList() const; @@ -1179,7 +1229,7 @@ public: return static_cast<LambdaCaptureDefault>(getLambdaData().CaptureDefault); } - /// \brief For a closure type, retrieve the mapping from captured + /// For a closure type, retrieve the mapping from captured /// variables and \c this to the non-static data members that store the /// values or references of the captures. /// @@ -1225,7 +1275,7 @@ public: /// this class must currently be in the process of being defined. void removeConversion(const NamedDecl *Old); - /// \brief Get all conversion functions visible in current class, + /// Get all conversion functions visible in current class, /// including conversion function templates. llvm::iterator_range<conversion_iterator> getVisibleConversionFunctions(); @@ -1235,12 +1285,12 @@ public: /// functions (C++ [dcl.init.aggr]p1). bool isAggregate() const { return data().Aggregate; } - /// \brief Whether this class has any in-class initializers + /// Whether this class has any in-class initializers /// for non-static data members (including those in anonymous unions or /// structs). bool hasInClassInitializer() const { return data().HasInClassInitializer; } - /// \brief Whether this class or any of its subobjects has any members of + /// Whether this class or any of its subobjects has any members of /// reference type which would make value-initialization ill-formed. /// /// Per C++03 [dcl.init]p5: @@ -1253,7 +1303,7 @@ public: data().HasUninitializedReferenceMember; } - /// \brief Whether this class is a POD-type (C++ [class]p4) + /// Whether this class is a POD-type (C++ [class]p4) /// /// For purposes of this function a class is POD if it is an aggregate /// that has no non-static non-POD data members, no reference data @@ -1263,11 +1313,11 @@ public: /// Note that this is the C++ TR1 definition of POD. bool isPOD() const { return data().PlainOldData; } - /// \brief True if this class is C-like, without C++-specific features, e.g. + /// True if this class is C-like, without C++-specific features, e.g. /// it contains only public fields, no bases, tag kind is not 'class', etc. bool isCLike() const; - /// \brief Determine whether this is an empty class in the sense of + /// Determine whether this is an empty class in the sense of /// (C++11 [meta.unary.prop]). /// /// The CXXRecordDecl is a class type, but not a union type, @@ -1278,7 +1328,7 @@ public: /// \note This does NOT include a check for union-ness. bool isEmpty() const { return data().Empty; } - /// \brief Determine whether this class has direct non-static data members. + /// Determine whether this class has direct non-static data members. bool hasDirectFields() const { auto &D = data(); return D.HasPublicFields || D.HasProtectedFields || D.HasPrivateFields; @@ -1288,32 +1338,36 @@ public: /// which means that the class contains or inherits a virtual function. bool isPolymorphic() const { return data().Polymorphic; } - /// \brief Determine whether this class has a pure virtual function. + /// Determine whether this class has a pure virtual function. /// /// The class is is abstract per (C++ [class.abstract]p2) if it declares /// a pure virtual function or inherits a pure virtual function that is /// not overridden. bool isAbstract() const { return data().Abstract; } - /// \brief Determine whether this class has standard layout per - /// (C++ [class]p7) + /// Determine whether this class is standard-layout per + /// C++ [class]p7. bool isStandardLayout() const { return data().IsStandardLayout; } - /// \brief Determine whether this class, or any of its class subobjects, + /// Determine whether this class was standard-layout per + /// C++11 [class]p7, specifically using the C++11 rules without any DRs. + bool isCXX11StandardLayout() const { return data().IsCXX11StandardLayout; } + + /// Determine whether this class, or any of its class subobjects, /// contains a mutable field. bool hasMutableFields() const { return data().HasMutableFields; } - /// \brief Determine whether this class has any variant members. + /// Determine whether this class has any variant members. bool hasVariantMembers() const { return data().HasVariantMembers; } - /// \brief Determine whether this class has a trivial default constructor + /// Determine whether this class has a trivial default constructor /// (C++11 [class.ctor]p5). bool hasTrivialDefaultConstructor() const { return hasDefaultConstructor() && (data().HasTrivialSpecialMembers & SMF_DefaultConstructor); } - /// \brief Determine whether this class has a non-trivial default constructor + /// Determine whether this class has a non-trivial default constructor /// (C++11 [class.ctor]p5). bool hasNonTrivialDefaultConstructor() const { return (data().DeclaredNonTrivialSpecialMembers & SMF_DefaultConstructor) || @@ -1321,7 +1375,7 @@ public: !(data().HasTrivialSpecialMembers & SMF_DefaultConstructor)); } - /// \brief Determine whether this class has at least one constexpr constructor + /// Determine whether this class has at least one constexpr constructor /// other than the copy or move constructors. bool hasConstexprNonCopyMoveConstructor() const { return data().HasConstexprNonCopyMoveConstructor || @@ -1329,41 +1383,56 @@ public: defaultedDefaultConstructorIsConstexpr()); } - /// \brief Determine whether a defaulted default constructor for this class + /// Determine whether a defaulted default constructor for this class /// would be constexpr. bool defaultedDefaultConstructorIsConstexpr() const { return data().DefaultedDefaultConstructorIsConstexpr && (!isUnion() || hasInClassInitializer() || !hasVariantMembers()); } - /// \brief Determine whether this class has a constexpr default constructor. + /// Determine whether this class has a constexpr default constructor. bool hasConstexprDefaultConstructor() const { return data().HasConstexprDefaultConstructor || (needsImplicitDefaultConstructor() && defaultedDefaultConstructorIsConstexpr()); } - /// \brief Determine whether this class has a trivial copy constructor + /// Determine whether this class has a trivial copy constructor /// (C++ [class.copy]p6, C++11 [class.copy]p12) bool hasTrivialCopyConstructor() const { return data().HasTrivialSpecialMembers & SMF_CopyConstructor; } - /// \brief Determine whether this class has a non-trivial copy constructor + bool hasTrivialCopyConstructorForCall() const { + return data().HasTrivialSpecialMembersForCall & SMF_CopyConstructor; + } + + /// Determine whether this class has a non-trivial copy constructor /// (C++ [class.copy]p6, C++11 [class.copy]p12) bool hasNonTrivialCopyConstructor() const { return data().DeclaredNonTrivialSpecialMembers & SMF_CopyConstructor || !hasTrivialCopyConstructor(); } - /// \brief Determine whether this class has a trivial move constructor + bool hasNonTrivialCopyConstructorForCall() const { + return (data().DeclaredNonTrivialSpecialMembersForCall & + SMF_CopyConstructor) || + !hasTrivialCopyConstructorForCall(); + } + + /// Determine whether this class has a trivial move constructor /// (C++11 [class.copy]p12) bool hasTrivialMoveConstructor() const { return hasMoveConstructor() && (data().HasTrivialSpecialMembers & SMF_MoveConstructor); } - /// \brief Determine whether this class has a non-trivial move constructor + bool hasTrivialMoveConstructorForCall() const { + return hasMoveConstructor() && + (data().HasTrivialSpecialMembersForCall & SMF_MoveConstructor); + } + + /// Determine whether this class has a non-trivial move constructor /// (C++11 [class.copy]p12) bool hasNonTrivialMoveConstructor() const { return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveConstructor) || @@ -1371,27 +1440,34 @@ public: !(data().HasTrivialSpecialMembers & SMF_MoveConstructor)); } - /// \brief Determine whether this class has a trivial copy assignment operator + bool hasNonTrivialMoveConstructorForCall() const { + return (data().DeclaredNonTrivialSpecialMembersForCall & + SMF_MoveConstructor) || + (needsImplicitMoveConstructor() && + !(data().HasTrivialSpecialMembersForCall & SMF_MoveConstructor)); + } + + /// Determine whether this class has a trivial copy assignment operator /// (C++ [class.copy]p11, C++11 [class.copy]p25) bool hasTrivialCopyAssignment() const { return data().HasTrivialSpecialMembers & SMF_CopyAssignment; } - /// \brief Determine whether this class has a non-trivial copy assignment + /// Determine whether this class has a non-trivial copy assignment /// operator (C++ [class.copy]p11, C++11 [class.copy]p25) bool hasNonTrivialCopyAssignment() const { return data().DeclaredNonTrivialSpecialMembers & SMF_CopyAssignment || !hasTrivialCopyAssignment(); } - /// \brief Determine whether this class has a trivial move assignment operator + /// Determine whether this class has a trivial move assignment operator /// (C++11 [class.copy]p25) bool hasTrivialMoveAssignment() const { return hasMoveAssignment() && (data().HasTrivialSpecialMembers & SMF_MoveAssignment); } - /// \brief Determine whether this class has a non-trivial move assignment + /// Determine whether this class has a non-trivial move assignment /// operator (C++11 [class.copy]p25) bool hasNonTrivialMoveAssignment() const { return (data().DeclaredNonTrivialSpecialMembers & SMF_MoveAssignment) || @@ -1399,19 +1475,32 @@ public: !(data().HasTrivialSpecialMembers & SMF_MoveAssignment)); } - /// \brief Determine whether this class has a trivial destructor + /// Determine whether this class has a trivial destructor /// (C++ [class.dtor]p3) bool hasTrivialDestructor() const { return data().HasTrivialSpecialMembers & SMF_Destructor; } - /// \brief Determine whether this class has a non-trivial destructor + bool hasTrivialDestructorForCall() const { + return data().HasTrivialSpecialMembersForCall & SMF_Destructor; + } + + /// Determine whether this class has a non-trivial destructor /// (C++ [class.dtor]p3) bool hasNonTrivialDestructor() const { return !(data().HasTrivialSpecialMembers & SMF_Destructor); } - /// \brief Determine whether declaring a const variable with this type is ok + bool hasNonTrivialDestructorForCall() const { + return !(data().HasTrivialSpecialMembersForCall & SMF_Destructor); + } + + void setHasTrivialSpecialMemberForCall() { + data().HasTrivialSpecialMembersForCall = + (SMF_CopyConstructor | SMF_MoveConstructor | SMF_Destructor); + } + + /// Determine whether declaring a const variable with this type is ok /// per core issue 253. bool allowConstDefaultInit() const { return !data().HasUninitializedFields || @@ -1419,7 +1508,7 @@ public: needsImplicitDefaultConstructor()); } - /// \brief Determine whether this class has a destructor which has no + /// Determine whether this class has a destructor which has no /// semantic effect. /// /// Any such destructor will be trivial, public, defaulted and not deleted, @@ -1428,41 +1517,29 @@ public: return data().HasIrrelevantDestructor; } - /// \brief Determine whether this class has at least one trivial, non-deleted - /// copy or move constructor. - bool canPassInRegisters() const { - return data().CanPassInRegisters; - } - - /// \brief Set that we can pass this RecordDecl in registers. - // FIXME: This should be set as part of completeDefinition. - void setCanPassInRegisters(bool CanPass) { - data().CanPassInRegisters = CanPass; - } - - /// \brief Determine whether this class has a non-literal or/ volatile type + /// Determine whether this class has a non-literal or/ volatile type /// non-static data member or base class. bool hasNonLiteralTypeFieldsOrBases() const { return data().HasNonLiteralTypeFieldsOrBases; } - /// \brief Determine whether this class has a using-declaration that names + /// Determine whether this class has a using-declaration that names /// a user-declared base class constructor. bool hasInheritedConstructor() const { return data().HasInheritedConstructor; } - /// \brief Determine whether this class has a using-declaration that names + /// Determine whether this class has a using-declaration that names /// a base class assignment operator. bool hasInheritedAssignment() const { return data().HasInheritedAssignment; } - /// \brief Determine whether this class is considered trivially copyable per + /// Determine whether this class is considered trivially copyable per /// (C++11 [class]p6). bool isTriviallyCopyable() const; - /// \brief Determine whether this class is considered trivial. + /// Determine whether this class is considered trivial. /// /// C++11 [class]p6: /// "A trivial class is a class that has a trivial default constructor and @@ -1471,7 +1548,7 @@ public: return isTriviallyCopyable() && hasTrivialDefaultConstructor(); } - /// \brief Determine whether this class is a literal type. + /// Determine whether this class is a literal type. /// /// C++11 [basic.types]p10: /// A class type that has all the following properties: @@ -1497,7 +1574,7 @@ public: hasTrivialDefaultConstructor()); } - /// \brief If this record is an instantiation of a member class, + /// If this record is an instantiation of a member class, /// retrieves the member class from which it was instantiated. /// /// This routine will return non-null for (non-templated) member @@ -1518,17 +1595,17 @@ public: /// declaration returned by getInstantiatedFromMemberClass(). CXXRecordDecl *getInstantiatedFromMemberClass() const; - /// \brief If this class is an instantiation of a member class of a + /// If this class is an instantiation of a member class of a /// class template specialization, retrieves the member specialization /// information. MemberSpecializationInfo *getMemberSpecializationInfo() const; - /// \brief Specify that this record is an instantiation of the + /// Specify that this record is an instantiation of the /// member class \p RD. void setInstantiationOfMemberClass(CXXRecordDecl *RD, TemplateSpecializationKind TSK); - /// \brief Retrieves the class template that is described by this + /// Retrieves the class template that is described by this /// class declaration. /// /// Every class template is represented as a ClassTemplateDecl and a @@ -1543,15 +1620,15 @@ public: void setDescribedClassTemplate(ClassTemplateDecl *Template); - /// \brief Determine whether this particular class is a specialization or + /// Determine whether this particular class is a specialization or /// instantiation of a class template or member class of a class template, /// and how it was instantiated or specialized. TemplateSpecializationKind getTemplateSpecializationKind() const; - /// \brief Set the kind of specialization or template instantiation this is. + /// 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 + /// 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; @@ -1560,17 +1637,17 @@ public: ->getTemplateInstantiationPattern()); } - /// \brief Returns the destructor decl for this class. + /// Returns the destructor decl for this class. CXXDestructorDecl *getDestructor() const; - /// \brief Returns true if the class destructor, or any implicitly invoked + /// Returns true if the class destructor, or any implicitly invoked /// destructors are marked noreturn. bool isAnyDestructorNoReturn() const; - /// \brief If the class is a local class [class.local], returns + /// If the class is a local class [class.local], returns /// the enclosing function declaration. const FunctionDecl *isLocalClass() const { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(getDeclContext())) + if (const auto *RD = dyn_cast<CXXRecordDecl>(getDeclContext())) return RD->isLocalClass(); return dyn_cast<FunctionDecl>(getDeclContext()); @@ -1581,11 +1658,11 @@ public: const_cast<const CXXRecordDecl*>(this)->isLocalClass()); } - /// \brief Determine whether this dependent class is a current instantiation, + /// Determine whether this dependent class is a current instantiation, /// when viewed from within the given context. bool isCurrentInstantiation(const DeclContext *CurContext) const; - /// \brief Determine whether this class is derived from the class \p Base. + /// Determine whether this class is derived from the class \p Base. /// /// This routine only determines whether this class is derived from \p Base, /// but does not account for factors that may make a Derived -> Base class @@ -1597,7 +1674,7 @@ public: /// \returns true if this class is derived from Base, false otherwise. bool isDerivedFrom(const CXXRecordDecl *Base) const; - /// \brief Determine whether this class is derived from the type \p Base. + /// Determine whether this class is derived from the type \p Base. /// /// This routine only determines whether this class is derived from \p Base, /// but does not account for factors that may make a Derived -> Base class @@ -1615,7 +1692,7 @@ public: /// tangling input and output in \p Paths bool isDerivedFrom(const CXXRecordDecl *Base, CXXBasePaths &Paths) const; - /// \brief Determine whether this class is virtually derived from + /// Determine whether this class is virtually derived from /// the class \p Base. /// /// This routine only determines whether this class is virtually @@ -1630,11 +1707,11 @@ public: /// false otherwise. bool isVirtuallyDerivedFrom(const CXXRecordDecl *Base) const; - /// \brief Determine whether this class is provably not derived from + /// Determine whether this class is provably not derived from /// the type \p Base. bool isProvablyNotDerivedFrom(const CXXRecordDecl *Base) const; - /// \brief Function type used by forallBases() as a callback. + /// Function type used by forallBases() as a callback. /// /// \param BaseDefinition the definition of the base class /// @@ -1642,7 +1719,7 @@ public: using ForallBasesCallback = llvm::function_ref<bool(const CXXRecordDecl *BaseDefinition)>; - /// \brief Determines if the given callback holds for all the direct + /// Determines if the given callback holds for all the direct /// or indirect base classes of this type. /// /// The class itself does not count as a base class. This routine @@ -1658,7 +1735,7 @@ public: bool forallBases(ForallBasesCallback BaseMatches, bool AllowShortCircuit = true) const; - /// \brief Function type used by lookupInBases() to determine whether a + /// Function type used by lookupInBases() to determine whether a /// specific base class subobject matches the lookup criteria. /// /// \param Specifier the base-class specifier that describes the inheritance @@ -1672,7 +1749,7 @@ public: llvm::function_ref<bool(const CXXBaseSpecifier *Specifier, CXXBasePath &Path)>; - /// \brief Look for entities within the base classes of this C++ class, + /// Look for entities within the base classes of this C++ class, /// transitively searching all base class subobjects. /// /// This routine uses the callback function \p BaseMatches to find base @@ -1696,7 +1773,7 @@ public: bool lookupInBases(BaseMatchesCallback BaseMatches, CXXBasePaths &Paths, bool LookupInDependent = false) const; - /// \brief Base-class lookup callback that determines whether the given + /// Base-class lookup callback that determines whether the given /// base class specifier refers to a specific class declaration. /// /// This callback can be used with \c lookupInBases() to determine whether @@ -1706,7 +1783,7 @@ public: static bool FindBaseClass(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, const CXXRecordDecl *BaseRecord); - /// \brief Base-class lookup callback that determines whether the + /// Base-class lookup callback that determines whether the /// given base class specifier refers to a specific class /// declaration and describes virtual derivation. /// @@ -1719,7 +1796,7 @@ public: CXXBasePath &Path, const CXXRecordDecl *BaseRecord); - /// \brief Base-class lookup callback that determines whether there exists + /// Base-class lookup callback that determines whether there exists /// a tag with the given name. /// /// This callback can be used with \c lookupInBases() to find tag members @@ -1727,7 +1804,7 @@ public: static bool FindTagMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); - /// \brief Base-class lookup callback that determines whether there exists + /// Base-class lookup callback that determines whether there exists /// a member with the given name. /// /// This callback can be used with \c lookupInBases() to find members @@ -1735,7 +1812,7 @@ public: static bool FindOrdinaryMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); - /// \brief Base-class lookup callback that determines whether there exists + /// Base-class lookup callback that determines whether there exists /// a member with the given name. /// /// This callback can be used with \c lookupInBases() to find members @@ -1745,7 +1822,7 @@ public: FindOrdinaryMemberInDependentClasses(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); - /// \brief Base-class lookup callback that determines whether there exists + /// Base-class lookup callback that determines whether there exists /// an OpenMP declare reduction member with the given name. /// /// This callback can be used with \c lookupInBases() to find members @@ -1753,7 +1830,7 @@ public: static bool FindOMPReductionMember(const CXXBaseSpecifier *Specifier, CXXBasePath &Path, DeclarationName Name); - /// \brief Base-class lookup callback that determines whether there exists + /// Base-class lookup callback that determines whether there exists /// a member with the given name that can be used in a nested-name-specifier. /// /// This callback can be used with \c lookupInBases() to find members of @@ -1763,12 +1840,12 @@ public: CXXBasePath &Path, DeclarationName Name); - /// \brief Retrieve the final overriders for each virtual member + /// Retrieve the final overriders for each virtual member /// function in the class hierarchy where this class is the /// most-derived class in the class hierarchy. void getFinalOverriders(CXXFinalOverriderMap &FinaOverriders) const; - /// \brief Get the indirect primary bases for this class. + /// Get the indirect primary bases for this class. void getIndirectPrimaryBases(CXXIndirectPrimaryBaseSet& Bases) const; /// Performs an imprecise lookup of a dependent name in this class. @@ -1784,7 +1861,7 @@ public: /// GraphViz. void viewInheritance(ASTContext& Context) const; - /// \brief Calculates the access of a decl that is reached + /// Calculates the access of a decl that is reached /// along a path. static AccessSpecifier MergeAccess(AccessSpecifier PathAccess, AccessSpecifier DeclAccess) { @@ -1793,14 +1870,16 @@ public: return (PathAccess > DeclAccess ? PathAccess : DeclAccess); } - /// \brief Indicates that the declaration of a defaulted or deleted special + /// Indicates that the declaration of a defaulted or deleted special /// member function is now complete. void finishedDefaultedOrDeletedMember(CXXMethodDecl *MD); - /// \brief Indicates that the definition of this class is now complete. + void setTrivialForCallFlags(CXXMethodDecl *MD); + + /// Indicates that the definition of this class is now complete. void completeDefinition() override; - /// \brief Indicates that the definition of this class is now complete, + /// Indicates that the definition of this class is now complete, /// and provides a final overrider map to help determine /// /// \param FinalOverriders The final overrider map for this class, which can @@ -1809,7 +1888,7 @@ public: /// definition. void completeDefinition(CXXFinalOverriderMap *FinalOverriders); - /// \brief Determine whether this class may end up being abstract, even though + /// Determine whether this class may end up being abstract, even though /// it is not yet known to be abstract. /// /// \returns true if this class is not known to be abstract but has any @@ -1818,7 +1897,7 @@ public: /// actually abstract. bool mayBeAbstract() const; - /// \brief If this is the closure type of a lambda expression, retrieve the + /// If this is the closure type of a lambda expression, retrieve the /// number to be used for name mangling in the Itanium C++ ABI. /// /// Zero indicates that this closure type has internal linkage, so the @@ -1829,7 +1908,7 @@ public: return getLambdaData().ManglingNumber; } - /// \brief Retrieve the declaration that provides additional context for a + /// Retrieve the declaration that provides additional context for a /// lambda, when the normal declaration context is not specific enough. /// /// Certain contexts (default arguments of in-class function parameters and @@ -1840,17 +1919,17 @@ public: /// the declaration context suffices. Decl *getLambdaContextDecl() const; - /// \brief Set the mangling number and context declaration for a lambda + /// Set the mangling number and context declaration for a lambda /// class. void setLambdaMangling(unsigned ManglingNumber, Decl *ContextDecl) { getLambdaData().ManglingNumber = ManglingNumber; getLambdaData().ContextDecl = ContextDecl; } - /// \brief Returns the inheritance model used for this record. + /// Returns the inheritance model used for this record. MSInheritanceAttr::Spelling getMSInheritanceModel() const; - /// \brief Calculate what the inheritance model would be for this class. + /// Calculate what the inheritance model would be for this class. MSInheritanceAttr::Spelling calculateInheritanceModel() const; /// In the Microsoft C++ ABI, use zero for the field offset of a null data @@ -1865,11 +1944,11 @@ public: (hasDefinition() && isPolymorphic()); } - /// \brief Controls when vtordisps will be emitted if this record is used as a + /// Controls when vtordisps will be emitted if this record is used as a /// virtual base. MSVtorDispAttr::Mode getMSVtorDispMode() const; - /// \brief Determine whether this lambda expression was known to be dependent + /// Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be /// dependent. /// @@ -1888,8 +1967,8 @@ public: return getLambdaData().MethodTyInfo; } - // \brief Determine whether this type is an Interface Like type for - // __interface inheritence purposes. + // Determine whether this type is an Interface Like type for + // __interface inheritance purposes. bool isInterfaceLike() const; static bool classof(const Decl *D) { return classofKind(D->getKind()); } @@ -1898,7 +1977,7 @@ public: } }; -/// \brief Represents a C++ deduction guide declaration. +/// Represents a C++ deduction guide declaration. /// /// \code /// template<typename T> struct A { A(); A(T); }; @@ -1957,7 +2036,7 @@ public: static bool classofKind(Kind K) { return K == CXXDeductionGuide; } }; -/// \brief Represents a static or instance method of a struct/union/class. +/// Represents a static or instance method of a struct/union/class. /// /// In the terminology of the C++ Standard, these are the (static and /// non-static) member functions, whether virtual or not. @@ -2007,8 +2086,7 @@ public: bool isVolatile() const { return getType()->castAs<FunctionType>()->isVolatile(); } bool isVirtual() const { - CXXMethodDecl *CD = - cast<CXXMethodDecl>(const_cast<CXXMethodDecl*>(this)->getCanonicalDecl()); + CXXMethodDecl *CD = const_cast<CXXMethodDecl*>(this)->getCanonicalDecl(); // Member function is virtual if it is marked explicitly so, or if it is // declared in __interface -- then it is automatically pure virtual. @@ -2031,16 +2109,16 @@ public: Base, IsAppleKext); } - /// \brief Determine whether this is a usual deallocation function + /// Determine whether this is a usual deallocation function /// (C++ [basic.stc.dynamic.deallocation]p2), which is an overloaded /// delete or delete[] operator with a particular signature. bool isUsualDeallocationFunction() const; - /// \brief Determine whether this is a copy-assignment operator, regardless + /// Determine whether this is a copy-assignment operator, regardless /// of whether it was declared implicitly or explicitly. bool isCopyAssignmentOperator() const; - /// \brief Determine whether this is a move assignment operator. + /// Determine whether this is a move assignment operator. bool isMoveAssignmentOperator() const; CXXMethodDecl *getCanonicalDecl() override { @@ -2093,7 +2171,7 @@ public: cast<CXXRecordDecl>(FunctionDecl::getParent())); } - /// \brief Returns the type of the \c this pointer. + /// Returns the type of the \c this pointer. /// /// Should only be called for instance (i.e., non-static) methods. Note /// that for the call operator of a lambda closure type, this returns the @@ -2105,7 +2183,7 @@ public: return getType()->getAs<FunctionProtoType>()->getTypeQuals(); } - /// \brief Retrieve the ref-qualifier associated with this method. + /// Retrieve the ref-qualifier associated with this method. /// /// In the following example, \c f() has an lvalue ref-qualifier, \c g() /// has an rvalue ref-qualifier, and \c h() has no ref-qualifier. @@ -2122,7 +2200,7 @@ public: bool hasInlineBody() const; - /// \brief Determine whether this is a lambda closure type's static member + /// Determine whether this is a lambda closure type's static member /// function that is used for the result of the lambda's conversion to /// function pointer (for a lambda with no captures). /// @@ -2131,7 +2209,7 @@ public: /// or clone the function call operator. bool isLambdaStaticInvoker() const; - /// \brief Find the method in \p RD that corresponds to this one. + /// Find the method in \p RD that corresponds to this one. /// /// Find if \p RD or one of the classes it inherits from override this method. /// If so, return it. \p RD is assumed to be a subclass of the class defining @@ -2154,7 +2232,7 @@ public: } }; -/// \brief Represents a C++ base or member initializer. +/// Represents a C++ base or member initializer. /// /// This is part of a constructor initializer that /// initializes one non-static member variable or one base class. For @@ -2170,13 +2248,13 @@ public: /// }; /// \endcode class CXXCtorInitializer final { - /// \brief Either the base class name/delegating constructor type (stored as + /// Either the base class name/delegating constructor type (stored as /// a TypeSourceInfo*), an normal field (FieldDecl), or an anonymous field /// (IndirectFieldDecl*) being initialized. llvm::PointerUnion3<TypeSourceInfo *, FieldDecl *, IndirectFieldDecl *> Initializee; - /// \brief The source location for the field name or, for a base initializer + /// The source location for the field name or, for a base initializer /// pack expansion, the location of the ellipsis. /// /// In the case of a delegating @@ -2184,25 +2262,25 @@ class CXXCtorInitializer final { /// Initializee points to the CXXConstructorDecl (to allow loop detection). SourceLocation MemberOrEllipsisLocation; - /// \brief The argument used to initialize the base or member, which may + /// The argument used to initialize the base or member, which may /// end up constructing an object (when multiple arguments are involved). Stmt *Init; - /// \brief Location of the left paren of the ctor-initializer. + /// Location of the left paren of the ctor-initializer. SourceLocation LParenLoc; - /// \brief Location of the right paren of the ctor-initializer. + /// Location of the right paren of the ctor-initializer. SourceLocation RParenLoc; - /// \brief If the initializee is a type, whether that type makes this + /// If the initializee is a type, whether that type makes this /// a delegating initialization. unsigned IsDelegating : 1; - /// \brief If the initializer is a base initializer, this keeps track + /// If the initializer is a base initializer, this keeps track /// of whether the base is virtual or not. unsigned IsVirtual : 1; - /// \brief Whether or not the initializer is explicitly written + /// Whether or not the initializer is explicitly written /// in the sources. unsigned IsWritten : 1; @@ -2211,35 +2289,35 @@ class CXXCtorInitializer final { unsigned SourceOrder : 13; public: - /// \brief Creates a new base-class initializer. + /// Creates a new base-class initializer. explicit CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, bool IsVirtual, SourceLocation L, Expr *Init, SourceLocation R, SourceLocation EllipsisLoc); - /// \brief Creates a new member initializer. + /// Creates a new member initializer. explicit CXXCtorInitializer(ASTContext &Context, FieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); - /// \brief Creates a new anonymous field initializer. + /// Creates a new anonymous field initializer. explicit CXXCtorInitializer(ASTContext &Context, IndirectFieldDecl *Member, SourceLocation MemberLoc, SourceLocation L, Expr *Init, SourceLocation R); - /// \brief Creates a new delegating initializer. + /// Creates a new delegating initializer. explicit CXXCtorInitializer(ASTContext &Context, TypeSourceInfo *TInfo, SourceLocation L, Expr *Init, SourceLocation R); - /// \brief Determine whether this initializer is initializing a base class. + /// Determine whether this initializer is initializing a base class. bool isBaseInitializer() const { return Initializee.is<TypeSourceInfo*>() && !IsDelegating; } - /// \brief Determine whether this initializer is initializing a non-static + /// Determine whether this initializer is initializing a non-static /// data member. bool isMemberInitializer() const { return Initializee.is<FieldDecl*>(); } @@ -2251,7 +2329,7 @@ public: return Initializee.is<IndirectFieldDecl*>(); } - /// \brief Determine whether this initializer is an implicit initializer + /// Determine whether this initializer is an implicit initializer /// generated for a field with an initializer defined on the member /// declaration. /// @@ -2261,18 +2339,18 @@ public: return Init->getStmtClass() == Stmt::CXXDefaultInitExprClass; } - /// \brief Determine whether this initializer is creating a delegating + /// Determine whether this initializer is creating a delegating /// constructor. bool isDelegatingInitializer() const { return Initializee.is<TypeSourceInfo*>() && IsDelegating; } - /// \brief Determine whether this initializer is a pack expansion. + /// Determine whether this initializer is a pack expansion. bool isPackExpansion() const { return isBaseInitializer() && MemberOrEllipsisLocation.isValid(); } - // \brief For a pack expansion, returns the location of the ellipsis. + // For a pack expansion, returns the location of the ellipsis. SourceLocation getEllipsisLoc() const { assert(isPackExpansion() && "Initializer is not a pack expansion"); return MemberOrEllipsisLocation; @@ -2294,13 +2372,13 @@ public: return IsVirtual; } - /// \brief Returns the declarator information for a base class or delegating + /// Returns the declarator information for a base class or delegating /// initializer. TypeSourceInfo *getTypeSourceInfo() const { return Initializee.dyn_cast<TypeSourceInfo *>(); } - /// \brief If this is a member initializer, returns the declaration of the + /// If this is a member initializer, returns the declaration of the /// non-static data member being initialized. Otherwise, returns null. FieldDecl *getMember() const { if (isMemberInitializer()) @@ -2326,23 +2404,23 @@ public: return MemberOrEllipsisLocation; } - /// \brief Determine the source location of the initializer. + /// Determine the source location of the initializer. SourceLocation getSourceLocation() const; - /// \brief Determine the source range covering the entire initializer. + /// Determine the source range covering the entire initializer. SourceRange getSourceRange() const LLVM_READONLY; - /// \brief Determine whether this initializer is explicitly written + /// Determine whether this initializer is explicitly written /// in the source code. bool isWritten() const { return IsWritten; } - /// \brief Return the source position of the initializer, counting from 0. + /// Return the source position of the initializer, counting from 0. /// If the initializer was implicit, -1 is returned. int getSourceOrder() const { return IsWritten ? static_cast<int>(SourceOrder) : -1; } - /// \brief Set the source order of this initializer. + /// Set the source order of this initializer. /// /// This can only be called once for each initializer; it cannot be called /// on an initializer having a positive number of (implicit) array indices. @@ -2363,8 +2441,8 @@ public: SourceLocation getLParenLoc() const { return LParenLoc; } SourceLocation getRParenLoc() const { return RParenLoc; } - /// \brief Get the initializer. - Expr *getInit() const { return static_cast<Expr*>(Init); } + /// Get the initializer. + Expr *getInit() const { return static_cast<Expr *>(Init); } }; /// Description of a constructor that was inherited from a base class. @@ -2384,7 +2462,7 @@ public: CXXConstructorDecl *getConstructor() const { return BaseCtor; } }; -/// \brief Represents a C++ constructor within a class. +/// Represents a C++ constructor within a class. /// /// For example: /// @@ -2399,12 +2477,12 @@ class CXXConstructorDecl final private llvm::TrailingObjects<CXXConstructorDecl, InheritedConstructor> { /// \name Support for base and member initializers. /// \{ - /// \brief The arguments used to initialize the base or member. + /// The arguments used to initialize the base or member. LazyCXXCtorInitializersPtr CtorInitializers; unsigned NumCtorInitializers : 31; /// \} - /// \brief Whether this constructor declaration is an implicitly-declared + /// Whether this constructor declaration is an implicitly-declared /// inheriting constructor. unsigned IsInheritingConstructor : 1; @@ -2439,10 +2517,10 @@ public: bool isConstexpr, InheritedConstructor Inherited = InheritedConstructor()); - /// \brief Iterates through the member/base initializer list. + /// Iterates through the member/base initializer list. using init_iterator = CXXCtorInitializer **; - /// \brief Iterates through the member/base initializer list. + /// Iterates through the member/base initializer list. using init_const_iterator = CXXCtorInitializer *const *; using init_range = llvm::iterator_range<init_iterator>; @@ -2453,21 +2531,21 @@ public: return init_const_range(init_begin(), init_end()); } - /// \brief Retrieve an iterator to the first initializer. + /// Retrieve an iterator to the first initializer. init_iterator init_begin() { const auto *ConstThis = this; return const_cast<init_iterator>(ConstThis->init_begin()); } - /// \brief Retrieve an iterator to the first initializer. + /// Retrieve an iterator to the first initializer. init_const_iterator init_begin() const; - /// \brief Retrieve an iterator past the last initializer. + /// Retrieve an iterator past the last initializer. init_iterator init_end() { return init_begin() + NumCtorInitializers; } - /// \brief Retrieve an iterator past the last initializer. + /// Retrieve an iterator past the last initializer. init_const_iterator init_end() const { return init_begin() + NumCtorInitializers; } @@ -2490,7 +2568,7 @@ public: return init_const_reverse_iterator(init_begin()); } - /// \brief Determine the number of arguments used to initialize the member + /// Determine the number of arguments used to initialize the member /// or base. unsigned getNumCtorInitializers() const { return NumCtorInitializers; @@ -2512,13 +2590,13 @@ public: return getCanonicalDecl()->isExplicitSpecified(); } - /// \brief Determine whether this constructor is a delegating constructor. + /// Determine whether this constructor is a delegating constructor. bool isDelegatingConstructor() const { return (getNumCtorInitializers() == 1) && init_begin()[0]->isDelegatingInitializer(); } - /// \brief When this constructor delegates to another, retrieve the target. + /// When this constructor delegates to another, retrieve the target. CXXConstructorDecl *getTargetConstructor() const; /// Whether this constructor is a default @@ -2526,7 +2604,7 @@ public: /// default-initialize a class of this type. bool isDefaultConstructor() const; - /// \brief Whether this constructor is a copy constructor (C++ [class.copy]p2, + /// Whether this constructor is a copy constructor (C++ [class.copy]p2, /// which can be used to copy the class. /// /// \p TypeQuals will be set to the qualifiers on the @@ -2549,27 +2627,27 @@ public: return isCopyConstructor(TypeQuals); } - /// \brief Determine whether this constructor is a move constructor + /// Determine whether this constructor is a move constructor /// (C++11 [class.copy]p3), which can be used to move values of the class. /// /// \param TypeQuals If this constructor is a move constructor, will be set /// to the type qualifiers on the referent of the first parameter's type. bool isMoveConstructor(unsigned &TypeQuals) const; - /// \brief Determine whether this constructor is a move constructor + /// Determine whether this constructor is a move constructor /// (C++11 [class.copy]p3), which can be used to move values of the class. bool isMoveConstructor() const { unsigned TypeQuals = 0; return isMoveConstructor(TypeQuals); } - /// \brief Determine whether this is a copy or move constructor. + /// Determine whether this is a copy or move constructor. /// /// \param TypeQuals Will be set to the type qualifiers on the reference /// parameter, if in fact this is a copy or move constructor. bool isCopyOrMoveConstructor(unsigned &TypeQuals) const; - /// \brief Determine whether this a copy or move constructor. + /// Determine whether this a copy or move constructor. bool isCopyOrMoveConstructor() const { unsigned Quals; return isCopyOrMoveConstructor(Quals); @@ -2580,16 +2658,16 @@ public: /// used for user-defined conversions. bool isConvertingConstructor(bool AllowExplicit) const; - /// \brief Determine whether this is a member template specialization that + /// Determine whether this is a member template specialization that /// would copy the object to itself. Such constructors are never used to copy /// an object. bool isSpecializationCopyingObject() const; - /// \brief Determine whether this is an implicit constructor synthesized to + /// Determine whether this is an implicit constructor synthesized to /// model a call to a constructor inherited from a base class. bool isInheritingConstructor() const { return IsInheritingConstructor; } - /// \brief Get the constructor that this inheriting constructor is based on. + /// Get the constructor that this inheriting constructor is based on. InheritedConstructor getInheritedConstructor() const { return IsInheritingConstructor ? *getTrailingObjects<InheritedConstructor>() : InheritedConstructor(); @@ -2607,7 +2685,7 @@ public: static bool classofKind(Kind K) { return K == CXXConstructor; } }; -/// \brief Represents a C++ destructor within a class. +/// Represents a C++ destructor within a class. /// /// For example: /// @@ -2669,7 +2747,7 @@ public: static bool classofKind(Kind K) { return K == CXXDestructor; } }; -/// \brief Represents a C++ conversion function within a class. +/// Represents a C++ conversion function within a class. /// /// For example: /// @@ -2713,12 +2791,12 @@ public: return getCanonicalDecl()->isExplicitSpecified(); } - /// \brief Returns the type that this conversion function is converting to. + /// Returns the type that this conversion function is converting to. QualType getConversionType() const { return getType()->getAs<FunctionType>()->getReturnType(); } - /// \brief Determine whether this conversion function is a conversion from + /// Determine whether this conversion function is a conversion from /// a lambda closure type to a block pointer. bool isLambdaToBlockPointerConversion() const; @@ -2734,7 +2812,7 @@ public: static bool classofKind(Kind K) { return K == CXXConversion; } }; -/// \brief Represents a linkage specification. +/// Represents a linkage specification. /// /// For example: /// \code @@ -2744,7 +2822,7 @@ class LinkageSpecDecl : public Decl, public DeclContext { virtual void anchor(); public: - /// \brief Represents the language in a linkage specification. + /// Represents the language in a linkage specification. /// /// The values are part of the serialization ABI for /// ASTs and cannot be changed without altering that ABI. To help @@ -2756,20 +2834,20 @@ public: }; private: - /// \brief The language for this linkage specification. + /// The language for this linkage specification. unsigned Language : 3; - /// \brief True if this linkage spec has braces. + /// True if this linkage spec has braces. /// /// This is needed so that hasBraces() returns the correct result while the /// linkage spec body is being parsed. Once RBraceLoc has been set this is /// not used, so it doesn't need to be serialized. unsigned HasBraces : 1; - /// \brief The source location for the extern keyword. + /// The source location for the extern keyword. SourceLocation ExternLoc; - /// \brief The source location for the right brace (if valid). + /// The source location for the right brace (if valid). SourceLocation RBraceLoc; LinkageSpecDecl(DeclContext *DC, SourceLocation ExternLoc, @@ -2785,13 +2863,13 @@ public: bool HasBraces); static LinkageSpecDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// \brief Return the language specified by this linkage specification. + /// Return the language specified by this linkage specification. LanguageIDs getLanguage() const { return LanguageIDs(Language); } - /// \brief Set the language specified by this linkage specification. + /// Set the language specified by this linkage specification. void setLanguage(LanguageIDs L) { Language = L; } - /// \brief Determines whether this linkage specification had braces in + /// Determines whether this linkage specification had braces in /// its syntactic form. bool hasBraces() const { assert(!RBraceLoc.isValid() || HasBraces); @@ -2830,7 +2908,7 @@ public: } }; -/// \brief Represents C++ using-directive. +/// Represents C++ using-directive. /// /// For example: /// \code @@ -2841,16 +2919,16 @@ public: /// artificial names for all using-directives in order to store /// them in DeclContext effectively. class UsingDirectiveDecl : public NamedDecl { - /// \brief The location of the \c using keyword. + /// The location of the \c using keyword. SourceLocation UsingLoc; - /// \brief The location of the \c namespace keyword. + /// The location of the \c namespace keyword. SourceLocation NamespaceLoc; - /// \brief The nested-name-specifier that precedes the namespace. + /// The nested-name-specifier that precedes the namespace. NestedNameSpecifierLoc QualifierLoc; - /// \brief The namespace nominated by this using-directive. + /// The namespace nominated by this using-directive. NamedDecl *NominatedNamespace; /// Enclosing context containing both using-directive and nominated @@ -2867,7 +2945,7 @@ class UsingDirectiveDecl : public NamedDecl { NamespaceLoc(NamespcLoc), QualifierLoc(QualifierLoc), NominatedNamespace(Nominated), CommonAncestor(CommonAncestor) {} - /// \brief Returns special DeclarationName used by using-directives. + /// Returns special DeclarationName used by using-directives. /// /// This is only used by DeclContext for storing UsingDirectiveDecls in /// its lookup structure. @@ -2883,11 +2961,11 @@ public: // Friend for getUsingDirectiveName. friend class DeclContext; - /// \brief Retrieve the nested-name-specifier that qualifies the + /// Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies the + /// Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); @@ -2898,26 +2976,26 @@ public: return NominatedNamespace; } - /// \brief Returns the namespace nominated by this using-directive. + /// Returns the namespace nominated by this using-directive. NamespaceDecl *getNominatedNamespace(); const NamespaceDecl *getNominatedNamespace() const { return const_cast<UsingDirectiveDecl*>(this)->getNominatedNamespace(); } - /// \brief Returns the common ancestor context of this using-directive and + /// Returns the common ancestor context of this using-directive and /// its nominated namespace. DeclContext *getCommonAncestor() { return CommonAncestor; } const DeclContext *getCommonAncestor() const { return CommonAncestor; } - /// \brief Return the location of the \c using keyword. + /// Return the location of the \c using keyword. SourceLocation getUsingLoc() const { return UsingLoc; } // FIXME: Could omit 'Key' in name. - /// \brief Returns the location of the \c namespace keyword. + /// Returns the location of the \c namespace keyword. SourceLocation getNamespaceKeyLocation() const { return NamespaceLoc; } - /// \brief Returns the location of this using declaration's identifier. + /// Returns the location of this using declaration's identifier. SourceLocation getIdentLocation() const { return getLocation(); } static UsingDirectiveDecl *Create(ASTContext &C, DeclContext *DC, @@ -2937,7 +3015,7 @@ public: static bool classofKind(Kind K) { return K == UsingDirective; } }; -/// \brief Represents a C++ namespace alias. +/// Represents a C++ namespace alias. /// /// For example: /// @@ -2948,18 +3026,18 @@ class NamespaceAliasDecl : public NamedDecl, public Redeclarable<NamespaceAliasDecl> { friend class ASTDeclReader; - /// \brief The location of the \c namespace keyword. + /// The location of the \c namespace keyword. SourceLocation NamespaceLoc; - /// \brief The location of the namespace's identifier. + /// The location of the namespace's identifier. /// /// This is accessed by TargetNameLoc. SourceLocation IdentLoc; - /// \brief The nested-name-specifier that precedes the namespace. + /// The nested-name-specifier that precedes the namespace. NestedNameSpecifierLoc QualifierLoc; - /// \brief The Decl that this alias points to, either a NamespaceDecl or + /// The Decl that this alias points to, either a NamespaceDecl or /// a NamespaceAliasDecl. NamedDecl *Namespace; @@ -3006,26 +3084,26 @@ public: return getFirstDecl(); } - /// \brief Retrieve the nested-name-specifier that qualifies the + /// Retrieve the nested-name-specifier that qualifies the /// name of the namespace, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies the + /// Retrieve the nested-name-specifier that qualifies the /// name of the namespace. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the namespace declaration aliased by this directive. + /// Retrieve the namespace declaration aliased by this directive. NamespaceDecl *getNamespace() { - if (NamespaceAliasDecl *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) + if (auto *AD = dyn_cast<NamespaceAliasDecl>(Namespace)) return AD->getNamespace(); return cast<NamespaceDecl>(Namespace); } const NamespaceDecl *getNamespace() const { - return const_cast<NamespaceAliasDecl*>(this)->getNamespace(); + return const_cast<NamespaceAliasDecl *>(this)->getNamespace(); } /// Returns the location of the alias name, i.e. 'foo' in @@ -3038,7 +3116,7 @@ public: /// Returns the location of the identifier in the named namespace. SourceLocation getTargetNameLoc() const { return IdentLoc; } - /// \brief Retrieve the namespace that this alias refers to, which + /// Retrieve the namespace that this alias refers to, which /// may either be a NamespaceDecl or a NamespaceAliasDecl. NamedDecl *getAliasedNamespace() const { return Namespace; } @@ -3050,7 +3128,7 @@ public: static bool classofKind(Kind K) { return K == NamespaceAlias; } }; -/// \brief Represents a shadow declaration introduced into a scope by a +/// Represents a shadow declaration introduced into a scope by a /// (resolved) using declaration. /// /// For example, @@ -3069,7 +3147,7 @@ class UsingShadowDecl : public NamedDecl, public Redeclarable<UsingShadowDecl> { /// The referenced declaration. NamedDecl *Underlying = nullptr; - /// \brief The using declaration which introduced this decl or the next using + /// The using declaration which introduced this decl or the next using /// shadow declaration contained in the aforementioned using declaration. NamedDecl *UsingOrNextShadow = nullptr; @@ -3123,22 +3201,26 @@ public: return getFirstDecl(); } - /// \brief Gets the underlying declaration which has been brought into the + /// Gets the underlying declaration which has been brought into the /// local scope. NamedDecl *getTargetDecl() const { return Underlying; } - /// \brief Sets the underlying declaration which has been brought into the + /// Sets the underlying declaration which has been brought into the /// local scope. - void setTargetDecl(NamedDecl* ND) { + void setTargetDecl(NamedDecl *ND) { assert(ND && "Target decl is null!"); Underlying = ND; - IdentifierNamespace = ND->getIdentifierNamespace(); + // A UsingShadowDecl is never a friend or local extern declaration, even + // if it is a shadow declaration for one. + IdentifierNamespace = + ND->getIdentifierNamespace() & + ~(IDNS_OrdinaryFriend | IDNS_TagFriend | IDNS_LocalExtern); } - /// \brief Gets the using declaration to which this declaration is tied. + /// Gets the using declaration to which this declaration is tied. UsingDecl *getUsingDecl() const; - /// \brief The next using shadow declaration contained in the shadow decl + /// The next using shadow declaration contained in the shadow decl /// chain of the using declaration which introduced this decl. UsingShadowDecl *getNextUsingShadowDecl() const { return dyn_cast_or_null<UsingShadowDecl>(UsingOrNextShadow); @@ -3150,7 +3232,7 @@ public: } }; -/// \brief Represents a shadow constructor declaration introduced into a +/// Represents a shadow constructor declaration introduced into a /// class by a C++11 using-declaration that names a constructor. /// /// For example: @@ -3161,18 +3243,18 @@ public: /// }; /// \endcode class ConstructorUsingShadowDecl final : public UsingShadowDecl { - /// \brief If this constructor using declaration inherted the constructor + /// If this constructor using declaration inherted the constructor /// from an indirect base class, this is the ConstructorUsingShadowDecl /// in the named direct base class from which the declaration was inherited. ConstructorUsingShadowDecl *NominatedBaseClassShadowDecl = nullptr; - /// \brief If this constructor using declaration inherted the constructor + /// If this constructor using declaration inherted the constructor /// from an indirect base class, this is the ConstructorUsingShadowDecl /// that will be used to construct the unique direct or virtual base class /// that receives the constructor arguments. ConstructorUsingShadowDecl *ConstructedBaseClassShadowDecl = nullptr; - /// \brief \c true if the constructor ultimately named by this using shadow + /// \c true if the constructor ultimately named by this using shadow /// declaration is within a virtual base class subobject of the class that /// contains this declaration. unsigned IsVirtual : 1; @@ -3224,24 +3306,24 @@ public: } //@} - /// \brief Get the inheriting constructor declaration for the direct base + /// Get the inheriting constructor declaration for the direct base /// class from which this using shadow declaration was inherited, if there is /// one. This can be different for each redeclaration of the same shadow decl. ConstructorUsingShadowDecl *getNominatedBaseClassShadowDecl() const { return NominatedBaseClassShadowDecl; } - /// \brief Get the inheriting constructor declaration for the base class + /// Get the inheriting constructor declaration for the base class /// for which we don't have an explicit initializer, if there is one. ConstructorUsingShadowDecl *getConstructedBaseClassShadowDecl() const { return ConstructedBaseClassShadowDecl; } - /// \brief Get the base class that was named in the using declaration. This + /// Get the base class that was named in the using declaration. This /// can be different for each redeclaration of this same shadow decl. CXXRecordDecl *getNominatedBaseClass() const; - /// \brief Get the base class whose constructor or constructor shadow + /// Get the base class whose constructor or constructor shadow /// declaration is passed the constructor arguments. CXXRecordDecl *getConstructedBaseClass() const { return cast<CXXRecordDecl>((ConstructedBaseClassShadowDecl @@ -3250,13 +3332,13 @@ public: ->getDeclContext()); } - /// \brief Returns \c true if the constructed base class is a virtual base + /// Returns \c true if the constructed base class is a virtual base /// class subobject of this declaration's class. bool constructsVirtualBase() const { return IsVirtual; } - /// \brief Get the constructor or constructor template in the derived class + /// Get the constructor or constructor template in the derived class /// correspnding to this using shadow declaration, if it has been implicitly /// declared already. CXXConstructorDecl *getConstructor() const; @@ -3266,24 +3348,24 @@ public: static bool classofKind(Kind K) { return K == ConstructorUsingShadow; } }; -/// \brief Represents a C++ using-declaration. +/// Represents a C++ using-declaration. /// /// For example: /// \code /// using someNameSpace::someIdentifier; /// \endcode class UsingDecl : public NamedDecl, public Mergeable<UsingDecl> { - /// \brief The source location of the 'using' keyword itself. + /// The source location of the 'using' keyword itself. SourceLocation UsingLocation; - /// \brief The nested-name-specifier that precedes the name. + /// The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; - /// \brief Provides source/type location info for the declaration name + /// Provides source/type location info for the declaration name /// embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; - /// \brief The first shadow declaration of the shadow decl chain associated + /// The first shadow declaration of the shadow decl chain associated /// with this using declaration. /// /// The bool member of the pair store whether this decl has the \c typename @@ -3304,17 +3386,17 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - /// \brief Return the source location of the 'using' keyword. + /// Return the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } - /// \brief Set the source location of the 'using' keyword. + /// Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } - /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// Retrieve the nested-name-specifier that qualifies the name, /// with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies the name. + /// Retrieve the nested-name-specifier that qualifies the name. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3323,19 +3405,19 @@ public: return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } - /// \brief Return true if it is a C++03 access declaration (no 'using'). + /// Return true if it is a C++03 access declaration (no 'using'). bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } - /// \brief Return true if the using declaration has 'typename'. + /// Return true if the using declaration has 'typename'. bool hasTypename() const { return FirstUsingShadow.getInt(); } - /// \brief Sets whether the using declaration has 'typename'. + /// Sets whether the using declaration has 'typename'. void setTypename(bool TN) { FirstUsingShadow.setInt(TN); } - /// \brief Iterates through the using shadow declarations associated with + /// Iterates through the using shadow declarations associated with /// this using declaration. class shadow_iterator { - /// \brief The current using shadow declaration. + /// The current using shadow declaration. UsingShadowDecl *Current = nullptr; public: @@ -3382,7 +3464,7 @@ public: shadow_iterator shadow_end() const { return shadow_iterator(); } - /// \brief Return the number of shadowed declarations associated with this + /// Return the number of shadowed declarations associated with this /// using declaration. unsigned shadow_size() const { return std::distance(shadow_begin(), shadow_end()); @@ -3480,7 +3562,7 @@ public: static bool classofKind(Kind K) { return K == UsingPack; } }; -/// \brief Represents a dependent using declaration which was not marked with +/// Represents a dependent using declaration which was not marked with /// \c typename. /// /// Unlike non-dependent using declarations, these *only* bring through @@ -3493,16 +3575,16 @@ public: /// \endcode class UnresolvedUsingValueDecl : public ValueDecl, public Mergeable<UnresolvedUsingValueDecl> { - /// \brief The source location of the 'using' keyword + /// The source location of the 'using' keyword SourceLocation UsingLocation; - /// \brief If this is a pack expansion, the location of the '...'. + /// If this is a pack expansion, the location of the '...'. SourceLocation EllipsisLoc; - /// \brief The nested-name-specifier that precedes the name. + /// The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; - /// \brief Provides source/type location info for the declaration name + /// Provides source/type location info for the declaration name /// embedded in the ValueDecl base class. DeclarationNameLoc DNLoc; @@ -3522,20 +3604,20 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - /// \brief Returns the source location of the 'using' keyword. + /// Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return UsingLocation; } - /// \brief Set the source location of the 'using' keyword. + /// Set the source location of the 'using' keyword. void setUsingLoc(SourceLocation L) { UsingLocation = L; } - /// \brief Return true if it is a C++03 access declaration (no 'using'). + /// Return true if it is a C++03 access declaration (no 'using'). bool isAccessDeclaration() const { return UsingLocation.isInvalid(); } - /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// Retrieve the nested-name-specifier that qualifies the name, /// with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies the name. + /// Retrieve the nested-name-specifier that qualifies the name. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3544,12 +3626,12 @@ public: return DeclarationNameInfo(getDeclName(), getLocation(), DNLoc); } - /// \brief Determine whether this is a pack expansion. + /// Determine whether this is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } - /// \brief Get the location of the ellipsis if this is a pack expansion. + /// Get the location of the ellipsis if this is a pack expansion. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } @@ -3576,7 +3658,7 @@ public: static bool classofKind(Kind K) { return K == UnresolvedUsingValue; } }; -/// \brief Represents a dependent using declaration which was marked with +/// Represents a dependent using declaration which was marked with /// \c typename. /// /// \code @@ -3592,13 +3674,13 @@ class UnresolvedUsingTypenameDecl public Mergeable<UnresolvedUsingTypenameDecl> { friend class ASTDeclReader; - /// \brief The source location of the 'typename' keyword + /// The source location of the 'typename' keyword SourceLocation TypenameLocation; - /// \brief If this is a pack expansion, the location of the '...'. + /// If this is a pack expansion, the location of the '...'. SourceLocation EllipsisLoc; - /// \brief The nested-name-specifier that precedes the name. + /// The nested-name-specifier that precedes the name. NestedNameSpecifierLoc QualifierLoc; UnresolvedUsingTypenameDecl(DeclContext *DC, SourceLocation UsingLoc, @@ -3615,17 +3697,17 @@ class UnresolvedUsingTypenameDecl void anchor() override; public: - /// \brief Returns the source location of the 'using' keyword. + /// Returns the source location of the 'using' keyword. SourceLocation getUsingLoc() const { return getLocStart(); } - /// \brief Returns the source location of the 'typename' keyword. + /// Returns the source location of the 'typename' keyword. SourceLocation getTypenameLoc() const { return TypenameLocation; } - /// \brief Retrieve the nested-name-specifier that qualifies the name, + /// Retrieve the nested-name-specifier that qualifies the name, /// with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies the name. + /// Retrieve the nested-name-specifier that qualifies the name. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } @@ -3634,12 +3716,12 @@ public: return DeclarationNameInfo(getDeclName(), getLocation()); } - /// \brief Determine whether this is a pack expansion. + /// Determine whether this is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } - /// \brief Get the location of the ellipsis if this is a pack expansion. + /// Get the location of the ellipsis if this is a pack expansion. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } @@ -3665,7 +3747,7 @@ public: static bool classofKind(Kind K) { return K == UnresolvedUsingTypename; } }; -/// \brief Represents a C++11 static_assert declaration. +/// Represents a C++11 static_assert declaration. class StaticAssertDecl : public Decl { llvm::PointerIntPair<Expr *, 1, bool> AssertExprAndFailed; StringLiteral *Message; diff --git a/include/clang/AST/DeclContextInternals.h b/include/clang/AST/DeclContextInternals.h index 6545f70f70b55..ccd82d2cf0d21 100644 --- a/include/clang/AST/DeclContextInternals.h +++ b/include/clang/AST/DeclContextInternals.h @@ -30,17 +30,17 @@ namespace clang { class DependentDiagnostic; -/// \brief An array of decls optimized for the common case of only containing +/// An array of decls optimized for the common case of only containing /// one entry. struct StoredDeclsList { - /// \brief When in vector form, this is what the Data pointer points to. + /// When in vector form, this is what the Data pointer points to. using DeclsTy = SmallVector<NamedDecl *, 4>; - /// \brief A collection of declarations, with a flag to indicate if we have + /// A collection of declarations, with a flag to indicate if we have /// further external declarations. using DeclsAndHasExternalTy = llvm::PointerIntPair<DeclsTy *, 1, bool>; - /// \brief The stored data, which will be either a pointer to a NamedDecl, + /// The stored data, which will be either a pointer to a NamedDecl, /// or a pointer to a vector with a flag to indicate if there are further /// external declarations. llvm::PointerUnion<NamedDecl *, DeclsAndHasExternalTy> Data; @@ -122,7 +122,7 @@ public: == Vec.end() && "list still contains decl"); } - /// \brief Remove any declarations which were imported from an external + /// Remove any declarations which were imported from an external /// AST source. void removeExternalDecls() { if (isNull()) { diff --git a/include/clang/AST/DeclFriend.h b/include/clang/AST/DeclFriend.h index 5d1c6b86fe118..47fb68bf42d3e 100644 --- a/include/clang/AST/DeclFriend.h +++ b/include/clang/AST/DeclFriend.h @@ -148,13 +148,13 @@ public: /// Retrieves the source range for the friend declaration. SourceRange getSourceRange() const override LLVM_READONLY { if (NamedDecl *ND = getFriendDecl()) { - if (FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) + if (const auto *FD = dyn_cast<FunctionDecl>(ND)) return FD->getSourceRange(); - if (FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(ND)) + if (const auto *FTD = dyn_cast<FunctionTemplateDecl>(ND)) return FTD->getSourceRange(); - if (ClassTemplateDecl *CTD = dyn_cast<ClassTemplateDecl>(ND)) + if (const auto *CTD = dyn_cast<ClassTemplateDecl>(ND)) return CTD->getSourceRange(); - if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(ND)) { + if (const auto *DD = dyn_cast<DeclaratorDecl>(ND)) { if (DD->getOuterLocStart() != DD->getInnerLocStart()) return DD->getSourceRange(); } diff --git a/include/clang/AST/DeclLookups.h b/include/clang/AST/DeclLookups.h index 2fff055825632..64eb3f24b3701 100644 --- a/include/clang/AST/DeclLookups.h +++ b/include/clang/AST/DeclLookups.h @@ -86,16 +86,11 @@ inline DeclContext::lookups_range DeclContext::lookups() const { return lookups_range(all_lookups_iterator(), all_lookups_iterator()); } -inline DeclContext::all_lookups_iterator DeclContext::lookups_begin() const { - return lookups().begin(); -} - -inline DeclContext::all_lookups_iterator DeclContext::lookups_end() const { - return lookups().end(); -} - -inline DeclContext::lookups_range DeclContext::noload_lookups() const { +inline DeclContext::lookups_range +DeclContext::noload_lookups(bool PreserveInternalState) const { DeclContext *Primary = const_cast<DeclContext*>(this)->getPrimaryContext(); + if (!PreserveInternalState) + Primary->loadLazyLocalLexicalLookups(); if (StoredDeclsMap *Map = Primary->getLookupPtr()) return lookups_range(all_lookups_iterator(Map->begin(), Map->end()), all_lookups_iterator(Map->end(), Map->end())); @@ -105,16 +100,6 @@ inline DeclContext::lookups_range DeclContext::noload_lookups() const { return lookups_range(all_lookups_iterator(), all_lookups_iterator()); } -inline -DeclContext::all_lookups_iterator DeclContext::noload_lookups_begin() const { - return noload_lookups().begin(); -} - -inline -DeclContext::all_lookups_iterator DeclContext::noload_lookups_end() const { - return noload_lookups().end(); -} - } // namespace clang #endif // LLVM_CLANG_AST_DECLLOOKUPS_H diff --git a/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index cef7d935370a2..c81a5f805fc03 100644 --- a/include/clang/AST/DeclObjC.h +++ b/include/clang/AST/DeclObjC.h @@ -97,7 +97,7 @@ public: } }; -/// \brief A list of Objective-C protocols, along with the source +/// A list of Objective-C protocols, along with the source /// locations at which they were referenced. class ObjCProtocolList : public ObjCList<ObjCProtocolDecl> { SourceLocation *Locations = nullptr; @@ -156,10 +156,10 @@ private: // Method has a definition. unsigned IsDefined : 1; - /// \brief Method redeclaration in the same interface. + /// Method redeclaration in the same interface. unsigned IsRedeclaration : 1; - /// \brief Is redeclared in the same interface. + /// Is redeclared in the same interface. mutable unsigned HasRedeclaration : 1; // NOTE: VC++ treats enums as signed, avoid using ImplementationControl enum @@ -170,14 +170,14 @@ private: /// in, inout, etc. unsigned objcDeclQualifier : 7; - /// \brief Indicates whether this method has a related result type. + /// Indicates whether this method has a related result type. unsigned RelatedResultType : 1; - /// \brief Whether the locations of the selector identifiers are in a + /// Whether the locations of the selector identifiers are in a /// "standard" position, a enum SelectorLocationsKind. unsigned SelLocsKind : 2; - /// \brief Whether this method overrides any other in the class hierarchy. + /// Whether this method overrides any other in the class hierarchy. /// /// A method is said to override any method in the class's /// base classes, its protocols, or its categories' protocols, that has @@ -186,7 +186,7 @@ private: /// method in the interface or its categories. unsigned IsOverriding : 1; - /// \brief Indicates if the method was a definition but its body was skipped. + /// Indicates if the method was a definition but its body was skipped. unsigned HasSkippedBody : 1; // Return type of this method. @@ -195,7 +195,7 @@ private: // Type source information for the return type. TypeSourceInfo *ReturnTInfo; - /// \brief Array of ParmVarDecls for the formal parameters of this method + /// Array of ParmVarDecls for the formal parameters of this method /// and optionally followed by selector locations. void *ParamsAndSelLocs = nullptr; unsigned NumParams = 0; @@ -241,7 +241,7 @@ private: return getSelLocsKind() != SelLoc_NonStandard; } - /// \brief Get a pointer to the stored selector identifiers locations array. + /// Get a pointer to the stored selector identifiers locations array. /// No locations will be stored if HasStandardSelLocs is true. SourceLocation *getStoredSelLocs() { return reinterpret_cast<SourceLocation*>(getParams() + NumParams); @@ -250,7 +250,7 @@ private: return reinterpret_cast<const SourceLocation*>(getParams() + NumParams); } - /// \brief Get a pointer to the stored selector identifiers locations array. + /// Get a pointer to the stored selector identifiers locations array. /// No locations will be stored if HasStandardSelLocs is true. ParmVarDecl **getParams() { return reinterpret_cast<ParmVarDecl **>(ParamsAndSelLocs); @@ -259,7 +259,7 @@ private: return reinterpret_cast<const ParmVarDecl *const *>(ParamsAndSelLocs); } - /// \brief Get the number of stored selector identifiers locations. + /// Get the number of stored selector identifiers locations. /// No locations will be stored if HasStandardSelLocs is true. unsigned getNumStoredSelLocs() const { if (hasStandardSelLocs()) @@ -271,7 +271,7 @@ private: ArrayRef<ParmVarDecl*> Params, ArrayRef<SourceLocation> SelLocs); - /// \brief A definition will return its interface declaration. + /// A definition will return its interface declaration. /// An interface declaration will return its definition. /// Otherwise it will return itself. ObjCMethodDecl *getNextRedeclarationImpl() override; @@ -301,18 +301,18 @@ public: } void setObjCDeclQualifier(ObjCDeclQualifier QV) { objcDeclQualifier = QV; } - /// \brief Determine whether this method has a result type that is related + /// Determine whether this method has a result type that is related /// to the message receiver's type. bool hasRelatedResultType() const { return RelatedResultType; } - /// \brief Note whether this method has a related result type. + /// Note whether this method has a related result type. void SetRelatedResultType(bool RRT = true) { RelatedResultType = RRT; } - /// \brief True if this is a method redeclaration in the same interface. + /// True if this is a method redeclaration in the same interface. bool isRedeclaration() const { return IsRedeclaration; } void setAsRedeclaration(const ObjCMethodDecl *PrevMethod); - /// \brief Returns the location where the declarator ends. It will be + /// Returns the location where the declarator ends. It will be /// the location of ';' for a method declaration and the location of '{' /// for a method definition. SourceLocation getDeclaratorEndLoc() const { return DeclEndLoc; } @@ -362,7 +362,7 @@ public: void setReturnType(QualType T) { MethodDeclType = T; } SourceRange getReturnTypeSourceRange() const; - /// \brief Determine the type of an expression that sends a message to this + /// Determine the type of an expression that sends a message to this /// function. This replaces the type parameters with the types they would /// get if the receiver was parameterless (e.g. it may replace the type /// parameter with 'id'). @@ -407,7 +407,7 @@ public: NumParams); } - /// \brief Sets the method's parameters and selector source locations. + /// Sets the method's parameters and selector source locations. /// If the method is implicit (not coming from source) \p SelLocs is /// ignored. void setMethodParams(ASTContext &C, @@ -462,7 +462,7 @@ public: bool isDefined() const { return IsDefined; } void setDefined(bool isDefined) { IsDefined = isDefined; } - /// \brief Whether this method overrides any other in the class hierarchy. + /// Whether this method overrides any other in the class hierarchy. /// /// A method is said to override any method in the class's /// base classes, its protocols, or its categories' protocols, that has @@ -472,7 +472,7 @@ public: bool isOverriding() const { return IsOverriding; } void setOverriding(bool isOverriding) { IsOverriding = isOverriding; } - /// \brief Return overridden methods for the given \p Method. + /// Return overridden methods for the given \p Method. /// /// An ObjC method is considered to override any method in the class's /// base classes (and base's categories), its protocols, or its categories' @@ -483,11 +483,11 @@ public: void getOverriddenMethods( SmallVectorImpl<const ObjCMethodDecl *> &Overridden) const; - /// \brief True if the method was a definition but its body was skipped. + /// True if the method was a definition but its body was skipped. bool hasSkippedBody() const { return HasSkippedBody; } void setHasSkippedBody(bool Skipped = true) { HasSkippedBody = Skipped; } - /// \brief Returns the property associated with this method's selector. + /// Returns the property associated with this method's selector. /// /// Note that even if this particular method is not marked as a property /// accessor, it is still possible for it to match a property declared in a @@ -520,10 +520,10 @@ public: bool isDesignatedInitializerForTheInterface( const ObjCMethodDecl **InitMethod = nullptr) const; - /// \brief Determine whether this method has a body. + /// Determine whether this method has a body. bool hasBody() const override { return Body.isValid(); } - /// \brief Retrieve the body of this method, if it has one. + /// Retrieve the body of this method, if it has one. Stmt *getBody() const override; void setLazyBody(uint64_t Offset) { Body = Offset; } @@ -531,7 +531,7 @@ public: CompoundStmt *getCompoundBody() { return (CompoundStmt*)getBody(); } void setBody(Stmt *B) { Body = B; } - /// \brief Returns whether this specific method is a definition. + /// Returns whether this specific method is a definition. bool isThisDeclarationADefinition() const { return hasBody(); } // Implement isa/cast/dyncast/etc. @@ -737,7 +737,7 @@ enum class ObjCPropertyQueryKind : uint8_t { OBJC_PR_query_class }; -/// \brief Represents one property declaration in an Objective-C interface. +/// Represents one property declaration in an Objective-C interface. /// /// For example: /// \code{.mm} @@ -770,7 +770,7 @@ public: }; enum { - /// \brief Number of bits fitting all the property attributes. + /// Number of bits fitting all the property attributes. NumPropertyAttrsBits = 15 }; @@ -1163,7 +1163,7 @@ public: } }; -/// \brief Represents an ObjC class declaration. +/// Represents an ObjC class declaration. /// /// For example: /// @@ -1197,7 +1197,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl mutable const Type *TypeForDecl = nullptr; struct DefinitionData { - /// \brief The definition of this class, for quick access from any + /// The definition of this class, for quick access from any /// declaration. ObjCInterfaceDecl *Definition = nullptr; @@ -1210,7 +1210,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// Protocols reference in both the \@interface and class extensions. ObjCList<ObjCProtocolDecl> AllReferencedProtocols; - /// \brief List of categories and class extensions defined for this class. + /// List of categories and class extensions defined for this class. /// /// Categories are stored as a linked list in the AST, since the categories /// and class extensions come long after the initial interface declaration, @@ -1221,11 +1221,11 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// extensions and implementation. This list is built lazily. ObjCIvarDecl *IvarList = nullptr; - /// \brief Indicates that the contents of this Objective-C class will be + /// Indicates that the contents of this Objective-C class will be /// completed by the external AST source when required. mutable unsigned ExternallyCompleted : 1; - /// \brief Indicates that the ivar cache does not yet include ivars + /// Indicates that the ivar cache does not yet include ivars /// declared in the implementation. mutable unsigned IvarListMissingImplementation : 1; @@ -1248,7 +1248,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// One of the \c InheritedDesignatedInitializersState enumeratos. mutable unsigned InheritedDesignatedInitializers : 2; - /// \brief The location of the last location in this declaration, before + /// The location of the last location in this declaration, before /// the properties/methods. For example, this will be the '>', '}', or /// identifier, SourceLocation EndLoc; @@ -1262,7 +1262,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl /// The type parameters associated with this class, if any. ObjCTypeParamList *TypeParamList = nullptr; - /// \brief Contains a pointer to the data associated with this class, + /// Contains a pointer to the data associated with this class, /// which will be NULL if this class has not yet been defined. /// /// The bit indicates when we don't need to check for out-of-date @@ -1283,7 +1283,7 @@ class ObjCInterfaceDecl : public ObjCContainerDecl return *Data.getPointer(); } - /// \brief Allocate the definition data for this class. + /// Allocate the definition data for this class. void allocateDefinitionData(); using redeclarable_base = Redeclarable<ObjCInterfaceDecl>; @@ -1338,7 +1338,7 @@ public: return SourceRange(getAtStartLoc(), getLocation()); } - /// \brief Indicate that this Objective-C class is complete, but that + /// Indicate that this Objective-C class is complete, but that /// the external AST source will be responsible for filling in its contents /// when a complete class is required. void setExternallyCompleted(); @@ -1544,13 +1544,13 @@ public: isDesignatedInitializer(Selector Sel, const ObjCMethodDecl **InitMethod = nullptr) const; - /// \brief Determine whether this particular declaration of this class is + /// Determine whether this particular declaration of this class is /// actually also a definition. bool isThisDeclarationADefinition() const { return getDefinition() == this; } - /// \brief Determine whether this class has been defined. + /// Determine whether this class has been defined. bool hasDefinition() const { // If the name of this class is out-of-date, bring it up-to-date, which // might bring in a definition. @@ -1562,21 +1562,21 @@ public: return Data.getPointer(); } - /// \brief Retrieve the definition of this class, or NULL if this class + /// Retrieve the definition of this class, or NULL if this class /// has been forward-declared (with \@class) but not yet defined (with /// \@interface). ObjCInterfaceDecl *getDefinition() { return hasDefinition()? Data.getPointer()->Definition : nullptr; } - /// \brief Retrieve the definition of this class, or NULL if this class + /// Retrieve the definition of this class, or NULL if this class /// has been forward-declared (with \@class) but not yet defined (with /// \@interface). const ObjCInterfaceDecl *getDefinition() const { return hasDefinition()? Data.getPointer()->Definition : nullptr; } - /// \brief Starts the definition of this Objective-C class, taking it from + /// Starts the definition of this Objective-C class, taking it from /// a forward declaration (\@class) to a definition (\@interface). void startDefinition(); @@ -1608,7 +1608,7 @@ public: data().SuperClassTInfo = superClass; } - /// \brief Iterator that walks over the list of categories, filtering out + /// Iterator that walks over the list of categories, filtering out /// those that do not meet specific criteria. /// /// This class template is used for the various permutations of category @@ -1655,13 +1655,13 @@ public: }; private: - /// \brief Test whether the given category is visible. + /// Test whether the given category is visible. /// /// Used in the \c visible_categories_iterator. static bool isVisibleCategory(ObjCCategoryDecl *Cat); public: - /// \brief Iterator that walks over the list of categories and extensions + /// Iterator that walks over the list of categories and extensions /// that are visible, i.e., not hidden in a non-imported submodule. using visible_categories_iterator = filtered_category_iterator<isVisibleCategory>; @@ -1674,30 +1674,30 @@ public: visible_categories_end()); } - /// \brief Retrieve an iterator to the beginning of the visible-categories + /// Retrieve an iterator to the beginning of the visible-categories /// list. visible_categories_iterator visible_categories_begin() const { return visible_categories_iterator(getCategoryListRaw()); } - /// \brief Retrieve an iterator to the end of the visible-categories list. + /// Retrieve an iterator to the end of the visible-categories list. visible_categories_iterator visible_categories_end() const { return visible_categories_iterator(); } - /// \brief Determine whether the visible-categories list is empty. + /// Determine whether the visible-categories list is empty. bool visible_categories_empty() const { return visible_categories_begin() == visible_categories_end(); } private: - /// \brief Test whether the given category... is a category. + /// Test whether the given category... is a category. /// /// Used in the \c known_categories_iterator. static bool isKnownCategory(ObjCCategoryDecl *) { return true; } public: - /// \brief Iterator that walks over all of the known categories and + /// Iterator that walks over all of the known categories and /// extensions, including those that are hidden. using known_categories_iterator = filtered_category_iterator<isKnownCategory>; using known_categories_range = @@ -1708,30 +1708,30 @@ public: known_categories_end()); } - /// \brief Retrieve an iterator to the beginning of the known-categories + /// Retrieve an iterator to the beginning of the known-categories /// list. known_categories_iterator known_categories_begin() const { return known_categories_iterator(getCategoryListRaw()); } - /// \brief Retrieve an iterator to the end of the known-categories list. + /// Retrieve an iterator to the end of the known-categories list. known_categories_iterator known_categories_end() const { return known_categories_iterator(); } - /// \brief Determine whether the known-categories list is empty. + /// Determine whether the known-categories list is empty. bool known_categories_empty() const { return known_categories_begin() == known_categories_end(); } private: - /// \brief Test whether the given category is a visible extension. + /// Test whether the given category is a visible extension. /// /// Used in the \c visible_extensions_iterator. static bool isVisibleExtension(ObjCCategoryDecl *Cat); public: - /// \brief Iterator that walks over all of the visible extensions, skipping + /// Iterator that walks over all of the visible extensions, skipping /// any that are known but hidden. using visible_extensions_iterator = filtered_category_iterator<isVisibleExtension>; @@ -1744,24 +1744,24 @@ public: visible_extensions_end()); } - /// \brief Retrieve an iterator to the beginning of the visible-extensions + /// Retrieve an iterator to the beginning of the visible-extensions /// list. visible_extensions_iterator visible_extensions_begin() const { return visible_extensions_iterator(getCategoryListRaw()); } - /// \brief Retrieve an iterator to the end of the visible-extensions list. + /// Retrieve an iterator to the end of the visible-extensions list. visible_extensions_iterator visible_extensions_end() const { return visible_extensions_iterator(); } - /// \brief Determine whether the visible-extensions list is empty. + /// Determine whether the visible-extensions list is empty. bool visible_extensions_empty() const { return visible_extensions_begin() == visible_extensions_end(); } private: - /// \brief Test whether the given category is an extension. + /// Test whether the given category is an extension. /// /// Used in the \c known_extensions_iterator. static bool isKnownExtension(ObjCCategoryDecl *Cat); @@ -1771,7 +1771,7 @@ public: friend class ASTDeclWriter; friend class ASTReader; - /// \brief Iterator that walks over all of the known extensions. + /// Iterator that walks over all of the known extensions. using known_extensions_iterator = filtered_category_iterator<isKnownExtension>; using known_extensions_range = @@ -1782,23 +1782,23 @@ public: known_extensions_end()); } - /// \brief Retrieve an iterator to the beginning of the known-extensions + /// Retrieve an iterator to the beginning of the known-extensions /// list. known_extensions_iterator known_extensions_begin() const { return known_extensions_iterator(getCategoryListRaw()); } - /// \brief Retrieve an iterator to the end of the known-extensions list. + /// Retrieve an iterator to the end of the known-extensions list. known_extensions_iterator known_extensions_end() const { return known_extensions_iterator(); } - /// \brief Determine whether the known-extensions list is empty. + /// Determine whether the known-extensions list is empty. bool known_extensions_empty() const { return known_extensions_begin() == known_extensions_end(); } - /// \brief Retrieve the raw pointer to the start of the category/extension + /// Retrieve the raw pointer to the start of the category/extension /// list. ObjCCategoryDecl* getCategoryListRaw() const { // FIXME: Should make sure no callers ever do this. @@ -1811,7 +1811,7 @@ public: return data().CategoryList; } - /// \brief Set the raw pointer to the start of the category/extension + /// Set the raw pointer to the start of the category/extension /// list. void setCategoryListRaw(ObjCCategoryDecl *category) { data().CategoryList = category; @@ -1874,7 +1874,7 @@ public: ObjCInterfaceDecl *lookupInheritedClass(const IdentifierInfo *ICName); - /// \brief Lookup a method in the classes implementation hierarchy. + /// Lookup a method in the classes implementation hierarchy. ObjCMethodDecl *lookupPrivateMethod(const Selector &Sel, bool Instance=true) const; @@ -1882,7 +1882,7 @@ public: return lookupPrivateMethod(Sel, false); } - /// \brief Lookup a setter or getter in the class hierarchy, + /// Lookup a setter or getter in the class hierarchy, /// including in all categories except for category passed /// as argument. ObjCMethodDecl *lookupPropertyAccessor(const Selector Sel, @@ -1988,7 +1988,7 @@ public: static ObjCIvarDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// \brief Return the class interface that this ivar is logically contained + /// Return the class interface that this ivar is logically contained /// in; this is either the interface where the ivar was declared, or the /// interface the ivar is conceptually a part of in the case of synthesized /// ivars. @@ -2027,7 +2027,7 @@ private: unsigned Synthesized : 1; }; -/// \brief Represents a field declaration created by an \@defs(...). +/// Represents a field declaration created by an \@defs(...). class ObjCAtDefsFieldDecl : public FieldDecl { ObjCAtDefsFieldDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation IdLoc, IdentifierInfo *Id, @@ -2051,7 +2051,7 @@ public: static bool classofKind(Kind K) { return K == ObjCAtDefsField; } }; -/// \brief Represents an Objective-C protocol declaration. +/// Represents an Objective-C protocol declaration. /// /// Objective-C protocols declare a pure abstract type (i.e., no instance /// variables are permitted). Protocols originally drew inspiration from @@ -2083,14 +2083,14 @@ public: class ObjCProtocolDecl : public ObjCContainerDecl, public Redeclarable<ObjCProtocolDecl> { struct DefinitionData { - // \brief The declaration that defines this protocol. + // The declaration that defines this protocol. ObjCProtocolDecl *Definition; - /// \brief Referenced protocols + /// Referenced protocols ObjCProtocolList ReferencedProtocols; }; - /// \brief Contains a pointer to the data associated with this class, + /// Contains a pointer to the data associated with this class, /// which will be NULL if this class has not yet been defined. /// /// The bit indicates when we don't need to check for out-of-date @@ -2213,7 +2213,7 @@ public: return lookupMethod(Sel, false/*isInstance*/); } - /// \brief Determine whether this protocol has a definition. + /// Determine whether this protocol has a definition. bool hasDefinition() const { // If the name of this protocol is out-of-date, bring it up-to-date, which // might bring in a definition. @@ -2225,23 +2225,23 @@ public: return Data.getPointer(); } - /// \brief Retrieve the definition of this protocol, if any. + /// Retrieve the definition of this protocol, if any. ObjCProtocolDecl *getDefinition() { return hasDefinition()? Data.getPointer()->Definition : nullptr; } - /// \brief Retrieve the definition of this protocol, if any. + /// Retrieve the definition of this protocol, if any. const ObjCProtocolDecl *getDefinition() const { return hasDefinition()? Data.getPointer()->Definition : nullptr; } - /// \brief Determine whether this particular declaration is also the + /// Determine whether this particular declaration is also the /// definition. bool isThisDeclarationADefinition() const { return getDefinition() == this; } - /// \brief Starts the definition of this Objective-C protocol. + /// Starts the definition of this Objective-C protocol. void startDefinition(); /// Produce a name to be used for protocol's metadata. It comes either via @@ -2310,7 +2310,7 @@ class ObjCCategoryDecl : public ObjCContainerDecl { /// FIXME: this should not be a singly-linked list. Move storage elsewhere. ObjCCategoryDecl *NextClassCategory = nullptr; - /// \brief The location of the category name in this declaration. + /// The location of the category name in this declaration. SourceLocation CategoryNameLoc; /// class extension may have private ivars. @@ -2400,7 +2400,7 @@ public: ObjCCategoryDecl *getNextClassCategory() const { return NextClassCategory; } - /// \brief Retrieve the pointer to the next stored category (or extension), + /// Retrieve the pointer to the next stored category (or extension), /// which may be hidden. ObjCCategoryDecl *getNextClassCategoryRaw() const { return NextClassCategory; @@ -2578,7 +2578,7 @@ class ObjCImplementationDecl : public ObjCImplDecl { SourceLocation IvarRBraceLoc; /// Support for ivar initialization. - /// \brief The arguments used to initialize the ivars + /// The arguments used to initialize the ivars LazyCXXCtorInitializersPtr IvarInitializers; unsigned NumIvarInitializers = 0; @@ -2694,7 +2694,7 @@ public: return getIdentifier()->getName(); } - /// @brief Get the name of the class associated with this interface. + /// Get the name of the class associated with this interface. // // FIXME: Move to StringRef API. std::string getNameAsString() const { @@ -2785,7 +2785,7 @@ public: private: SourceLocation AtLoc; // location of \@synthesize or \@dynamic - /// \brief For \@synthesize, the location of the ivar, if it was written in + /// For \@synthesize, the location of the ivar, if it was written in /// the source code. /// /// \code @@ -2854,7 +2854,7 @@ public: this->IvarLoc = IvarLoc; } - /// \brief For \@synthesize, returns true if an ivar name was explicitly + /// For \@synthesize, returns true if an ivar name was explicitly /// specified. /// /// \code diff --git a/include/clang/AST/DeclOpenMP.h b/include/clang/AST/DeclOpenMP.h index 2a329c3732cb6..bec3acffc4332 100644 --- a/include/clang/AST/DeclOpenMP.h +++ b/include/clang/AST/DeclOpenMP.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines OpenMP nodes for declarative directives. +/// This file defines OpenMP nodes for declarative directives. /// //===----------------------------------------------------------------------===// @@ -24,7 +24,7 @@ namespace clang { -/// \brief This represents '#pragma omp threadprivate ...' directive. +/// This represents '#pragma omp threadprivate ...' directive. /// For example, in the following, both 'a' and 'A::b' are threadprivate: /// /// \code @@ -89,7 +89,7 @@ public: static bool classofKind(Kind K) { return K == OMPThreadPrivate; } }; -/// \brief This represents '#pragma omp declare reduction ...' directive. +/// This represents '#pragma omp declare reduction ...' directive. /// For example, in the following, declared reduction 'foo' for types 'int' and /// 'float': /// @@ -109,14 +109,14 @@ public: private: friend class ASTDeclReader; - /// \brief Combiner for declare reduction construct. + /// Combiner for declare reduction construct. Expr *Combiner; - /// \brief Initializer for declare reduction construct. + /// Initializer for declare reduction construct. Expr *Initializer; /// Kind of initializer - function call or omp_priv<init_expr> initializtion. InitKind InitializerKind = CallInit; - /// \brief Reference to the previous declare reduction construct in the same + /// Reference to the previous declare reduction construct in the same /// scope with the same name. Required for proper templates instantiation if /// the declare reduction construct is declared inside compound statement. LazyDeclPtr PrevDeclInScope; @@ -135,33 +135,33 @@ private: } public: - /// \brief Create declare reduction node. + /// Create declare reduction node. static OMPDeclareReductionDecl * Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, QualType T, OMPDeclareReductionDecl *PrevDeclInScope); - /// \brief Create deserialized declare reduction node. + /// Create deserialized declare reduction node. static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// \brief Get combiner expression of the declare reduction construct. + /// Get combiner expression of the declare reduction construct. Expr *getCombiner() { return Combiner; } const Expr *getCombiner() const { return Combiner; } - /// \brief Set combiner expression for the declare reduction construct. + /// Set combiner expression for the declare reduction construct. void setCombiner(Expr *E) { Combiner = E; } - /// \brief Get initializer expression (if specified) of the declare reduction + /// Get initializer expression (if specified) of the declare reduction /// construct. Expr *getInitializer() { return Initializer; } const Expr *getInitializer() const { return Initializer; } /// Get initializer kind. InitKind getInitializerKind() const { return InitializerKind; } - /// \brief Set initializer expression for the declare reduction construct. + /// Set initializer expression for the declare reduction construct. void setInitializer(Expr *E, InitKind IK) { Initializer = E; InitializerKind = IK; } - /// \brief Get reference to previous declare reduction construct in the same + /// Get reference to previous declare reduction construct in the same /// scope with the same name. OMPDeclareReductionDecl *getPrevDeclInScope(); const OMPDeclareReductionDecl *getPrevDeclInScope() const; @@ -189,9 +189,10 @@ class OMPCapturedExprDecl final : public VarDecl { void anchor() override; OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, - QualType Type, SourceLocation StartLoc) - : VarDecl(OMPCapturedExpr, C, DC, StartLoc, SourceLocation(), Id, Type, - nullptr, SC_None) { + QualType Type, TypeSourceInfo *TInfo, + SourceLocation StartLoc) + : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo, + SC_None) { setImplicit(); } diff --git a/include/clang/AST/DeclTemplate.h b/include/clang/AST/DeclTemplate.h index 7842d70971747..a2f00ec9ffa22 100644 --- a/include/clang/AST/DeclTemplate.h +++ b/include/clang/AST/DeclTemplate.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the C++ template declaration subclasses. +/// Defines the C++ template declaration subclasses. // //===----------------------------------------------------------------------===// @@ -56,14 +56,14 @@ class UnresolvedSetImpl; class VarTemplateDecl; class VarTemplatePartialSpecializationDecl; -/// \brief Stores a template parameter of any kind. +/// Stores a template parameter of any kind. using TemplateParameter = llvm::PointerUnion3<TemplateTypeParmDecl *, NonTypeTemplateParmDecl *, TemplateTemplateParmDecl *>; NamedDecl *getAsNamedDecl(TemplateParameter P); -/// \brief Stores a list of template parameters for a TemplateDecl and its +/// Stores a list of template parameters for a TemplateDecl and its /// derived classes. class TemplateParameterList final : private llvm::TrailingObjects<TemplateParameterList, NamedDecl *, @@ -110,10 +110,10 @@ public: SourceLocation RAngleLoc, Expr *RequiresClause); - /// \brief Iterates through the template parameters in this list. + /// Iterates through the template parameters in this list. using iterator = NamedDecl **; - /// \brief Iterates through the template parameters in this list. + /// Iterates through the template parameters in this list. using const_iterator = NamedDecl * const *; iterator begin() { return getTrailingObjects<NamedDecl *>(); } @@ -139,32 +139,32 @@ public: return begin()[Idx]; } - /// \brief Returns the minimum number of arguments needed to form a + /// Returns the minimum number of arguments needed to form a /// template specialization. /// /// This may be fewer than the number of template parameters, if some of /// the parameters have default arguments or if there is a parameter pack. unsigned getMinRequiredArguments() const; - /// \brief Get the depth of this template parameter list in the set of + /// Get the depth of this template parameter list in the set of /// template parameter lists. /// /// The first template parameter list in a declaration will have depth 0, /// the second template parameter list will have depth 1, etc. unsigned getDepth() const; - /// \brief Determine whether this template parameter list contains an + /// Determine whether this template parameter list contains an /// unexpanded parameter pack. bool containsUnexpandedParameterPack() const { return ContainsUnexpandedParameterPack; } - /// \brief The constraint-expression of the associated requires-clause. + /// The constraint-expression of the associated requires-clause. Expr *getRequiresClause() { return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr; } - /// \brief The constraint-expression of the associated requires-clause. + /// The constraint-expression of the associated requires-clause. const Expr *getRequiresClause() const { return HasRequiresClause ? *getTrailingObjects<Expr *>() : nullptr; } @@ -182,7 +182,7 @@ public: using FixedSizeStorageOwner = TrailingObjects::FixedSizeStorageOwner; }; -/// \brief Stores a list of template parameters and the associated +/// Stores a list of template parameters and the associated /// requires-clause (if any) for a TemplateDecl and its derived classes. /// Suitable for creating on the stack. template <size_t N, bool HasRequiresClause> @@ -206,13 +206,13 @@ public: TemplateLoc, LAngleLoc, Params, RAngleLoc, RequiresClause))) {} }; -/// \brief A template argument list. +/// A template argument list. class TemplateArgumentList final : private llvm::TrailingObjects<TemplateArgumentList, TemplateArgument> { - /// \brief The template argument list. + /// The template argument list. const TemplateArgument *Arguments; - /// \brief The number of template arguments in this template + /// The number of template arguments in this template /// argument list. unsigned NumArguments; @@ -226,23 +226,23 @@ public: TemplateArgumentList(const TemplateArgumentList &) = delete; TemplateArgumentList &operator=(const TemplateArgumentList &) = delete; - /// \brief Type used to indicate that the template argument list itself is a + /// Type used to indicate that the template argument list itself is a /// stack object. It does not own its template arguments. enum OnStackType { OnStack }; - /// \brief Create a new template argument list that copies the given set of + /// Create a new template argument list that copies the given set of /// template arguments. static TemplateArgumentList *CreateCopy(ASTContext &Context, ArrayRef<TemplateArgument> Args); - /// \brief Construct a new, temporary template argument list on the stack. + /// Construct a new, temporary template argument list on the stack. /// /// The template argument list does not own the template arguments /// provided. explicit TemplateArgumentList(OnStackType, ArrayRef<TemplateArgument> Args) : Arguments(Args.data()), NumArguments(Args.size()) {} - /// \brief Produces a shallow copy of the given template argument list. + /// Produces a shallow copy of the given template argument list. /// /// This operation assumes that the input argument list outlives it. /// This takes the list as a pointer to avoid looking like a copy @@ -251,25 +251,25 @@ public: explicit TemplateArgumentList(const TemplateArgumentList *Other) : Arguments(Other->data()), NumArguments(Other->size()) {} - /// \brief Retrieve the template argument at a given index. + /// Retrieve the template argument at a given index. const TemplateArgument &get(unsigned Idx) const { assert(Idx < NumArguments && "Invalid template argument index"); return data()[Idx]; } - /// \brief Retrieve the template argument at a given index. + /// Retrieve the template argument at a given index. const TemplateArgument &operator[](unsigned Idx) const { return get(Idx); } - /// \brief Produce this as an array ref. + /// Produce this as an array ref. ArrayRef<TemplateArgument> asArray() const { return llvm::makeArrayRef(data(), size()); } - /// \brief Retrieve the number of template arguments in this + /// Retrieve the number of template arguments in this /// template argument list. unsigned size() const { return NumArguments; } - /// \brief Retrieve a pointer to the template argument list. + /// Retrieve a pointer to the template argument list. const TemplateArgument *data() const { return Arguments; } }; @@ -299,7 +299,7 @@ class DefaultArgStorage { static ParmDecl *getParmOwningDefaultArg(ParmDecl *Parm) { const DefaultArgStorage &Storage = Parm->getDefaultArgStorage(); - if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl*>()) + if (auto *Prev = Storage.ValueOrInherited.template dyn_cast<ParmDecl *>()) Parm = Prev; assert(!Parm->getDefaultArgStorage() .ValueOrInherited.template is<ParmDecl *>() && @@ -321,9 +321,9 @@ public: /// default argument is visible. ArgType get() const { const DefaultArgStorage *Storage = this; - if (auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl*>()) + if (const auto *Prev = ValueOrInherited.template dyn_cast<ParmDecl *>()) Storage = &Prev->getDefaultArgStorage(); - if (auto *C = Storage->ValueOrInherited.template dyn_cast<Chain*>()) + if (const auto *C = Storage->ValueOrInherited.template dyn_cast<Chain *>()) return C->Value; return Storage->ValueOrInherited.template get<ArgType>(); } @@ -331,9 +331,9 @@ public: /// Get the parameter from which we inherit the default argument, if any. /// This is the parameter on which the default argument was actually written. const ParmDecl *getInheritedFrom() const { - if (auto *D = ValueOrInherited.template dyn_cast<ParmDecl*>()) + if (const auto *D = ValueOrInherited.template dyn_cast<ParmDecl *>()) return D; - if (auto *C = ValueOrInherited.template dyn_cast<Chain*>()) + if (const auto *C = ValueOrInherited.template dyn_cast<Chain *>()) return C->PrevDeclWithDefaultArg; return nullptr; } @@ -365,7 +365,7 @@ public: // Kinds of Templates //===----------------------------------------------------------------------===// -/// \brief Stores the template parameter list and associated constraints for +/// Stores the template parameter list and associated constraints for /// \c TemplateDecl objects that track associated constraints. class ConstrainedTemplateDeclInfo { friend TemplateDecl; @@ -391,7 +391,7 @@ protected: }; -/// \brief The base class of all kinds of template declarations (e.g., +/// The base class of all kinds of template declarations (e.g., /// class, function, etc.). /// /// The TemplateDecl class stores the list of template parameters and a @@ -443,7 +443,7 @@ public: } Expr *getAssociatedConstraints() const { - const TemplateDecl *const C = cast<TemplateDecl>(getCanonicalDecl()); + const auto *const C = cast<TemplateDecl>(getCanonicalDecl()); const auto *const CTDI = C->TemplateParams.dyn_cast<ConstrainedTemplateDeclInfo *>(); return CTDI ? CTDI->getAssociatedConstraints() : nullptr; @@ -466,7 +466,8 @@ public: protected: NamedDecl *TemplatedDecl; - /// \brief The template parameter list and optional requires-clause + + /// The template parameter list and optional requires-clause /// associated with this declaration; alternatively, a /// \c ConstrainedTemplateDeclInfo if the associated constraints of the /// template are being tracked by this particular declaration. @@ -491,7 +492,7 @@ protected: } public: - /// \brief Initialize the underlying templated declaration and + /// Initialize the underlying templated declaration and /// template parameters. void init(NamedDecl *templatedDecl, TemplateParameterList* templateParams) { assert(!TemplatedDecl && "TemplatedDecl already set!"); @@ -501,7 +502,7 @@ public: } }; -/// \brief Provides information about a function template specialization, +/// Provides information about a function template specialization, /// which is a FunctionDecl that has been explicitly specialization or /// instantiated from a function template. class FunctionTemplateSpecializationInfo : public llvm::FoldingSetNode { @@ -524,31 +525,31 @@ public: const TemplateArgumentListInfo *TemplateArgsAsWritten, SourceLocation POI); - /// \brief The function template specialization that this structure + /// The function template specialization that this structure /// describes. FunctionDecl *Function; - /// \brief The function template from which this function template + /// The function template from which this function template /// specialization was generated. /// /// The two bits contain the top 4 values of TemplateSpecializationKind. llvm::PointerIntPair<FunctionTemplateDecl *, 2> Template; - /// \brief The template arguments used to produce the function template + /// The template arguments used to produce the function template /// specialization from the function template. const TemplateArgumentList *TemplateArguments; - /// \brief The template arguments as written in the sources, if provided. + /// The template arguments as written in the sources, if provided. const ASTTemplateArgumentListInfo *TemplateArgumentsAsWritten; - /// \brief The point at which this function template specialization was + /// The point at which this function template specialization was /// first instantiated. SourceLocation PointOfInstantiation; - /// \brief Retrieve the template from which this function was specialized. + /// Retrieve the template from which this function was specialized. FunctionTemplateDecl *getTemplate() const { return Template.getPointer(); } - /// \brief Determine what kind of template specialization this is. + /// Determine what kind of template specialization this is. TemplateSpecializationKind getTemplateSpecializationKind() const { return (TemplateSpecializationKind)(Template.getInt() + 1); } @@ -557,7 +558,7 @@ public: return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; } - /// \brief True if this declaration is an explicit specialization, + /// True if this declaration is an explicit specialization, /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { @@ -565,14 +566,14 @@ public: getTemplateSpecializationKind()); } - /// \brief Set the template specialization kind. + /// Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(TSK != TSK_Undeclared && "Cannot encode TSK_Undeclared for a function template specialization"); Template.setInt(TSK - 1); } - /// \brief Retrieve the first point of instantiation of this function + /// Retrieve the first point of instantiation of this function /// template specialization. /// /// The point of instantiation may be an invalid source location if this @@ -581,7 +582,7 @@ public: return PointOfInstantiation; } - /// \brief Set the (first) point of instantiation of this function template + /// Set the (first) point of instantiation of this function template /// specialization. void setPointOfInstantiation(SourceLocation POI) { PointOfInstantiation = POI; @@ -601,7 +602,7 @@ public: } }; -/// \brief Provides information a specialization of a member of a class +/// Provides information a specialization of a member of a class /// template, which may be a member function, static data member, /// member class or member enumeration. class MemberSpecializationInfo { @@ -621,11 +622,11 @@ public: "Cannot encode undeclared template specializations for members"); } - /// \brief Retrieve the member declaration from which this member was + /// Retrieve the member declaration from which this member was /// instantiated. NamedDecl *getInstantiatedFrom() const { return MemberAndTSK.getPointer(); } - /// \brief Determine what kind of template specialization this is. + /// Determine what kind of template specialization this is. TemplateSpecializationKind getTemplateSpecializationKind() const { return (TemplateSpecializationKind)(MemberAndTSK.getInt() + 1); } @@ -634,27 +635,27 @@ public: return getTemplateSpecializationKind() == TSK_ExplicitSpecialization; } - /// \brief Set the template specialization kind. + /// Set the template specialization kind. void setTemplateSpecializationKind(TemplateSpecializationKind TSK) { assert(TSK != TSK_Undeclared && "Cannot encode undeclared template specializations for members"); MemberAndTSK.setInt(TSK - 1); } - /// \brief Retrieve the first point of instantiation of this member. + /// Retrieve the first point of instantiation of this member. /// If the point of instantiation is an invalid location, then this member /// has not yet been instantiated. SourceLocation getPointOfInstantiation() const { return PointOfInstantiation; } - /// \brief Set the first point of instantiation. + /// Set the first point of instantiation. void setPointOfInstantiation(SourceLocation POI) { PointOfInstantiation = POI; } }; -/// \brief Provides information about a dependent function-template +/// Provides information about a dependent function-template /// specialization declaration. /// /// Since explicit function template specialization and instantiation @@ -699,25 +700,25 @@ public: Create(ASTContext &Context, const UnresolvedSetImpl &Templates, const TemplateArgumentListInfo &TemplateArgs); - /// \brief Returns the number of function templates that this might + /// Returns the number of function templates that this might /// be a specialization of. unsigned getNumTemplates() const { return NumTemplates; } - /// \brief Returns the i'th template candidate. + /// Returns the i'th template candidate. FunctionTemplateDecl *getTemplate(unsigned I) const { assert(I < getNumTemplates() && "template index out of range"); return getTrailingObjects<FunctionTemplateDecl *>()[I]; } - /// \brief Returns the explicit template arguments that were given. + /// Returns the explicit template arguments that were given. const TemplateArgumentLoc *getTemplateArgs() const { return getTrailingObjects<TemplateArgumentLoc>(); } - /// \brief Returns the number of explicit template arguments that were given. + /// Returns the number of explicit template arguments that were given. unsigned getNumTemplateArgs() const { return NumArgs; } - /// \brief Returns the nth template argument. + /// Returns the nth template argument. const TemplateArgumentLoc &getTemplateArg(unsigned I) const { assert(I < getNumTemplateArgs() && "template arg index out of range"); return getTemplateArgs()[I]; @@ -803,7 +804,7 @@ protected: struct CommonBase { CommonBase() : InstantiatedFromMember(nullptr, false) {} - /// \brief The template from which this was most + /// The template from which this was most /// directly instantiated (or null). /// /// The boolean value indicates whether this template @@ -811,7 +812,7 @@ protected: llvm::PointerIntPair<RedeclarableTemplateDecl*, 1, bool> InstantiatedFromMember; - /// \brief If non-null, points to an array of specializations (including + /// If non-null, points to an array of specializations (including /// partial specializations) known only by their external declaration IDs. /// /// The first value in the array is the number of specializations/partial @@ -819,11 +820,11 @@ protected: uint32_t *LazySpecializations = nullptr; }; - /// \brief Pointer to the common data shared by all declarations of this + /// Pointer to the common data shared by all declarations of this /// template. mutable CommonBase *Common = nullptr; - /// \brief Retrieves the "common" pointer shared by all (re-)declarations of + /// Retrieves the "common" pointer shared by all (re-)declarations of /// the same template. Calling this routine may implicitly allocate memory /// for the common pointer. CommonBase *getCommonPtr() const; @@ -849,7 +850,7 @@ public: friend class ASTReader; template <class decl_type> friend class RedeclarableTemplate; - /// \brief Retrieves the canonical declaration of this template. + /// Retrieves the canonical declaration of this template. RedeclarableTemplateDecl *getCanonicalDecl() override { return getFirstDecl(); } @@ -857,7 +858,7 @@ public: return getFirstDecl(); } - /// \brief Determines whether this template was a specialization of a + /// Determines whether this template was a specialization of a /// member template. /// /// In the following example, the function template \c X<int>::f and the @@ -879,14 +880,14 @@ public: return getCommonPtr()->InstantiatedFromMember.getInt(); } - /// \brief Note that this member template is a specialization. + /// Note that this member template is a specialization. void setMemberSpecialization() { assert(getCommonPtr()->InstantiatedFromMember.getPointer() && "Only member templates can be member template specializations"); getCommonPtr()->InstantiatedFromMember.setInt(true); } - /// \brief Retrieve the member template from which this template was + /// Retrieve the member template from which this template was /// instantiated, or nullptr if this template was not instantiated from a /// member template. /// @@ -968,14 +969,14 @@ class FunctionTemplateDecl : public RedeclarableTemplateDecl { protected: friend class FunctionDecl; - /// \brief Data that is common to all of the declarations of a given + /// Data that is common to all of the declarations of a given /// function template. struct Common : CommonBase { - /// \brief The function template specializations for this function + /// The function template specializations for this function /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> Specializations; - /// \brief The set of "injected" template arguments used within this + /// The set of "injected" template arguments used within this /// function template. /// /// This pointer refers to the template arguments (there are as @@ -999,12 +1000,12 @@ protected: return static_cast<Common *>(RedeclarableTemplateDecl::getCommonPtr()); } - /// \brief Retrieve the set of function template specializations of this + /// Retrieve the set of function template specializations of this /// function template. llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> & getSpecializations() const; - /// \brief Add a specialization of this function template. + /// Add a specialization of this function template. /// /// \param InsertPos Insert position in the FoldingSetVector, must have been /// retrieved by an earlier call to findSpecialization(). @@ -1015,7 +1016,7 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - /// \brief Load any lazily-loaded specializations from the external source. + /// Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; /// Get the underlying function declaration of the template. @@ -1029,7 +1030,7 @@ public: return getTemplatedDecl()->isThisDeclarationADefinition(); } - /// \brief Return the specialization with the provided arguments if it exists, + /// Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. FunctionDecl *findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); @@ -1043,7 +1044,7 @@ public: RedeclarableTemplateDecl::getCanonicalDecl()); } - /// \brief Retrieve the previous declaration of this function template, or + /// Retrieve the previous declaration of this function template, or /// nullptr if no such declaration exists. FunctionTemplateDecl *getPreviousDecl() { return cast_or_null<FunctionTemplateDecl>( @@ -1083,7 +1084,7 @@ public: return makeSpecIterator(getSpecializations(), true); } - /// \brief Retrieve the "injected" template arguments that correspond to the + /// Retrieve the "injected" template arguments that correspond to the /// template parameters of this function template. /// /// Although the C++ standard has no notion of the "injected" template @@ -1092,14 +1093,14 @@ public: /// template. ArrayRef<TemplateArgument> getInjectedTemplateArgs(); - /// \brief Create a function template node. + /// Create a function template node. static FunctionTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl); - /// \brief Create an empty function template node. + /// Create an empty function template node. static FunctionTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast support @@ -1111,7 +1112,7 @@ public: // Kinds of Template Parameters //===----------------------------------------------------------------------===// -/// \brief Defines the position of a template parameter within a template +/// Defines the position of a template parameter within a template /// parameter list. /// /// Because template parameter can be listed @@ -1144,7 +1145,7 @@ public: unsigned getIndex() const { return Position; } }; -/// \brief Declaration of a template type parameter. +/// Declaration of a template type parameter. /// /// For example, "T" in /// \code @@ -1154,13 +1155,13 @@ class TemplateTypeParmDecl : public TypeDecl { /// Sema creates these on the stack during auto type deduction. friend class Sema; - /// \brief Whether this template type parameter was declaration with + /// Whether this template type parameter was declaration with /// the 'typename' keyword. /// /// If false, it was declared with the 'class' keyword. bool Typename : 1; - /// \brief The default template argument, if any. + /// The default template argument, if any. using DefArgStorage = DefaultArgStorage<TemplateTypeParmDecl, TypeSourceInfo *>; DefArgStorage DefaultArgument; @@ -1180,7 +1181,7 @@ public: static TemplateTypeParmDecl *CreateDeserialized(const ASTContext &C, unsigned ID); - /// \brief Whether this template type parameter was declared with + /// Whether this template type parameter was declared with /// the 'typename' keyword. /// /// If not, it was declared with the 'class' keyword. @@ -1188,57 +1189,57 @@ public: const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } - /// \brief Determine whether this template parameter has a default + /// Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument.isSet(); } - /// \brief Retrieve the default argument, if any. + /// Retrieve the default argument, if any. QualType getDefaultArgument() const { return DefaultArgument.get()->getType(); } - /// \brief Retrieves the default argument's source information, if any. + /// Retrieves the default argument's source information, if any. TypeSourceInfo *getDefaultArgumentInfo() const { return DefaultArgument.get(); } - /// \brief Retrieves the location of the default argument declaration. + /// Retrieves the location of the default argument declaration. SourceLocation getDefaultArgumentLoc() const; - /// \brief Determines whether the default argument was inherited + /// Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { return DefaultArgument.isInherited(); } - /// \brief Set the default argument for this template parameter. + /// Set the default argument for this template parameter. void setDefaultArgument(TypeSourceInfo *DefArg) { DefaultArgument.set(DefArg); } - /// \brief Set that this default argument was inherited from another + /// Set that this default argument was inherited from another /// parameter. void setInheritedDefaultArgument(const ASTContext &C, TemplateTypeParmDecl *Prev) { DefaultArgument.setInherited(C, Prev); } - /// \brief Removes the default argument of this template parameter. + /// Removes the default argument of this template parameter. void removeDefaultArgument() { DefaultArgument.clear(); } - /// \brief Set whether this template type parameter was declared with + /// Set whether this template type parameter was declared with /// the 'typename' or 'class' keyword. void setDeclaredWithTypename(bool withTypename) { Typename = withTypename; } - /// \brief Retrieve the depth of the template parameter. + /// Retrieve the depth of the template parameter. unsigned getDepth() const; - /// \brief Retrieve the index of the template parameter. + /// Retrieve the index of the template parameter. unsigned getIndex() const; - /// \brief Returns whether this is a parameter pack. + /// Returns whether this is a parameter pack. bool isParameterPack() const; SourceRange getSourceRange() const override LLVM_READONLY; @@ -1261,7 +1262,7 @@ class NonTypeTemplateParmDecl final friend class ASTDeclReader; friend TrailingObjects; - /// \brief The default template argument, if any, and whether or not + /// The default template argument, if any, and whether or not /// it was inherited. using DefArgStorage = DefaultArgStorage<NonTypeTemplateParmDecl, Expr *>; DefArgStorage DefaultArgument; @@ -1269,15 +1270,15 @@ class NonTypeTemplateParmDecl final // FIXME: Collapse this into TemplateParamPosition; or, just move depth/index // down here to save memory. - /// \brief Whether this non-type template parameter is a parameter pack. + /// Whether this non-type template parameter is a parameter pack. bool ParameterPack; - /// \brief Whether this non-type template parameter is an "expanded" + /// Whether this non-type template parameter is an "expanded" /// parameter pack, meaning that its type is a pack expansion and we /// already know the set of types that expansion expands to. bool ExpandedParameterPack = false; - /// \brief The number of types in an expanded parameter pack. + /// The number of types in an expanded parameter pack. unsigned NumExpandedTypes = 0; size_t numTrailingObjects( @@ -1327,23 +1328,23 @@ public: const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } - /// \brief Determine whether this template parameter has a default + /// Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument.isSet(); } - /// \brief Retrieve the default argument, if any. + /// Retrieve the default argument, if any. Expr *getDefaultArgument() const { return DefaultArgument.get(); } - /// \brief Retrieve the location of the default argument, if any. + /// Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; - /// \brief Determines whether the default argument was inherited + /// Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { return DefaultArgument.isInherited(); } - /// \brief Set the default argument for this template parameter, and + /// Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. void setDefaultArgument(Expr *DefArg) { DefaultArgument.set(DefArg); } @@ -1352,10 +1353,10 @@ public: DefaultArgument.setInherited(C, Parm); } - /// \brief Removes the default argument of this template parameter. + /// Removes the default argument of this template parameter. void removeDefaultArgument() { DefaultArgument.clear(); } - /// \brief Whether this parameter is a non-type template parameter pack. + /// Whether this parameter is a non-type template parameter pack. /// /// If the parameter is a parameter pack, the type may be a /// \c PackExpansionType. In the following example, the \c Dims parameter @@ -1366,7 +1367,7 @@ public: /// \endcode bool isParameterPack() const { return ParameterPack; } - /// \brief Whether this parameter pack is a pack expansion. + /// Whether this parameter pack is a pack expansion. /// /// A non-type template parameter pack is a pack expansion if its type /// contains an unexpanded parameter pack. In this case, we will have @@ -1375,7 +1376,7 @@ public: return ParameterPack && getType()->getAs<PackExpansionType>(); } - /// \brief Whether this parameter is a non-type template parameter pack + /// Whether this parameter is a non-type template parameter pack /// that has a known list of different types at different positions. /// /// A parameter pack is an expanded parameter pack when the original @@ -1401,14 +1402,14 @@ public: /// return the expansion types. bool isExpandedParameterPack() const { return ExpandedParameterPack; } - /// \brief Retrieves the number of expansion types in an expanded parameter + /// Retrieves the number of expansion types in an expanded parameter /// pack. unsigned getNumExpansionTypes() const { assert(ExpandedParameterPack && "Not an expansion parameter pack"); return NumExpandedTypes; } - /// \brief Retrieve a particular expansion type within an expanded parameter + /// Retrieve a particular expansion type within an expanded parameter /// pack. QualType getExpansionType(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); @@ -1417,7 +1418,7 @@ public: return TypesAndInfos[I].first; } - /// \brief Retrieve a particular expansion type source info within an + /// Retrieve a particular expansion type source info within an /// expanded parameter pack. TypeSourceInfo *getExpansionTypeSourceInfo(unsigned I) const { assert(I < NumExpandedTypes && "Out-of-range expansion type index"); @@ -1443,20 +1444,20 @@ class TemplateTemplateParmDecl final protected TemplateParmPosition, private llvm::TrailingObjects<TemplateTemplateParmDecl, TemplateParameterList *> { - /// \brief The default template argument, if any. + /// The default template argument, if any. using DefArgStorage = DefaultArgStorage<TemplateTemplateParmDecl, TemplateArgumentLoc *>; DefArgStorage DefaultArgument; - /// \brief Whether this parameter is a parameter pack. + /// Whether this parameter is a parameter pack. bool ParameterPack; - /// \brief Whether this template template parameter is an "expanded" + /// Whether this template template parameter is an "expanded" /// parameter pack, meaning that it is a pack expansion and we /// already know the set of template parameters that expansion expands to. bool ExpandedParameterPack = false; - /// \brief The number of parameters in an expanded parameter pack. + /// The number of parameters in an expanded parameter pack. unsigned NumExpandedParams = 0; TemplateTemplateParmDecl(DeclContext *DC, SourceLocation L, @@ -1501,7 +1502,7 @@ public: using TemplateParmPosition::setPosition; using TemplateParmPosition::getIndex; - /// \brief Whether this template template parameter is a template + /// Whether this template template parameter is a template /// parameter pack. /// /// \code @@ -1509,7 +1510,7 @@ public: /// \endcode bool isParameterPack() const { return ParameterPack; } - /// \brief Whether this parameter pack is a pack expansion. + /// Whether this parameter pack is a pack expansion. /// /// A template template parameter pack is a pack expansion if its template /// parameter list contains an unexpanded parameter pack. @@ -1518,7 +1519,7 @@ public: getTemplateParameters()->containsUnexpandedParameterPack(); } - /// \brief Whether this parameter is a template template parameter pack that + /// Whether this parameter is a template template parameter pack that /// has a known list of different template parameter lists at different /// positions. /// @@ -1538,14 +1539,14 @@ public: /// parameter pack. bool isExpandedParameterPack() const { return ExpandedParameterPack; } - /// \brief Retrieves the number of expansion template parameters in + /// Retrieves the number of expansion template parameters in /// an expanded parameter pack. unsigned getNumExpansionTemplateParameters() const { assert(ExpandedParameterPack && "Not an expansion parameter pack"); return NumExpandedParams; } - /// \brief Retrieve a particular expansion type within an expanded parameter + /// Retrieve a particular expansion type within an expanded parameter /// pack. TemplateParameterList *getExpansionTemplateParameters(unsigned I) const { assert(I < NumExpandedParams && "Out-of-range expansion type index"); @@ -1554,26 +1555,26 @@ public: const DefArgStorage &getDefaultArgStorage() const { return DefaultArgument; } - /// \brief Determine whether this template parameter has a default + /// Determine whether this template parameter has a default /// argument. bool hasDefaultArgument() const { return DefaultArgument.isSet(); } - /// \brief Retrieve the default argument, if any. + /// Retrieve the default argument, if any. const TemplateArgumentLoc &getDefaultArgument() const { static const TemplateArgumentLoc None; return DefaultArgument.isSet() ? *DefaultArgument.get() : None; } - /// \brief Retrieve the location of the default argument, if any. + /// Retrieve the location of the default argument, if any. SourceLocation getDefaultArgumentLoc() const; - /// \brief Determines whether the default argument was inherited + /// Determines whether the default argument was inherited /// from a previous declaration of this template. bool defaultArgumentWasInherited() const { return DefaultArgument.isInherited(); } - /// \brief Set the default argument for this template parameter, and + /// Set the default argument for this template parameter, and /// whether that default argument was inherited from another /// declaration. void setDefaultArgument(const ASTContext &C, @@ -1583,7 +1584,7 @@ public: DefaultArgument.setInherited(C, Prev); } - /// \brief Removes the default argument of this template parameter. + /// Removes the default argument of this template parameter. void removeDefaultArgument() { DefaultArgument.clear(); } SourceRange getSourceRange() const override LLVM_READONLY { @@ -1598,7 +1599,7 @@ public: static bool classofKind(Kind K) { return K == TemplateTemplateParm; } }; -/// \brief Represents the builtin template declaration which is used to +/// Represents the builtin template declaration which is used to /// implement __make_integer_seq and other builtin templates. It serves /// no real purpose beyond existing as a place to hold template parameters. class BuiltinTemplateDecl : public TemplateDecl { @@ -1621,13 +1622,13 @@ public: } SourceRange getSourceRange() const override LLVM_READONLY { - return SourceRange(); + return {}; } BuiltinTemplateKind getBuiltinTemplateKind() const { return BTK; } }; -/// \brief Represents a class template specialization, which refers to +/// Represents a class template specialization, which refers to /// a class template with a given set of template arguments. /// /// Class template specializations represent both explicit @@ -1642,48 +1643,48 @@ public: /// \endcode class ClassTemplateSpecializationDecl : public CXXRecordDecl, public llvm::FoldingSetNode { - /// \brief Structure that stores information about a class template + /// Structure that stores information about a class template /// specialization that was instantiated from a class template partial /// specialization. struct SpecializedPartialSpecialization { - /// \brief The class template partial specialization from which this + /// The class template partial specialization from which this /// class template specialization was instantiated. ClassTemplatePartialSpecializationDecl *PartialSpecialization; - /// \brief The template argument list deduced for the class template + /// The template argument list deduced for the class template /// partial specialization itself. const TemplateArgumentList *TemplateArgs; }; - /// \brief The template that this specialization specializes + /// The template that this specialization specializes llvm::PointerUnion<ClassTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - /// \brief Further info for explicit template specialization/instantiation. + /// Further info for explicit template specialization/instantiation. struct ExplicitSpecializationInfo { - /// \brief The type-as-written. + /// The type-as-written. TypeSourceInfo *TypeAsWritten = nullptr; - /// \brief The location of the extern keyword. + /// The location of the extern keyword. SourceLocation ExternLoc; - /// \brief The location of the template keyword. + /// The location of the template keyword. SourceLocation TemplateKeywordLoc; ExplicitSpecializationInfo() = default; }; - /// \brief Further info for explicit template specialization/instantiation. + /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. ExplicitSpecializationInfo *ExplicitInfo = nullptr; - /// \brief The template arguments used to describe this specialization. + /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; - /// \brief The point where this template was instantiated (if any) + /// The point where this template was instantiated (if any) SourceLocation PointOfInstantiation; - /// \brief The kind of specialization this declaration refers to. + /// The kind of specialization this declaration refers to. /// Really a value of type TemplateSpecializationKind. unsigned SpecializationKind : 3; @@ -1719,26 +1720,20 @@ public: // it's not clear that we should override that, because the most recent // declaration as a CXXRecordDecl sometimes is the injected-class-name. ClassTemplateSpecializationDecl *getMostRecentDecl() { - CXXRecordDecl *Recent = static_cast<CXXRecordDecl *>( - this)->getMostRecentDecl(); - while (!isa<ClassTemplateSpecializationDecl>(Recent)) { - // FIXME: Does injected class name need to be in the redeclarations chain? - assert(Recent->isInjectedClassName() && Recent->getPreviousDecl()); - Recent = Recent->getPreviousDecl(); - } - return cast<ClassTemplateSpecializationDecl>(Recent); + return cast<ClassTemplateSpecializationDecl>( + getMostRecentNonInjectedDecl()); } - /// \brief Retrieve the template that this specialization specializes. + /// Retrieve the template that this specialization specializes. ClassTemplateDecl *getSpecializedTemplate() const; - /// \brief Retrieve the template arguments of the class template + /// Retrieve the template arguments of the class template /// specialization. const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; } - /// \brief Determine the kind of specialization that this + /// Determine the kind of specialization that this /// declaration represents. TemplateSpecializationKind getSpecializationKind() const { return static_cast<TemplateSpecializationKind>(SpecializationKind); @@ -1748,7 +1743,7 @@ public: return getSpecializationKind() == TSK_ExplicitSpecialization; } - /// \brief True if this declaration is an explicit specialization, + /// True if this declaration is an explicit specialization, /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { @@ -1760,7 +1755,7 @@ public: SpecializationKind = TSK; } - /// \brief Get the point of instantiation (if any), or null if none. + /// Get the point of instantiation (if any), or null if none. SourceLocation getPointOfInstantiation() const { return PointOfInstantiation; } @@ -1770,7 +1765,7 @@ public: PointOfInstantiation = Loc; } - /// \brief If this class template specialization is an instantiation of + /// If this class template specialization is an instantiation of /// a template (rather than an explicit specialization), return the /// class template or class template partial specialization from which it /// was instantiated. @@ -1784,19 +1779,19 @@ public: return getSpecializedTemplateOrPartial(); } - /// \brief Retrieve the class template or class template partial + /// Retrieve the class template or class template partial /// specialization which was specialized by this. llvm::PointerUnion<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *> getSpecializedTemplateOrPartial() const { - if (SpecializedPartialSpecialization *PartialSpec - = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + if (const auto *PartialSpec = + SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) return PartialSpec->PartialSpecialization; return SpecializedTemplate.get<ClassTemplateDecl*>(); } - /// \brief Retrieve the set of template arguments that should be used + /// Retrieve the set of template arguments that should be used /// to instantiate members of the class template or class template partial /// specialization from which this class template specialization was /// instantiated. @@ -1808,28 +1803,27 @@ public: /// deduced template arguments for the class template partial specialization /// itself. const TemplateArgumentList &getTemplateInstantiationArgs() const { - if (SpecializedPartialSpecialization *PartialSpec - = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization*>()) + if (const auto *PartialSpec = + SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) return *PartialSpec->TemplateArgs; return getTemplateArgs(); } - /// \brief Note that this class template specialization is actually an + /// Note that this class template specialization is actually an /// instantiation of the given class template partial specialization whose /// template arguments have been deduced. void setInstantiationOf(ClassTemplatePartialSpecializationDecl *PartialSpec, const TemplateArgumentList *TemplateArgs) { assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && "Already set to a class template partial specialization!"); - SpecializedPartialSpecialization *PS - = new (getASTContext()) SpecializedPartialSpecialization(); + auto *PS = new (getASTContext()) SpecializedPartialSpecialization(); PS->PartialSpecialization = PartialSpec; PS->TemplateArgs = TemplateArgs; SpecializedTemplate = PS; } - /// \brief Note that this class template specialization is an instantiation + /// Note that this class template specialization is an instantiation /// of the given class template. void setInstantiationOf(ClassTemplateDecl *TemplDecl) { assert(!SpecializedTemplate.is<SpecializedPartialSpecialization*>() && @@ -1837,7 +1831,7 @@ public: SpecializedTemplate = TemplDecl; } - /// \brief Sets the type of this specialization as it was written by + /// Sets the type of this specialization as it was written by /// the user. This will be a class template specialization type. void setTypeAsWritten(TypeSourceInfo *T) { if (!ExplicitInfo) @@ -1845,32 +1839,32 @@ public: ExplicitInfo->TypeAsWritten = T; } - /// \brief Gets the type of this specialization as it was written by + /// Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; } - /// \brief Gets the location of the extern keyword, if present. + /// Gets the location of the extern keyword, if present. SourceLocation getExternLoc() const { return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); } - /// \brief Sets the location of the extern keyword. + /// Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc) { if (!ExplicitInfo) ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->ExternLoc = Loc; } - /// \brief Sets the location of the template keyword. + /// Sets the location of the template keyword. void setTemplateKeywordLoc(SourceLocation Loc) { if (!ExplicitInfo) ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TemplateKeywordLoc = Loc; } - /// \brief Gets the location of the template keyword, if present. + /// Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } @@ -1899,14 +1893,14 @@ public: class ClassTemplatePartialSpecializationDecl : public ClassTemplateSpecializationDecl { - /// \brief The list of template parameters + /// The list of template parameters TemplateParameterList* TemplateParams = nullptr; - /// \brief The source info for the template arguments as written. + /// The source info for the template arguments as written. /// FIXME: redundant with TypeAsWritten? const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; - /// \brief The class template partial specialization from which this + /// The class template partial specialization from which this /// class template partial specialization was instantiated. /// /// The boolean value will be true to indicate that this class template @@ -1963,7 +1957,7 @@ public: return ArgsAsWritten; } - /// \brief Retrieve the member class template partial specialization from + /// Retrieve the member class template partial specialization from /// which this particular class template partial specialization was /// instantiated. /// @@ -1984,7 +1978,7 @@ public: /// \c Outer<float>::Inner<U*>, this function would return /// \c Outer<T>::Inner<U*>. ClassTemplatePartialSpecializationDecl *getInstantiatedFromMember() const { - const ClassTemplatePartialSpecializationDecl *First = + const auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); return First->InstantiatedFromMember.getPointer(); } @@ -1995,12 +1989,11 @@ public: void setInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *PartialSpec) { - ClassTemplatePartialSpecializationDecl *First = - cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); + auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); First->InstantiatedFromMember.setPointer(PartialSpec); } - /// \brief Determines whether this class template partial specialization + /// Determines whether this class template partial specialization /// template was a specialization of a member partial specialization. /// /// In the following example, the member template partial specialization @@ -2017,15 +2010,14 @@ public: /// struct X<int>::Inner<T*> { /* ... */ }; /// \endcode bool isMemberSpecialization() { - ClassTemplatePartialSpecializationDecl *First = + const auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); return First->InstantiatedFromMember.getInt(); } - /// \brief Note that this member template is a specialization. + /// Note that this member template is a specialization. void setMemberSpecialization() { - ClassTemplatePartialSpecializationDecl *First = - cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); + auto *First = cast<ClassTemplatePartialSpecializationDecl>(getFirstDecl()); assert(First->InstantiatedFromMember.getPointer() && "Only member templates can be member template specializations"); return First->InstantiatedFromMember.setInt(true); @@ -2052,29 +2044,29 @@ public: /// Declaration of a class template. class ClassTemplateDecl : public RedeclarableTemplateDecl { protected: - /// \brief Data that is common to all of the declarations of a given + /// Data that is common to all of the declarations of a given /// class template. struct Common : CommonBase { - /// \brief The class template specializations for this class + /// The class template specializations for this class /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<ClassTemplateSpecializationDecl> Specializations; - /// \brief The class template partial specializations for this class + /// The class template partial specializations for this class /// template. llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> PartialSpecializations; - /// \brief The injected-class-name type for this class template. + /// The injected-class-name type for this class template. QualType InjectedClassNameType; Common() = default; }; - /// \brief Retrieve the set of specializations of this class template. + /// Retrieve the set of specializations of this class template. llvm::FoldingSetVector<ClassTemplateSpecializationDecl> & getSpecializations() const; - /// \brief Retrieve the set of partial specializations of this class + /// Retrieve the set of partial specializations of this class /// template. llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> & getPartialSpecializations(); @@ -2100,22 +2092,22 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - /// \brief Load any lazily-loaded specializations from the external source. + /// Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; - /// \brief Get the underlying class declarations of the template. + /// Get the underlying class declarations of the template. CXXRecordDecl *getTemplatedDecl() const { return static_cast<CXXRecordDecl *>(TemplatedDecl); } - /// \brief Returns whether this template declaration defines the primary + /// Returns whether this template declaration defines the primary /// class pattern. bool isThisDeclarationADefinition() const { return getTemplatedDecl()->isThisDeclarationADefinition(); } // FIXME: remove default argument for AssociatedConstraints - /// \brief Create a class template node. + /// Create a class template node. static ClassTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, @@ -2123,15 +2115,15 @@ public: NamedDecl *Decl, Expr *AssociatedConstraints = nullptr); - /// \brief Create an empty class template node. + /// Create an empty class template node. static ClassTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// \brief Return the specialization with the provided arguments if it exists, + /// Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. ClassTemplateSpecializationDecl * findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - /// \brief Insert the specified specialization knowing that it is not already + /// Insert the specified specialization knowing that it is not already /// in. InsertPos must be obtained from findSpecialization. void AddSpecialization(ClassTemplateSpecializationDecl *D, void *InsertPos); @@ -2144,7 +2136,7 @@ public: RedeclarableTemplateDecl::getCanonicalDecl()); } - /// \brief Retrieve the previous declaration of this class template, or + /// Retrieve the previous declaration of this class template, or /// nullptr if no such declaration exists. ClassTemplateDecl *getPreviousDecl() { return cast_or_null<ClassTemplateDecl>( @@ -2169,21 +2161,21 @@ public: RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } - /// \brief Return the partial specialization with the provided arguments if it + /// Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. ClassTemplatePartialSpecializationDecl * findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - /// \brief Insert the specified partial specialization knowing that it is not + /// Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. void AddPartialSpecialization(ClassTemplatePartialSpecializationDecl *D, void *InsertPos); - /// \brief Retrieve the partial specializations as an ordered list. + /// Retrieve the partial specializations as an ordered list. void getPartialSpecializations( SmallVectorImpl<ClassTemplatePartialSpecializationDecl *> &PS); - /// \brief Find a class template partial specialization with the given + /// Find a class template partial specialization with the given /// type T. /// /// \param T a dependent type that names a specialization of this class @@ -2193,7 +2185,7 @@ public: /// the type \p T, or nullptr if no such partial specialization exists. ClassTemplatePartialSpecializationDecl *findPartialSpecialization(QualType T); - /// \brief Find a class template partial specialization which was instantiated + /// Find a class template partial specialization which was instantiated /// from the given member partial specialization. /// /// \param D a member class template partial specialization. @@ -2205,7 +2197,7 @@ public: findPartialSpecInstantiatedFromMember( ClassTemplatePartialSpecializationDecl *D); - /// \brief Retrieve the template specialization type of the + /// Retrieve the template specialization type of the /// injected-class-name for this class template. /// /// The injected-class-name for a class template \c X is \c @@ -2241,7 +2233,7 @@ public: static bool classofKind(Kind K) { return K == ClassTemplate; } }; -/// \brief Declaration of a friend template. +/// Declaration of a friend template. /// /// For example: /// \code @@ -2305,7 +2297,7 @@ public: return Friend.dyn_cast<NamedDecl*>(); } - /// \brief Retrieves the location of the 'friend' keyword. + /// Retrieves the location of the 'friend' keyword. SourceLocation getFriendLoc() const { return FriendLoc; } @@ -2324,7 +2316,7 @@ public: static bool classofKind(Kind K) { return K == Decl::FriendTemplate; } }; -/// \brief Declaration of an alias template. +/// Declaration of an alias template. /// /// For example: /// \code @@ -2365,7 +2357,7 @@ public: RedeclarableTemplateDecl::getCanonicalDecl()); } - /// \brief Retrieve the previous declaration of this function template, or + /// Retrieve the previous declaration of this function template, or /// nullptr if no such declaration exists. TypeAliasTemplateDecl *getPreviousDecl() { return cast_or_null<TypeAliasTemplateDecl>( @@ -2382,14 +2374,14 @@ public: RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } - /// \brief Create a function template node. + /// Create a function template node. static TypeAliasTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, NamedDecl *Decl); - /// \brief Create an empty alias template node. + /// Create an empty alias template node. static TypeAliasTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); // Implement isa/cast/dyncast support @@ -2397,7 +2389,7 @@ public: static bool classofKind(Kind K) { return K == TypeAliasTemplate; } }; -/// \brief Declaration of a function specialization at template class scope. +/// Declaration of a function specialization at template class scope. /// /// This is a non-standard extension needed to support MSVC. /// @@ -2463,7 +2455,7 @@ public: inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) : Function(FTD) {} -/// \brief Represents a variable template specialization, which refers to +/// Represents a variable template specialization, which refers to /// a variable template with a given set of template arguments. /// /// Variable template specializations represent both explicit @@ -2479,53 +2471,53 @@ inline AnyFunctionDecl::AnyFunctionDecl(FunctionTemplateDecl *FTD) class VarTemplateSpecializationDecl : public VarDecl, public llvm::FoldingSetNode { - /// \brief Structure that stores information about a variable template + /// Structure that stores information about a variable template /// specialization that was instantiated from a variable template partial /// specialization. struct SpecializedPartialSpecialization { - /// \brief The variable template partial specialization from which this + /// The variable template partial specialization from which this /// variable template specialization was instantiated. VarTemplatePartialSpecializationDecl *PartialSpecialization; - /// \brief The template argument list deduced for the variable template + /// The template argument list deduced for the variable template /// partial specialization itself. const TemplateArgumentList *TemplateArgs; }; - /// \brief The template that this specialization specializes. + /// The template that this specialization specializes. llvm::PointerUnion<VarTemplateDecl *, SpecializedPartialSpecialization *> SpecializedTemplate; - /// \brief Further info for explicit template specialization/instantiation. + /// Further info for explicit template specialization/instantiation. struct ExplicitSpecializationInfo { - /// \brief The type-as-written. + /// The type-as-written. TypeSourceInfo *TypeAsWritten = nullptr; - /// \brief The location of the extern keyword. + /// The location of the extern keyword. SourceLocation ExternLoc; - /// \brief The location of the template keyword. + /// The location of the template keyword. SourceLocation TemplateKeywordLoc; ExplicitSpecializationInfo() = default; }; - /// \brief Further info for explicit template specialization/instantiation. + /// Further info for explicit template specialization/instantiation. /// Does not apply to implicit specializations. ExplicitSpecializationInfo *ExplicitInfo = nullptr; - /// \brief The template arguments used to describe this specialization. + /// The template arguments used to describe this specialization. const TemplateArgumentList *TemplateArgs; TemplateArgumentListInfo TemplateArgsInfo; - /// \brief The point where this template was instantiated (if any). + /// The point where this template was instantiated (if any). SourceLocation PointOfInstantiation; - /// \brief The kind of specialization this declaration refers to. + /// The kind of specialization this declaration refers to. /// Really a value of type TemplateSpecializationKind. unsigned SpecializationKind : 3; - /// \brief Whether this declaration is a complete definition of the + /// Whether this declaration is a complete definition of the /// variable template specialization. We can't otherwise tell apart /// an instantiated declaration from an instantiated definition with /// no initializer. @@ -2562,10 +2554,10 @@ public: return cast<VarTemplateSpecializationDecl>(Recent); } - /// \brief Retrieve the template that this specialization specializes. + /// Retrieve the template that this specialization specializes. VarTemplateDecl *getSpecializedTemplate() const; - /// \brief Retrieve the template arguments of the variable template + /// Retrieve the template arguments of the variable template /// specialization. const TemplateArgumentList &getTemplateArgs() const { return *TemplateArgs; } @@ -2576,7 +2568,7 @@ public: return TemplateArgsInfo; } - /// \brief Determine the kind of specialization that this + /// Determine the kind of specialization that this /// declaration represents. TemplateSpecializationKind getSpecializationKind() const { return static_cast<TemplateSpecializationKind>(SpecializationKind); @@ -2586,7 +2578,7 @@ public: return getSpecializationKind() == TSK_ExplicitSpecialization; } - /// \brief True if this declaration is an explicit specialization, + /// True if this declaration is an explicit specialization, /// explicit instantiation declaration, or explicit instantiation /// definition. bool isExplicitInstantiationOrSpecialization() const { @@ -2598,7 +2590,7 @@ public: SpecializationKind = TSK; } - /// \brief Get the point of instantiation (if any), or null if none. + /// Get the point of instantiation (if any), or null if none. SourceLocation getPointOfInstantiation() const { return PointOfInstantiation; } @@ -2610,7 +2602,7 @@ public: void setCompleteDefinition() { IsCompleteDefinition = true; } - /// \brief If this variable template specialization is an instantiation of + /// If this variable template specialization is an instantiation of /// a template (rather than an explicit specialization), return the /// variable template or variable template partial specialization from which /// it was instantiated. @@ -2623,18 +2615,18 @@ public: return getSpecializedTemplateOrPartial(); } - /// \brief Retrieve the variable template or variable template partial + /// Retrieve the variable template or variable template partial /// specialization which was specialized by this. llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> getSpecializedTemplateOrPartial() const { - if (SpecializedPartialSpecialization *PartialSpec = + if (const auto *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) return PartialSpec->PartialSpecialization; return SpecializedTemplate.get<VarTemplateDecl *>(); } - /// \brief Retrieve the set of template arguments that should be used + /// Retrieve the set of template arguments that should be used /// to instantiate the initializer of the variable template or variable /// template partial specialization from which this variable template /// specialization was instantiated. @@ -2646,28 +2638,27 @@ public: /// return deduced template arguments for the variable template partial /// specialization itself. const TemplateArgumentList &getTemplateInstantiationArgs() const { - if (SpecializedPartialSpecialization *PartialSpec = + if (const auto *PartialSpec = SpecializedTemplate.dyn_cast<SpecializedPartialSpecialization *>()) return *PartialSpec->TemplateArgs; return getTemplateArgs(); } - /// \brief Note that this variable template specialization is actually an + /// Note that this variable template specialization is actually an /// instantiation of the given variable template partial specialization whose /// template arguments have been deduced. void setInstantiationOf(VarTemplatePartialSpecializationDecl *PartialSpec, const TemplateArgumentList *TemplateArgs) { assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() && "Already set to a variable template partial specialization!"); - SpecializedPartialSpecialization *PS = - new (getASTContext()) SpecializedPartialSpecialization(); + auto *PS = new (getASTContext()) SpecializedPartialSpecialization(); PS->PartialSpecialization = PartialSpec; PS->TemplateArgs = TemplateArgs; SpecializedTemplate = PS; } - /// \brief Note that this variable template specialization is an instantiation + /// Note that this variable template specialization is an instantiation /// of the given variable template. void setInstantiationOf(VarTemplateDecl *TemplDecl) { assert(!SpecializedTemplate.is<SpecializedPartialSpecialization *>() && @@ -2675,7 +2666,7 @@ public: SpecializedTemplate = TemplDecl; } - /// \brief Sets the type of this specialization as it was written by + /// Sets the type of this specialization as it was written by /// the user. void setTypeAsWritten(TypeSourceInfo *T) { if (!ExplicitInfo) @@ -2683,32 +2674,32 @@ public: ExplicitInfo->TypeAsWritten = T; } - /// \brief Gets the type of this specialization as it was written by + /// Gets the type of this specialization as it was written by /// the user, if it was so written. TypeSourceInfo *getTypeAsWritten() const { return ExplicitInfo ? ExplicitInfo->TypeAsWritten : nullptr; } - /// \brief Gets the location of the extern keyword, if present. + /// Gets the location of the extern keyword, if present. SourceLocation getExternLoc() const { return ExplicitInfo ? ExplicitInfo->ExternLoc : SourceLocation(); } - /// \brief Sets the location of the extern keyword. + /// Sets the location of the extern keyword. void setExternLoc(SourceLocation Loc) { if (!ExplicitInfo) ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->ExternLoc = Loc; } - /// \brief Sets the location of the template keyword. + /// Sets the location of the template keyword. void setTemplateKeywordLoc(SourceLocation Loc) { if (!ExplicitInfo) ExplicitInfo = new (getASTContext()) ExplicitSpecializationInfo; ExplicitInfo->TemplateKeywordLoc = Loc; } - /// \brief Gets the location of the template keyword, if present. + /// Gets the location of the template keyword, if present. SourceLocation getTemplateKeywordLoc() const { return ExplicitInfo ? ExplicitInfo->TemplateKeywordLoc : SourceLocation(); } @@ -2735,14 +2726,14 @@ public: class VarTemplatePartialSpecializationDecl : public VarTemplateSpecializationDecl { - /// \brief The list of template parameters + /// The list of template parameters TemplateParameterList *TemplateParams = nullptr; - /// \brief The source info for the template arguments as written. + /// The source info for the template arguments as written. /// FIXME: redundant with TypeAsWritten? const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; - /// \brief The variable template partial specialization from which this + /// The variable template partial specialization from which this /// variable template partial specialization was instantiated. /// /// The boolean value will be true to indicate that this variable template @@ -2794,7 +2785,7 @@ public: return ArgsAsWritten; } - /// \brief Retrieve the member variable template partial specialization from + /// Retrieve the member variable template partial specialization from /// which this particular variable template partial specialization was /// instantiated. /// @@ -2815,19 +2806,18 @@ public: /// \c Outer<float>::Inner<U*>, this function would return /// \c Outer<T>::Inner<U*>. VarTemplatePartialSpecializationDecl *getInstantiatedFromMember() const { - const VarTemplatePartialSpecializationDecl *First = + const auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); return First->InstantiatedFromMember.getPointer(); } void setInstantiatedFromMember(VarTemplatePartialSpecializationDecl *PartialSpec) { - VarTemplatePartialSpecializationDecl *First = - cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); + auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); First->InstantiatedFromMember.setPointer(PartialSpec); } - /// \brief Determines whether this variable template partial specialization + /// Determines whether this variable template partial specialization /// was a specialization of a member partial specialization. /// /// In the following example, the member template partial specialization @@ -2844,15 +2834,14 @@ public: /// U* X<int>::Inner<T*> = (T*)(0) + 1; /// \endcode bool isMemberSpecialization() { - VarTemplatePartialSpecializationDecl *First = + const auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); return First->InstantiatedFromMember.getInt(); } - /// \brief Note that this member template is a specialization. + /// Note that this member template is a specialization. void setMemberSpecialization() { - VarTemplatePartialSpecializationDecl *First = - cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); + auto *First = cast<VarTemplatePartialSpecializationDecl>(getFirstDecl()); assert(First->InstantiatedFromMember.getPointer() && "Only member templates can be member template specializations"); return First->InstantiatedFromMember.setInt(true); @@ -2868,14 +2857,14 @@ public: /// Declaration of a variable template. class VarTemplateDecl : public RedeclarableTemplateDecl { protected: - /// \brief Data that is common to all of the declarations of a given + /// Data that is common to all of the declarations of a given /// variable template. struct Common : CommonBase { - /// \brief The variable template specializations for this variable + /// The variable template specializations for this variable /// template, including explicit specializations and instantiations. llvm::FoldingSetVector<VarTemplateSpecializationDecl> Specializations; - /// \brief The variable template partial specializations for this variable + /// The variable template partial specializations for this variable /// template. llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> PartialSpecializations; @@ -2883,11 +2872,11 @@ protected: Common() = default; }; - /// \brief Retrieve the set of specializations of this variable template. + /// Retrieve the set of specializations of this variable template. llvm::FoldingSetVector<VarTemplateSpecializationDecl> & getSpecializations() const; - /// \brief Retrieve the set of partial specializations of this class + /// Retrieve the set of partial specializations of this class /// template. llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> & getPartialSpecializations(); @@ -2907,15 +2896,15 @@ public: friend class ASTDeclReader; friend class ASTDeclWriter; - /// \brief Load any lazily-loaded specializations from the external source. + /// Load any lazily-loaded specializations from the external source. void LoadLazySpecializations() const; - /// \brief Get the underlying variable declarations of the template. + /// Get the underlying variable declarations of the template. VarDecl *getTemplatedDecl() const { return static_cast<VarDecl *>(TemplatedDecl); } - /// \brief Returns whether this template declaration defines the primary + /// Returns whether this template declaration defines the primary /// variable pattern. bool isThisDeclarationADefinition() const { return getTemplatedDecl()->isThisDeclarationADefinition(); @@ -2923,21 +2912,21 @@ public: VarTemplateDecl *getDefinition(); - /// \brief Create a variable template node. + /// Create a variable template node. static VarTemplateDecl *Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, TemplateParameterList *Params, VarDecl *Decl); - /// \brief Create an empty variable template node. + /// Create an empty variable template node. static VarTemplateDecl *CreateDeserialized(ASTContext &C, unsigned ID); - /// \brief Return the specialization with the provided arguments if it exists, + /// Return the specialization with the provided arguments if it exists, /// otherwise return the insertion point. VarTemplateSpecializationDecl * findSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - /// \brief Insert the specified specialization knowing that it is not already + /// Insert the specified specialization knowing that it is not already /// in. InsertPos must be obtained from findSpecialization. void AddSpecialization(VarTemplateSpecializationDecl *D, void *InsertPos); @@ -2948,7 +2937,7 @@ public: return cast<VarTemplateDecl>(RedeclarableTemplateDecl::getCanonicalDecl()); } - /// \brief Retrieve the previous declaration of this variable template, or + /// Retrieve the previous declaration of this variable template, or /// nullptr if no such declaration exists. VarTemplateDecl *getPreviousDecl() { return cast_or_null<VarTemplateDecl>( @@ -2973,21 +2962,21 @@ public: RedeclarableTemplateDecl::getInstantiatedFromMemberTemplate()); } - /// \brief Return the partial specialization with the provided arguments if it + /// Return the partial specialization with the provided arguments if it /// exists, otherwise return the insertion point. VarTemplatePartialSpecializationDecl * findPartialSpecialization(ArrayRef<TemplateArgument> Args, void *&InsertPos); - /// \brief Insert the specified partial specialization knowing that it is not + /// Insert the specified partial specialization knowing that it is not /// already in. InsertPos must be obtained from findPartialSpecialization. void AddPartialSpecialization(VarTemplatePartialSpecializationDecl *D, void *InsertPos); - /// \brief Retrieve the partial specializations as an ordered list. + /// Retrieve the partial specializations as an ordered list. void getPartialSpecializations( SmallVectorImpl<VarTemplatePartialSpecializationDecl *> &PS); - /// \brief Find a variable template partial specialization which was + /// Find a variable template partial specialization which was /// instantiated /// from the given member partial specialization. /// @@ -3021,11 +3010,11 @@ public: }; inline NamedDecl *getAsNamedDecl(TemplateParameter P) { - if (auto *PD = P.dyn_cast<TemplateTypeParmDecl*>()) + if (auto *PD = P.dyn_cast<TemplateTypeParmDecl *>()) return PD; - if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl*>()) + if (auto *PD = P.dyn_cast<NonTypeTemplateParmDecl *>()) return PD; - return P.get<TemplateTemplateParmDecl*>(); + return P.get<TemplateTemplateParmDecl *>(); } inline TemplateDecl *getAsTypeTemplateDecl(Decl *D) { diff --git a/include/clang/AST/DeclVisitor.h b/include/clang/AST/DeclVisitor.h index 3ff274bd6a7a1..520a4a10bfe10 100644 --- a/include/clang/AST/DeclVisitor.h +++ b/include/clang/AST/DeclVisitor.h @@ -30,7 +30,7 @@ namespace declvisitor { template <typename T> struct make_ptr { using type = T *; }; template <typename T> struct make_const_ptr { using type = const T *; }; -/// \brief A simple visitor class that helps create declaration visitors. +/// A simple visitor class that helps create declaration visitors. template<template <typename> class Ptr, typename ImplClass, typename RetTy=void> class Base { public: @@ -62,7 +62,7 @@ public: } // namespace declvisitor -/// \brief A simple visitor class that helps create declaration visitors. +/// A simple visitor class that helps create declaration visitors. /// /// This class does not preserve constness of Decl pointers (see also /// ConstDeclVisitor). @@ -70,7 +70,7 @@ template<typename ImplClass, typename RetTy = void> class DeclVisitor : public declvisitor::Base<declvisitor::make_ptr, ImplClass, RetTy> {}; -/// \brief A simple visitor class that helps create declaration visitors. +/// A simple visitor class that helps create declaration visitors. /// /// This class preserves constness of Decl pointers (see also DeclVisitor). template<typename ImplClass, typename RetTy = void> diff --git a/include/clang/AST/DeclarationName.h b/include/clang/AST/DeclarationName.h index 467b02c52b0c9..9d3dad6bbd9d2 100644 --- a/include/clang/AST/DeclarationName.h +++ b/include/clang/AST/DeclarationName.h @@ -194,7 +194,7 @@ public: (reinterpret_cast<IdentifierInfo *>(Ptr & ~PtrMask)); } - /// \brief Evaluates true when this declaration name is empty. + /// Evaluates true when this declaration name is empty. bool isEmpty() const { return !*this; } @@ -211,7 +211,7 @@ public: /// getNameKind - Determine what kind of name this is. NameKind getNameKind() const; - /// \brief Determines whether the name itself is dependent, e.g., because it + /// Determines whether the name itself is dependent, e.g., because it /// involves a C++ type that is itself dependent. /// /// Note that this does not capture all of the notions of "dependent name", @@ -541,10 +541,10 @@ public: LocInfo.CXXLiteralOperatorName.OpNameLoc = Loc.getRawEncoding(); } - /// \brief Determine whether this name involves a template parameter. + /// Determine whether this name involves a template parameter. bool isInstantiationDependent() const; - /// \brief Determine whether this name contains an unexpanded + /// Determine whether this name contains an unexpanded /// parameter pack. bool containsUnexpandedParameterPack() const; diff --git a/include/clang/AST/EvaluatedExprVisitor.h b/include/clang/AST/EvaluatedExprVisitor.h index aad7726f8484d..e00986dbe9c86 100644 --- a/include/clang/AST/EvaluatedExprVisitor.h +++ b/include/clang/AST/EvaluatedExprVisitor.h @@ -24,7 +24,7 @@ namespace clang { class ASTContext; -/// \brief Given a potentially-evaluated expression, this visitor visits all +/// Given a potentially-evaluated expression, this visitor visits all /// of its potentially-evaluated subexpressions, recursively. template<template <typename> class Ptr, typename ImplClass> class EvaluatedExprVisitorBase : public StmtVisitorBase<Ptr, ImplClass, void> { @@ -95,7 +95,7 @@ public: this->Visit(*I); } - /// \brief The basis case walks all of the children of the statement or + /// The basis case walks all of the children of the statement or /// expression, assuming they are all potentially evaluated. void VisitStmt(PTR(Stmt) S) { for (auto *SubStmt : S->children()) diff --git a/include/clang/AST/Expr.h b/include/clang/AST/Expr.h index f2770940372fd..7585231e62e5c 100644 --- a/include/clang/AST/Expr.h +++ b/include/clang/AST/Expr.h @@ -52,10 +52,10 @@ namespace clang { class TargetInfo; class ValueDecl; -/// \brief A simple array of base specifiers. +/// A simple array of base specifiers. typedef SmallVector<CXXBaseSpecifier*, 4> CXXCastPath; -/// \brief An adjustment to be made to the temporary created when emitting a +/// An adjustment to be made to the temporary created when emitting a /// reference binding, which accesses a particular subobject of that temporary. struct SubobjectAdjustment { enum { @@ -121,7 +121,7 @@ protected: setType(T); } - /// \brief Construct an empty expression. + /// Construct an empty expression. explicit Expr(StmtClass SC, EmptyShell) : Stmt(SC) { } public: @@ -148,7 +148,7 @@ public: /// @endcode bool isValueDependent() const { return ExprBits.ValueDependent; } - /// \brief Set whether this expression is value-dependent or not. + /// Set whether this expression is value-dependent or not. void setValueDependent(bool VD) { ExprBits.ValueDependent = VD; } @@ -166,12 +166,12 @@ public: /// @endcode bool isTypeDependent() const { return ExprBits.TypeDependent; } - /// \brief Set whether this expression is type-dependent or not. + /// Set whether this expression is type-dependent or not. void setTypeDependent(bool TD) { ExprBits.TypeDependent = TD; } - /// \brief Whether this expression is instantiation-dependent, meaning that + /// Whether this expression is instantiation-dependent, meaning that /// it depends in some way on a template parameter, even if neither its type /// nor (constant) value can change due to the template instantiation. /// @@ -192,12 +192,12 @@ public: return ExprBits.InstantiationDependent; } - /// \brief Set whether this expression is instantiation-dependent or not. + /// Set whether this expression is instantiation-dependent or not. void setInstantiationDependent(bool ID) { ExprBits.InstantiationDependent = ID; } - /// \brief Whether this expression contains an unexpanded parameter + /// Whether this expression contains an unexpanded parameter /// pack (for C++11 variadic templates). /// /// Given the following function template: @@ -215,7 +215,7 @@ public: return ExprBits.ContainsUnexpandedParameterPack; } - /// \brief Set the bit that describes whether this expression + /// Set the bit that describes whether this expression /// contains an unexpanded parameter pack. void setContainsUnexpandedParameterPack(bool PP = true) { ExprBits.ContainsUnexpandedParameterPack = PP; @@ -297,11 +297,11 @@ public: isModifiableLvalueResult isModifiableLvalue(ASTContext &Ctx, SourceLocation *Loc = nullptr) const; - /// \brief The return type of classify(). Represents the C++11 expression + /// The return type of classify(). Represents the C++11 expression /// taxonomy. class Classification { public: - /// \brief The various classification results. Most of these mean prvalue. + /// The various classification results. Most of these mean prvalue. enum Kinds { CL_LValue, CL_XValue, @@ -316,7 +316,7 @@ public: CL_ObjCMessageRValue, // ObjC message is an rvalue CL_PRValue // A prvalue for any other reason, of any other type }; - /// \brief The results of modification testing. + /// The results of modification testing. enum ModifiableType { CM_Untested, // testModifiable was false. CM_Modifiable, @@ -356,13 +356,13 @@ public: bool isRValue() const { return Kind >= CL_XValue; } bool isModifiable() const { return getModifiable() == CM_Modifiable; } - /// \brief Create a simple, modifiably lvalue + /// Create a simple, modifiably lvalue static Classification makeSimpleLValue() { return Classification(CL_LValue, CM_Modifiable); } }; - /// \brief Classify - Classify this expression according to the C++11 + /// Classify - Classify this expression according to the C++11 /// expression taxonomy. /// /// C++11 defines ([basic.lval]) a new taxonomy of expressions to replace the @@ -378,7 +378,7 @@ public: return ClassifyImpl(Ctx, nullptr); } - /// \brief ClassifyModifiable - Classify this expression according to the + /// ClassifyModifiable - Classify this expression according to the /// C++11 expression taxonomy, and see if it is valid on the left side /// of an assignment. /// @@ -429,14 +429,14 @@ private: public: - /// \brief Returns true if this expression is a gl-value that + /// Returns true if this expression is a gl-value that /// potentially refers to a bit-field. /// /// In C++, whether a gl-value refers to a bitfield is essentially /// an aspect of the value-kind type system. bool refersToBitField() const { return getObjectKind() == OK_BitField; } - /// \brief If this expression refers to a bit-field, retrieve the + /// If this expression refers to a bit-field, retrieve the /// declaration of that bit-field. /// /// Note that this returns a non-null pointer in subtly different @@ -454,26 +454,26 @@ public: return const_cast<Expr*>(this)->getReferencedDeclOfCallee(); } - /// \brief If this expression is an l-value for an Objective C + /// If this expression is an l-value for an Objective C /// property, find the underlying property reference expression. const ObjCPropertyRefExpr *getObjCProperty() const; - /// \brief Check if this expression is the ObjC 'self' implicit parameter. + /// Check if this expression is the ObjC 'self' implicit parameter. bool isObjCSelfExpr() const; - /// \brief Returns whether this expression refers to a vector element. + /// Returns whether this expression refers to a vector element. bool refersToVectorElement() const; - /// \brief Returns whether this expression refers to a global register + /// Returns whether this expression refers to a global register /// variable. bool refersToGlobalRegisterVar() const; - /// \brief Returns whether this expression has a placeholder type. + /// Returns whether this expression has a placeholder type. bool hasPlaceholderType() const { return getType()->isPlaceholderType(); } - /// \brief Returns whether this expression has a specific placeholder type. + /// Returns whether this expression has a specific placeholder type. bool hasPlaceholderType(BuiltinType::Kind K) const { assert(BuiltinType::isPlaceholderTypeKind(K)); if (const BuiltinType *BT = dyn_cast<BuiltinType>(getType())) @@ -539,11 +539,11 @@ public: /// EvalStatus is a struct with detailed info about an evaluation in progress. struct EvalStatus { - /// \brief Whether the evaluated expression has side effects. + /// Whether the evaluated expression has side effects. /// For example, (f() && 0) can be folded, but it still has side effects. bool HasSideEffects; - /// \brief Whether the evaluation hit undefined behavior. + /// Whether the evaluation hit undefined behavior. /// For example, 1.0 / 0.0 can be folded to Inf, but has undefined behavior. /// Likewise, INT_MAX + 1 can be folded to INT_MIN, but has UB. bool HasUndefinedBehavior; @@ -586,7 +586,7 @@ public: bool EvaluateAsRValue(EvalResult &Result, const ASTContext &Ctx) const; /// EvaluateAsBooleanCondition - Return true if this is a constant - /// which we we can fold and convert to a boolean condition using + /// which we can fold and convert to a boolean condition using /// any crazy technique that we want to, even if the expression has /// side-effects. bool EvaluateAsBooleanCondition(bool &Result, const ASTContext &Ctx) const; @@ -625,7 +625,7 @@ public: bool HasSideEffects(const ASTContext &Ctx, bool IncludePossibleEffects = true) const; - /// \brief Determine whether this expression involves a call to any function + /// Determine whether this expression involves a call to any function /// that is not trivial. bool hasNonTrivialCall(const ASTContext &Ctx) const; @@ -658,7 +658,14 @@ public: ArrayRef<const Expr*> Args, const Expr *This = nullptr) const; - /// \brief If the current Expr is a pointer, this will try to statically + /// Indicates how the constant expression will be used. + enum ConstExprUsage { EvaluateForCodeGen, EvaluateForMangling }; + + /// Evaluate an expression that is required to be a constant expression. + bool EvaluateAsConstantExpr(EvalResult &Result, ConstExprUsage Usage, + const ASTContext &Ctx) const; + + /// If the current Expr is a pointer, this will try to statically /// determine the number of bytes available where the pointer is pointing. /// Returns true if all of the above holds and we were able to figure out the /// size, false otherwise. @@ -668,40 +675,40 @@ public: bool tryEvaluateObjectSize(uint64_t &Result, ASTContext &Ctx, unsigned Type) const; - /// \brief Enumeration used to describe the kind of Null pointer constant + /// Enumeration used to describe the kind of Null pointer constant /// returned from \c isNullPointerConstant(). enum NullPointerConstantKind { - /// \brief Expression is not a Null pointer constant. + /// Expression is not a Null pointer constant. NPCK_NotNull = 0, - /// \brief Expression is a Null pointer constant built from a zero integer + /// Expression is a Null pointer constant built from a zero integer /// expression that is not a simple, possibly parenthesized, zero literal. /// C++ Core Issue 903 will classify these expressions as "not pointers" /// once it is adopted. /// http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#903 NPCK_ZeroExpression, - /// \brief Expression is a Null pointer constant built from a literal zero. + /// Expression is a Null pointer constant built from a literal zero. NPCK_ZeroLiteral, - /// \brief Expression is a C++11 nullptr. + /// Expression is a C++11 nullptr. NPCK_CXX11_nullptr, - /// \brief Expression is a GNU-style __null constant. + /// Expression is a GNU-style __null constant. NPCK_GNUNull }; - /// \brief Enumeration used to describe how \c isNullPointerConstant() + /// Enumeration used to describe how \c isNullPointerConstant() /// should cope with value-dependent expressions. enum NullPointerConstantValueDependence { - /// \brief Specifies that the expression should never be value-dependent. + /// Specifies that the expression should never be value-dependent. NPC_NeverValueDependent = 0, - /// \brief Specifies that a value-dependent expression of integral or + /// Specifies that a value-dependent expression of integral or /// dependent type should be considered a null pointer constant. NPC_ValueDependentIsNull, - /// \brief Specifies that a value-dependent expression should be considered + /// Specifies that a value-dependent expression should be considered /// to never be a null pointer constant. NPC_ValueDependentIsNotNull }; @@ -717,10 +724,10 @@ public: /// write barrier. bool isOBJCGCCandidate(ASTContext &Ctx) const; - /// \brief Returns true if this expression is a bound member function. + /// Returns true if this expression is a bound member function. bool isBoundMemberFunction(ASTContext &Ctx) const; - /// \brief Given an expression of bound-member type, find the type + /// Given an expression of bound-member type, find the type /// of the member. Returns null if this is an *overloaded* bound /// member expression. static QualType findBoundMemberType(const Expr *expr); @@ -788,7 +795,7 @@ public: return const_cast<Expr*>(this)->ignoreParenBaseCasts(); } - /// \brief Determine whether this expression is a default function argument. + /// Determine whether this expression is a default function argument. /// /// Default arguments are implicitly generated in the abstract syntax tree /// by semantic analysis for function calls, object constructions, etc. in @@ -797,11 +804,11 @@ public: /// the expression is a default argument. bool isDefaultArgument() const; - /// \brief Determine whether the result of this expression is a + /// Determine whether the result of this expression is a /// temporary object of the given class type. bool isTemporaryObject(ASTContext &Ctx, const CXXRecordDecl *TempTy) const; - /// \brief Whether this expression is an implicit reference to 'this' in C++. + /// Whether this expression is an implicit reference to 'this' in C++. bool isImplicitCXXThis() const; const Expr *IgnoreImpCasts() const LLVM_READONLY { @@ -824,7 +831,7 @@ public: static bool hasAnyTypeDependentArguments(ArrayRef<Expr *> Exprs); - /// \brief For an expression of class type or pointer to class type, + /// For an expression of class type or pointer to class type, /// return the most derived class decl the expression is known to refer to. /// /// If this expression is a cast, this method looks through it to find the @@ -833,7 +840,7 @@ public: /// behavior if the object isn't dynamically of the derived type. const CXXRecordDecl *getBestDynamicClassType() const; - /// \brief Get the inner expression that determines the best dynamic class. + /// Get the inner expression that determines the best dynamic class. /// If this is a prvalue, we guarantee that it is of the most-derived type /// for the object itself. const Expr *getBestDynamicClassTypeExpr() const; @@ -883,6 +890,7 @@ public: (SourceExpr && SourceExpr->isInstantiationDependent()), false), SourceExpr(SourceExpr), Loc(Loc) { + setIsUnique(false); } /// Given an expression which invokes a copy constructor --- i.e. a @@ -893,7 +901,7 @@ public: explicit OpaqueValueExpr(EmptyShell Empty) : Expr(OpaqueValueExprClass, Empty) { } - /// \brief Retrieve the location of this expression. + /// Retrieve the location of this expression. SourceLocation getLocation() const { return Loc; } SourceLocation getLocStart() const LLVM_READONLY { @@ -925,12 +933,20 @@ public: /// place. Expr *getSourceExpr() const { return SourceExpr; } + void setIsUnique(bool V) { + assert((!V || SourceExpr) && + "unique OVEs are expected to have source expressions"); + OpaqueValueExprBits.IsUnique = V; + } + + bool isUnique() const { return OpaqueValueExprBits.IsUnique; } + static bool classof(const Stmt *T) { return T->getStmtClass() == OpaqueValueExprClass; } }; -/// \brief A reference to a declared variable, function, enum, etc. +/// A reference to a declared variable, function, enum, etc. /// [C99 6.5.1p2] /// /// This encodes all the information about how a declaration is referenced @@ -958,13 +974,13 @@ class DeclRefExpr final private llvm::TrailingObjects<DeclRefExpr, NestedNameSpecifierLoc, NamedDecl *, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { - /// \brief The declaration that we are referencing. + /// The declaration that we are referencing. ValueDecl *D; - /// \brief The location of the declaration name itself. + /// The location of the declaration name itself. SourceLocation Loc; - /// \brief Provides source/type location info for the declaration name + /// Provides source/type location info for the declaration name /// embedded in D. DeclarationNameLoc DNLoc; @@ -980,7 +996,7 @@ class DeclRefExpr final return hasTemplateKWAndArgsInfo() ? 1 : 0; } - /// \brief Test whether there is a distinct FoundDecl attached to the end of + /// Test whether there is a distinct FoundDecl attached to the end of /// this DRE. bool hasFoundDecl() const { return DeclRefExprBits.HasFoundDecl; } @@ -993,11 +1009,11 @@ class DeclRefExpr final const TemplateArgumentListInfo *TemplateArgs, QualType T, ExprValueKind VK); - /// \brief Construct an empty declaration reference expression. + /// Construct an empty declaration reference expression. explicit DeclRefExpr(EmptyShell Empty) : Expr(DeclRefExprClass, Empty) { } - /// \brief Computes the type- and value-dependence flags for this + /// Computes the type- and value-dependence flags for this /// declaration reference expression. void computeDependence(const ASTContext &C); @@ -1031,7 +1047,7 @@ public: NamedDecl *FoundD = nullptr, const TemplateArgumentListInfo *TemplateArgs = nullptr); - /// \brief Construct an empty declaration reference expression. + /// Construct an empty declaration reference expression. static DeclRefExpr *CreateEmpty(const ASTContext &Context, bool HasQualifier, bool HasFoundDecl, @@ -1051,11 +1067,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; - /// \brief Determine whether this declaration reference was preceded by a + /// Determine whether this declaration reference was preceded by a /// C++ nested-name-specifier, e.g., \c N::foo. bool hasQualifier() const { return DeclRefExprBits.HasQualifier; } - /// \brief If the name was qualified, retrieves the nested-name-specifier + /// If the name was qualified, retrieves the nested-name-specifier /// that precedes the name, with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { if (!hasQualifier()) @@ -1063,13 +1079,13 @@ public: return *getTrailingObjects<NestedNameSpecifierLoc>(); } - /// \brief If the name was qualified, retrieves the nested-name-specifier + /// If the name was qualified, retrieves the nested-name-specifier /// that precedes the name. Otherwise, returns NULL. NestedNameSpecifier *getQualifier() const { return getQualifierLoc().getNestedNameSpecifier(); } - /// \brief Get the NamedDecl through which this reference occurred. + /// Get the NamedDecl through which this reference occurred. /// /// This Decl may be different from the ValueDecl actually referred to in the /// presence of using declarations, etc. It always returns non-NULL, and may @@ -1079,7 +1095,7 @@ public: return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; } - /// \brief Get the NamedDecl through which this reference occurred. + /// Get the NamedDecl through which this reference occurred. /// See non-const variant. const NamedDecl *getFoundDecl() const { return hasFoundDecl() ? *getTrailingObjects<NamedDecl *>() : D; @@ -1089,36 +1105,36 @@ public: return DeclRefExprBits.HasTemplateKWAndArgsInfo; } - /// \brief Retrieve the location of the template keyword preceding + /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } - /// \brief Retrieve the location of the left angle bracket starting the + /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } - /// \brief Retrieve the location of the right angle bracket ending the + /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!hasTemplateKWAndArgsInfo()) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->RAngleLoc; } - /// \brief Determines whether the name in this declaration reference + /// Determines whether the name in this declaration reference /// was preceded by the template keyword. bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - /// \brief Determines whether this declaration reference was followed by an + /// Determines whether this declaration reference was followed by an /// explicit template argument list. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Copies the template arguments (if present) into the given + /// Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) @@ -1126,7 +1142,7 @@ public: getTrailingObjects<TemplateArgumentLoc>(), List); } - /// \brief Retrieve the template arguments provided as part of this + /// Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) @@ -1135,7 +1151,7 @@ public: return getTrailingObjects<TemplateArgumentLoc>(); } - /// \brief Retrieve the number of template arguments provided as part of this + /// Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) @@ -1148,19 +1164,19 @@ public: return {getTemplateArgs(), getNumTemplateArgs()}; } - /// \brief Returns true if this expression refers to a function that + /// Returns true if this expression refers to a function that /// was resolved from an overloaded set having size greater than 1. bool hadMultipleCandidates() const { return DeclRefExprBits.HadMultipleCandidates; } - /// \brief Sets the flag telling whether this expression refers to + /// Sets the flag telling whether this expression refers to /// a function that was resolved from an overloaded set having size /// greater than 1. void setHadMultipleCandidates(bool V = true) { DeclRefExprBits.HadMultipleCandidates = V; } - /// \brief Does this DeclRefExpr refer to an enclosing local or a captured + /// Does this DeclRefExpr refer to an enclosing local or a captured /// variable? bool refersToEnclosingVariableOrCapture() const { return DeclRefExprBits.RefersToEnclosingVariableOrCapture; @@ -1184,17 +1200,18 @@ public: friend class ASTStmtWriter; }; -/// \brief [C99 6.4.2.2] - A predefined identifier such as __func__. +/// [C99 6.4.2.2] - A predefined identifier such as __func__. class PredefinedExpr : public Expr { public: enum IdentType { Func, Function, - LFunction, // Same as Function, but as wide string. + LFunction, // Same as Function, but as wide string. FuncDName, FuncSig, + LFuncSig, // Same as FuncSig, but as as wide string PrettyFunction, - /// \brief The same as PrettyFunction, except that the + /// The same as PrettyFunction, except that the /// 'virtual' keyword is omitted for virtual member functions. PrettyFunctionNoVirtual }; @@ -1208,7 +1225,7 @@ public: PredefinedExpr(SourceLocation L, QualType FNTy, IdentType IT, StringLiteral *SL); - /// \brief Construct an empty predefined expression. + /// Construct an empty predefined expression. explicit PredefinedExpr(EmptyShell Empty) : Expr(PredefinedExprClass, Empty), Loc(), Type(Func), FnName(nullptr) {} @@ -1241,7 +1258,7 @@ public: friend class ASTStmtReader; }; -/// \brief Used by IntegerLiteral/FloatingLiteral to store the numeric without +/// Used by IntegerLiteral/FloatingLiteral to store the numeric without /// leaking memory. /// /// For large floats/integers, APFloat/APInt will allocate memory from the heap @@ -1295,7 +1312,7 @@ public: class IntegerLiteral : public Expr, public APIntStorage { SourceLocation Loc; - /// \brief Construct an empty integer literal. + /// Construct an empty integer literal. explicit IntegerLiteral(EmptyShell Empty) : Expr(IntegerLiteralClass, Empty) { } @@ -1305,19 +1322,19 @@ public: IntegerLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l); - /// \brief Returns a new integer literal with value 'V' and type 'type'. + /// Returns a new integer literal with value 'V' and type 'type'. /// \param type - either IntTy, LongTy, LongLongTy, UnsignedIntTy, /// UnsignedLongTy, or UnsignedLongLongTy which should match the size of V /// \param V - the value that the returned integer literal contains. static IntegerLiteral *Create(const ASTContext &C, const llvm::APInt &V, QualType type, SourceLocation l); - /// \brief Returns a new empty integer literal. + /// Returns a new empty integer literal. static IntegerLiteral *Create(const ASTContext &C, EmptyShell Empty); SourceLocation getLocStart() const LLVM_READONLY { return Loc; } SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } - /// \brief Retrieve the location of the literal. + /// Retrieve the location of the literal. SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation Location) { Loc = Location; } @@ -1335,6 +1352,47 @@ public: } }; +class FixedPointLiteral : public Expr, public APIntStorage { + SourceLocation Loc; + unsigned Scale; + + /// \brief Construct an empty integer literal. + explicit FixedPointLiteral(EmptyShell Empty) + : Expr(FixedPointLiteralClass, Empty) {} + + public: + FixedPointLiteral(const ASTContext &C, const llvm::APInt &V, QualType type, + SourceLocation l, unsigned Scale); + + // Store the int as is without any bit shifting. + static FixedPointLiteral *CreateFromRawInt(const ASTContext &C, + const llvm::APInt &V, + QualType type, SourceLocation l, + unsigned Scale); + + SourceLocation getLocStart() const LLVM_READONLY { return Loc; } + SourceLocation getLocEnd() const LLVM_READONLY { return Loc; } + + /// \brief Retrieve the location of the literal. + SourceLocation getLocation() const { return Loc; } + + void setLocation(SourceLocation Location) { Loc = Location; } + + static bool classof(const Stmt *T) { + return T->getStmtClass() == FixedPointLiteralClass; + } + + std::string getValueAsString(unsigned Radix) const; + + // Iterators + child_range children() { + return child_range(child_iterator(), child_iterator()); + } + const_child_range children() const { + return const_child_range(const_child_iterator(), const_child_iterator()); + } +}; + class CharacterLiteral : public Expr { public: enum CharacterKind { @@ -1358,7 +1416,7 @@ public: CharacterLiteralBits.Kind = kind; } - /// \brief Construct an empty character literal. + /// Construct an empty character literal. CharacterLiteral(EmptyShell Empty) : Expr(CharacterLiteralClass, Empty) { } SourceLocation getLocation() const { return Loc; } @@ -1394,7 +1452,7 @@ class FloatingLiteral : public Expr, private APFloatStorage { FloatingLiteral(const ASTContext &C, const llvm::APFloat &V, bool isexact, QualType Type, SourceLocation L); - /// \brief Construct an empty floating-point literal. + /// Construct an empty floating-point literal. explicit FloatingLiteral(const ASTContext &C, EmptyShell Empty); public: @@ -1468,7 +1526,7 @@ public: false, false), Val(val) {} - /// \brief Build an empty imaginary literal. + /// Build an empty imaginary literal. explicit ImaginaryLiteral(EmptyShell Empty) : Expr(ImaginaryLiteralClass, Empty) { } @@ -1551,7 +1609,7 @@ public: return Create(C, Str, Kind, Pascal, Ty, &Loc, 1); } - /// \brief Construct an empty string literal. + /// Construct an empty string literal. static StringLiteral *CreateEmpty(const ASTContext &C, unsigned NumStrs); StringRef getString() const { @@ -1590,7 +1648,7 @@ public: unsigned getLength() const { return Length; } unsigned getCharByteWidth() const { return CharByteWidth; } - /// \brief Sets the string data to the given string data. + /// Sets the string data to the given string data. void setString(const ASTContext &C, StringRef Str, StringKind Kind, bool IsPascal); @@ -1604,6 +1662,14 @@ public: bool isUTF32() const { return Kind == UTF32; } bool isPascal() const { return IsPascal; } + bool containsNonAscii() const { + StringRef Str = getString(); + for (unsigned i = 0, e = Str.size(); i != e; ++i) + if (!isASCII(Str[i])) + return true; + return false; + } + bool containsNonAsciiOrNull() const { StringRef Str = getString(); for (unsigned i = 0, e = Str.size(); i != e; ++i) @@ -1674,7 +1740,7 @@ public: val->containsUnexpandedParameterPack()), L(l), R(r), Val(val) {} - /// \brief Construct an empty parenthesized expression. + /// Construct an empty parenthesized expression. explicit ParenExpr(EmptyShell Empty) : Expr(ParenExprClass, Empty) { } @@ -1685,11 +1751,11 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return L; } SourceLocation getLocEnd() const LLVM_READONLY { return R; } - /// \brief Get the location of the left parentheses '('. + /// Get the location of the left parentheses '('. SourceLocation getLParen() const { return L; } void setLParen(SourceLocation Loc) { L = Loc; } - /// \brief Get the location of the right parentheses ')'. + /// Get the location of the right parentheses ')'. SourceLocation getRParen() const { return R; } void setRParen(SourceLocation Loc) { R = Loc; } @@ -1720,21 +1786,21 @@ public: private: unsigned Opc : 5; + unsigned CanOverflow : 1; SourceLocation Loc; Stmt *Val; public: - - UnaryOperator(Expr *input, Opcode opc, QualType type, - ExprValueKind VK, ExprObjectKind OK, SourceLocation l) - : Expr(UnaryOperatorClass, type, VK, OK, - input->isTypeDependent() || type->isDependentType(), - input->isValueDependent(), - (input->isInstantiationDependent() || - type->isInstantiationDependentType()), - input->containsUnexpandedParameterPack()), - Opc(opc), Loc(l), Val(input) {} - - /// \brief Build an empty unary operator. + UnaryOperator(Expr *input, Opcode opc, QualType type, ExprValueKind VK, + ExprObjectKind OK, SourceLocation l, bool CanOverflow) + : Expr(UnaryOperatorClass, type, VK, OK, + input->isTypeDependent() || type->isDependentType(), + input->isValueDependent(), + (input->isInstantiationDependent() || + type->isInstantiationDependentType()), + input->containsUnexpandedParameterPack()), + Opc(opc), CanOverflow(CanOverflow), Loc(l), Val(input) {} + + /// Build an empty unary operator. explicit UnaryOperator(EmptyShell Empty) : Expr(UnaryOperatorClass, Empty), Opc(UO_AddrOf) { } @@ -1748,6 +1814,15 @@ public: SourceLocation getOperatorLoc() const { return Loc; } void setOperatorLoc(SourceLocation L) { Loc = L; } + /// Returns true if the unary operator can cause an overflow. For instance, + /// signed int i = INT_MAX; i++; + /// signed char c = CHAR_MAX; c++; + /// Due to integer promotions, c++ is promoted to an int before the postfix + /// increment, and the result is an int that cannot overflow. However, i++ + /// can overflow. + bool canOverflow() const { return CanOverflow; } + void setCanOverflow(bool C) { CanOverflow = C; } + /// isPostfix - Return true if this is a postfix operation, like x++. static bool isPostfix(Opcode Op) { return Op == UO_PostInc || Op == UO_PostDec; @@ -1789,11 +1864,11 @@ public: /// corresponds to, e.g. "sizeof" or "[pre]++" static StringRef getOpcodeStr(Opcode Op); - /// \brief Retrieve the unary opcode that corresponds to the given + /// Retrieve the unary opcode that corresponds to the given /// overloaded operator. static Opcode getOverloadedOpcode(OverloadedOperatorKind OO, bool Postfix); - /// \brief Retrieve the overloaded operator kind that corresponds to + /// Retrieve the overloaded operator kind that corresponds to /// the given unary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); @@ -1821,15 +1896,15 @@ public: // __builtin_offsetof(type, identifier(.identifier|[expr])*) class OffsetOfNode { public: - /// \brief The kind of offsetof node we have. + /// The kind of offsetof node we have. enum Kind { - /// \brief An index into an array. + /// An index into an array. Array = 0x00, - /// \brief A field. + /// A field. Field = 0x01, - /// \brief A field in a dependent type, known only by its name. + /// A field in a dependent type, known only by its name. Identifier = 0x02, - /// \brief An implicit indirection through a C++ base class, when the + /// An implicit indirection through a C++ base class, when the /// field found is in a base class. Base = 0x03 }; @@ -1837,10 +1912,10 @@ public: private: enum { MaskBits = 2, Mask = 0x03 }; - /// \brief The source range that covers this part of the designator. + /// The source range that covers this part of the designator. SourceRange Range; - /// \brief The data describing the designator, which comes in three + /// The data describing the designator, which comes in three /// different forms, depending on the lower two bits. /// - An unsigned index into the array of Expr*'s stored after this node /// in memory, for [constant-expression] designators. @@ -1852,53 +1927,53 @@ private: uintptr_t Data; public: - /// \brief Create an offsetof node that refers to an array element. + /// Create an offsetof node that refers to an array element. OffsetOfNode(SourceLocation LBracketLoc, unsigned Index, SourceLocation RBracketLoc) : Range(LBracketLoc, RBracketLoc), Data((Index << 2) | Array) {} - /// \brief Create an offsetof node that refers to a field. + /// Create an offsetof node that refers to a field. OffsetOfNode(SourceLocation DotLoc, FieldDecl *Field, SourceLocation NameLoc) : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), Data(reinterpret_cast<uintptr_t>(Field) | OffsetOfNode::Field) {} - /// \brief Create an offsetof node that refers to an identifier. + /// Create an offsetof node that refers to an identifier. OffsetOfNode(SourceLocation DotLoc, IdentifierInfo *Name, SourceLocation NameLoc) : Range(DotLoc.isValid() ? DotLoc : NameLoc, NameLoc), Data(reinterpret_cast<uintptr_t>(Name) | Identifier) {} - /// \brief Create an offsetof node that refers into a C++ base class. + /// Create an offsetof node that refers into a C++ base class. explicit OffsetOfNode(const CXXBaseSpecifier *Base) : Range(), Data(reinterpret_cast<uintptr_t>(Base) | OffsetOfNode::Base) {} - /// \brief Determine what kind of offsetof node this is. + /// Determine what kind of offsetof node this is. Kind getKind() const { return static_cast<Kind>(Data & Mask); } - /// \brief For an array element node, returns the index into the array + /// For an array element node, returns the index into the array /// of expressions. unsigned getArrayExprIndex() const { assert(getKind() == Array); return Data >> 2; } - /// \brief For a field offsetof node, returns the field. + /// For a field offsetof node, returns the field. FieldDecl *getField() const { assert(getKind() == Field); return reinterpret_cast<FieldDecl *>(Data & ~(uintptr_t)Mask); } - /// \brief For a field or identifier offsetof node, returns the name of + /// For a field or identifier offsetof node, returns the name of /// the field. IdentifierInfo *getFieldName() const; - /// \brief For a base class node, returns the base specifier. + /// For a base class node, returns the base specifier. CXXBaseSpecifier *getBase() const { assert(getKind() == Base); return reinterpret_cast<CXXBaseSpecifier *>(Data & ~(uintptr_t)Mask); } - /// \brief Retrieve the source range that covers this offsetof node. + /// Retrieve the source range that covers this offsetof node. /// /// For an array element node, the source range contains the locations of /// the square brackets. For a field or identifier node, the source range @@ -1961,7 +2036,7 @@ public: SourceLocation getOperatorLoc() const { return OperatorLoc; } void setOperatorLoc(SourceLocation L) { OperatorLoc = L; } - /// \brief Return the location of the right parentheses. + /// Return the location of the right parentheses. SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation R) { RParenLoc = R; } @@ -2055,7 +2130,7 @@ public: QualType resultType, SourceLocation op, SourceLocation rp); - /// \brief Construct an empty sizeof/alignof expression. + /// Construct an empty sizeof/alignof expression. explicit UnaryExprOrTypeTraitExpr(EmptyShell Empty) : Expr(UnaryExprOrTypeTraitExprClass, Empty) { } @@ -2138,7 +2213,7 @@ public: SubExprs[RHS] = rhs; } - /// \brief Create an empty array subscript expression. + /// Create an empty array subscript expression. explicit ArraySubscriptExpr(EmptyShell Shell) : Expr(ArraySubscriptExprClass, Shell) { } @@ -2160,19 +2235,19 @@ public: void setRHS(Expr *E) { SubExprs[RHS] = E; } Expr *getBase() { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); + return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS(); } const Expr *getBase() const { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getLHS():getRHS()); + return getRHS()->getType()->isIntegerType() ? getLHS() : getRHS(); } Expr *getIdx() { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); + return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS(); } const Expr *getIdx() const { - return cast<Expr>(getRHS()->getType()->isIntegerType() ? getRHS():getLHS()); + return getRHS()->getType()->isIntegerType() ? getRHS() : getLHS(); } SourceLocation getLocStart() const LLVM_READONLY { @@ -2243,7 +2318,7 @@ public: CallExpr(const ASTContext& C, Expr *fn, ArrayRef<Expr*> args, QualType t, ExprValueKind VK, SourceLocation rparenloc); - /// \brief Build an empty call expression. + /// Build an empty call expression. CallExpr(const ASTContext &C, StmtClass SC, EmptyShell Empty); const Expr *getCallee() const { return cast<Expr>(SubExprs[FN]); } @@ -2255,7 +2330,7 @@ public: return const_cast<CallExpr*>(this)->getCalleeDecl(); } - /// \brief If the callee is a FunctionDecl, return it. Otherwise return 0. + /// If the callee is a FunctionDecl, return it. Otherwise return 0. FunctionDecl *getDirectCallee(); const FunctionDecl *getDirectCallee() const { return const_cast<CallExpr*>(this)->getDirectCallee(); @@ -2265,7 +2340,7 @@ public: /// unsigned getNumArgs() const { return NumArgs; } - /// \brief Retrieve the call arguments. + /// Retrieve the call arguments. Expr **getArgs() { return reinterpret_cast<Expr **>(SubExprs+getNumPreArgs()+PREARGS_START); } @@ -2333,7 +2408,7 @@ public: /// of the callee. If not, return 0. unsigned getBuiltinCallee() const; - /// \brief Returns \c true if this is a call to a builtin which does not + /// Returns \c true if this is a call to a builtin which does not /// evaluate side-effects within its arguments. bool isUnevaluatedBuiltinCall(const ASTContext &Ctx) const; @@ -2348,6 +2423,10 @@ public: SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; + /// Return true if this is a call to __assume() or __builtin_assume() with + /// a non-value-dependent constant parameter evaluating as false. + bool isBuiltinAssumeFalse(const ASTContext &Ctx) const; + bool isCallToStdMove() const { const FunctionDecl* FD = getDirectCallee(); return getNumArgs() == 1 && FD && FD->isInStdNamespace() && @@ -2373,11 +2452,11 @@ public: /// Extra data stored in some MemberExpr objects. struct MemberExprNameQualifier { - /// \brief The nested-name-specifier that qualifies the name, including + /// The nested-name-specifier that qualifies the name, including /// source-location information. NestedNameSpecifierLoc QualifierLoc; - /// \brief The DeclAccessPair through which the MemberDecl was found due to + /// The DeclAccessPair through which the MemberDecl was found due to /// name qualifiers. DeclAccessPair FoundDecl; }; @@ -2410,20 +2489,20 @@ class MemberExpr final /// IsArrow - True if this is "X->F", false if this is "X.F". bool IsArrow : 1; - /// \brief True if this member expression used a nested-name-specifier to + /// True if this member expression used a nested-name-specifier to /// refer to the member, e.g., "x->Base::f", or found its member via a using /// declaration. When true, a MemberExprNameQualifier /// structure is allocated immediately after the MemberExpr. bool HasQualifierOrFoundDecl : 1; - /// \brief True if this member expression specified a template keyword + /// True if this member expression specified a template keyword /// and/or a template argument list explicitly, e.g., x->f<int>, /// x->template f, x->template f<int>. /// When true, an ASTTemplateKWAndArgsInfo structure and its /// TemplateArguments (if any) are present. bool HasTemplateKWAndArgsInfo : 1; - /// \brief True if this member expression refers to a method that + /// True if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. bool HadMultipleCandidates : 1; @@ -2476,14 +2555,14 @@ public: void setBase(Expr *E) { Base = E; } Expr *getBase() const { return cast<Expr>(Base); } - /// \brief Retrieve the member declaration to which this expression refers. + /// Retrieve the member declaration to which this expression refers. /// /// The returned declaration will be a FieldDecl or (in C++) a VarDecl (for /// static data members), a CXXMethodDecl, or an EnumConstantDecl. ValueDecl *getMemberDecl() const { return MemberDecl; } void setMemberDecl(ValueDecl *D) { MemberDecl = D; } - /// \brief Retrieves the declaration found by lookup. + /// Retrieves the declaration found by lookup. DeclAccessPair getFoundDecl() const { if (!HasQualifierOrFoundDecl) return DeclAccessPair::make(getMemberDecl(), @@ -2491,12 +2570,12 @@ public: return getTrailingObjects<MemberExprNameQualifier>()->FoundDecl; } - /// \brief Determines whether this member expression actually had + /// Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. bool hasQualifier() const { return getQualifier() != nullptr; } - /// \brief If the member name was qualified, retrieves the + /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name, with source-location /// information. NestedNameSpecifierLoc getQualifierLoc() const { @@ -2506,28 +2585,28 @@ public: return getTrailingObjects<MemberExprNameQualifier>()->QualifierLoc; } - /// \brief If the member name was qualified, retrieves the + /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// NULL. NestedNameSpecifier *getQualifier() const { return getQualifierLoc().getNestedNameSpecifier(); } - /// \brief Retrieve the location of the template keyword preceding + /// Retrieve the location of the template keyword preceding /// the member name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } - /// \brief Retrieve the location of the left angle bracket starting the + /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } - /// \brief Retrieve the location of the right angle bracket ending the + /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); @@ -2537,11 +2616,11 @@ public: /// Determines whether the member name was preceded by the template keyword. bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - /// \brief Determines whether the member name was followed by an + /// Determines whether the member name was followed by an /// explicit template argument list. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Copies the template arguments (if present) into the given + /// Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) @@ -2549,7 +2628,7 @@ public: getTrailingObjects<TemplateArgumentLoc>(), List); } - /// \brief Retrieve the template arguments provided as part of this + /// Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) @@ -2558,7 +2637,7 @@ public: return getTrailingObjects<TemplateArgumentLoc>(); } - /// \brief Retrieve the number of template arguments provided as part of this + /// Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) @@ -2571,7 +2650,7 @@ public: return {getTemplateArgs(), getNumTemplateArgs()}; } - /// \brief Retrieve the member declaration name info. + /// Retrieve the member declaration name info. DeclarationNameInfo getMemberNameInfo() const { return DeclarationNameInfo(MemberDecl->getDeclName(), MemberLoc, MemberDNLoc); @@ -2592,24 +2671,24 @@ public: SourceLocation getExprLoc() const LLVM_READONLY { return MemberLoc; } - /// \brief Determine whether the base of this explicit is implicit. + /// Determine whether the base of this explicit is implicit. bool isImplicitAccess() const { return getBase() && getBase()->isImplicitCXXThis(); } - /// \brief Returns true if this member expression refers to a method that + /// Returns true if this member expression refers to a method that /// was resolved from an overloaded set having size greater than 1. bool hadMultipleCandidates() const { return HadMultipleCandidates; } - /// \brief Sets the flag telling whether this expression refers to + /// Sets the flag telling whether this expression refers to /// a method that was resolved from an overloaded set having size /// greater than 1. void setHadMultipleCandidates(bool V = true) { HadMultipleCandidates = V; } - /// \brief Returns true if virtual dispatch is performed. + /// Returns true if virtual dispatch is performed. /// If the member access is fully qualified, (i.e. X::f()), virtual /// dispatching is not performed. In -fapple-kext mode qualified /// calls to virtual method will still go through the vtable. @@ -2656,7 +2735,7 @@ public: init->containsUnexpandedParameterPack()), LParenLoc(lparenloc), TInfoAndScope(tinfo, fileScope), Init(init) {} - /// \brief Construct an empty compound literal. + /// Construct an empty compound literal. explicit CompoundLiteralExpr(EmptyShell Empty) : Expr(CompoundLiteralExprClass, Empty) { } @@ -2743,26 +2822,30 @@ protected: (op && op->containsUnexpandedParameterPack()))), Op(op) { CastExprBits.Kind = kind; + CastExprBits.PartOfExplicitCast = false; setBasePathSize(BasePathSize); assert(CastConsistency()); } - /// \brief Construct an empty cast. + /// Construct an empty cast. CastExpr(StmtClass SC, EmptyShell Empty, unsigned BasePathSize) : Expr(SC, Empty) { + CastExprBits.PartOfExplicitCast = false; setBasePathSize(BasePathSize); } public: CastKind getCastKind() const { return (CastKind) CastExprBits.Kind; } void setCastKind(CastKind K) { CastExprBits.Kind = K; } - const char *getCastKindName() const; + + static const char *getCastKindName(CastKind CK); + const char *getCastKindName() const { return getCastKindName(getCastKind()); } Expr *getSubExpr() { return cast<Expr>(Op); } const Expr *getSubExpr() const { return cast<Expr>(Op); } void setSubExpr(Expr *E) { Op = E; } - /// \brief Retrieve the cast subexpression as it was written in the source + /// Retrieve the cast subexpression as it was written in the source /// code, looking through any implicit casts or other intermediate nodes /// introduced by semantic analysis. Expr *getSubExprAsWritten(); @@ -2770,6 +2853,10 @@ public: return const_cast<CastExpr *>(this)->getSubExprAsWritten(); } + /// If this cast applies a user-defined conversion, retrieve the conversion + /// function that it invokes. + NamedDecl *getConversionFunction() const; + typedef CXXBaseSpecifier **path_iterator; typedef const CXXBaseSpecifier * const *path_const_iterator; bool path_empty() const { return CastExprBits.BasePathSize == 0; } @@ -2828,7 +2915,7 @@ private: : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, BasePathLength) { } - /// \brief Construct an empty implicit cast. + /// Construct an empty implicit cast. explicit ImplicitCastExpr(EmptyShell Shell, unsigned PathSize) : CastExpr(ImplicitCastExprClass, Shell, PathSize) { } @@ -2839,6 +2926,11 @@ public: : CastExpr(ImplicitCastExprClass, ty, VK, kind, op, 0) { } + bool isPartOfExplicitCast() const { return CastExprBits.PartOfExplicitCast; } + void setIsPartOfExplicitCast(bool PartOfExplicitCast) { + CastExprBits.PartOfExplicitCast = PartOfExplicitCast; + } + static ImplicitCastExpr *Create(const ASTContext &Context, QualType T, CastKind Kind, Expr *Operand, const CXXCastPath *BasePath, @@ -2896,7 +2988,7 @@ protected: TypeSourceInfo *writtenTy) : CastExpr(SC, exprTy, VK, kind, op, PathSize), TInfo(writtenTy) {} - /// \brief Construct an empty explicit cast. + /// Construct an empty explicit cast. ExplicitCastExpr(StmtClass SC, EmptyShell Shell, unsigned PathSize) : CastExpr(SC, Shell, PathSize) { } @@ -2931,7 +3023,7 @@ class CStyleCastExpr final : ExplicitCastExpr(CStyleCastExprClass, exprTy, vk, kind, op, PathSize, writtenTy), LPLoc(l), RPLoc(r) {} - /// \brief Construct an empty C-style explicit cast. + /// Construct an empty C-style explicit cast. explicit CStyleCastExpr(EmptyShell Shell, unsigned PathSize) : ExplicitCastExpr(CStyleCastExprClass, Shell, PathSize) { } @@ -2964,7 +3056,7 @@ public: friend class CastExpr; }; -/// \brief A builtin binary operation expression such as "x + y" or "x <= y". +/// A builtin binary operation expression such as "x + y" or "x <= y". /// /// This expression node kind describes a builtin binary operation, /// such as "x + y" for integer values "x" and "y". The operands will @@ -3015,7 +3107,7 @@ public: "Use CompoundAssignOperator for compound assignments"); } - /// \brief Construct an empty binary operator. + /// Construct an empty binary operator. explicit BinaryOperator(EmptyShell Empty) : Expr(BinaryOperatorClass, Empty), Opc(BO_Comma) { } @@ -3044,11 +3136,11 @@ public: StringRef getOpcodeStr() const { return getOpcodeStr(getOpcode()); } - /// \brief Retrieve the binary opcode that corresponds to the given + /// Retrieve the binary opcode that corresponds to the given /// overloaded operator. static Opcode getOverloadedOpcode(OverloadedOperatorKind OO); - /// \brief Retrieve the overloaded operator kind that corresponds to + /// Retrieve the overloaded operator kind that corresponds to /// the given binary opcode. static OverloadedOperatorKind getOverloadedOperator(Opcode Opc); @@ -3078,7 +3170,7 @@ public: static Opcode negateComparisonOp(Opcode Opc) { switch (Opc) { default: - llvm_unreachable("Not a comparsion operator."); + llvm_unreachable("Not a comparison operator."); case BO_LT: return BO_GE; case BO_GT: return BO_LE; case BO_LE: return BO_GT; @@ -3091,7 +3183,7 @@ public: static Opcode reverseComparisonOp(Opcode Opc) { switch (Opc) { default: - llvm_unreachable("Not a comparsion operator."); + llvm_unreachable("Not a comparison operator."); case BO_LT: return BO_GT; case BO_GT: return BO_LT; case BO_LE: return BO_GE; @@ -3204,7 +3296,7 @@ public: "Only should be used for compound assignments"); } - /// \brief Build an empty compound assignment operator expression. + /// Build an empty compound assignment operator expression. explicit CompoundAssignOperator(EmptyShell Empty) : BinaryOperator(CompoundAssignOperatorClass, Empty) { } @@ -3294,7 +3386,7 @@ public: SubExprs[RHS] = rhs; } - /// \brief Build an empty conditional operator. + /// Build an empty conditional operator. explicit ConditionalOperator(EmptyShell Empty) : AbstractConditionalOperator(ConditionalOperatorClass, Empty) { } @@ -3372,30 +3464,30 @@ public: assert(OpaqueValue->getSourceExpr() == common && "Wrong opaque value"); } - /// \brief Build an empty conditional operator. + /// Build an empty conditional operator. explicit BinaryConditionalOperator(EmptyShell Empty) : AbstractConditionalOperator(BinaryConditionalOperatorClass, Empty) { } - /// \brief getCommon - Return the common expression, written to the + /// getCommon - Return the common expression, written to the /// left of the condition. The opaque value will be bound to the /// result of this expression. Expr *getCommon() const { return cast<Expr>(SubExprs[COMMON]); } - /// \brief getOpaqueValue - Return the opaque value placeholder. + /// getOpaqueValue - Return the opaque value placeholder. OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } - /// \brief getCond - Return the condition expression; this is defined + /// getCond - Return the condition expression; this is defined /// in terms of the opaque value. Expr *getCond() const { return cast<Expr>(SubExprs[COND]); } - /// \brief getTrueExpr - Return the subexpression which will be + /// getTrueExpr - Return the subexpression which will be /// evaluated if the condition evaluates to true; this is defined /// in terms of the opaque value. Expr *getTrueExpr() const { return cast<Expr>(SubExprs[LHS]); } - /// \brief getFalseExpr - Return the subexpression which will be + /// getFalseExpr - Return the subexpression which will be /// evaluated if the condnition evaluates to false; this is /// defined in terms of the opaque value. Expr *getFalseExpr() const { @@ -3451,7 +3543,7 @@ public: false), AmpAmpLoc(AALoc), LabelLoc(LLoc), Label(L) {} - /// \brief Build an empty address of a label expression. + /// Build an empty address of a label expression. explicit AddrLabelExpr(EmptyShell Empty) : Expr(AddrLabelExprClass, Empty) { } @@ -3498,7 +3590,7 @@ public: T->isDependentType(), false, false, false), SubStmt(substmt), LParenLoc(lp), RParenLoc(rp) { } - /// \brief Build an empty statement expression. + /// Build an empty statement expression. explicit StmtExpr(EmptyShell Empty) : Expr(StmtExprClass, Empty) { } CompoundStmt *getSubStmt() { return cast<CompoundStmt>(SubStmt); } @@ -3544,7 +3636,7 @@ public: ShuffleVectorExpr(const ASTContext &C, ArrayRef<Expr*> args, QualType Type, SourceLocation BLoc, SourceLocation RP); - /// \brief Build an empty vector-shuffle expression. + /// Build an empty vector-shuffle expression. explicit ShuffleVectorExpr(EmptyShell Empty) : Expr(ShuffleVectorExprClass, Empty), SubExprs(nullptr) { } @@ -3566,7 +3658,7 @@ public: /// pointers. unsigned getNumSubExprs() const { return NumExprs; } - /// \brief Retrieve the array of expressions. + /// Retrieve the array of expressions. Expr **getSubExprs() { return reinterpret_cast<Expr **>(SubExprs); } /// getExpr - Return the Expr at the specified index. @@ -3684,7 +3776,7 @@ public: SubExprs[RHS] = rhs; } - /// \brief Build an empty __builtin_choose_expr. + /// Build an empty __builtin_choose_expr. explicit ChooseExpr(EmptyShell Empty) : Expr(ChooseExprClass, Empty) { } /// isConditionTrue - Return whether the condition is true (i.e. not @@ -3751,7 +3843,7 @@ public: false), TokenLoc(Loc) { } - /// \brief Build an empty GNU __null expression. + /// Build an empty GNU __null expression. explicit GNUNullExpr(EmptyShell Empty) : Expr(GNUNullExprClass, Empty) { } /// getTokenLocation - The location of the __null token. @@ -3824,7 +3916,7 @@ public: } }; -/// @brief Describes an C or C++ initializer list. +/// Describes an C or C++ initializer list. /// /// InitListExpr describes an initializer list, which can be used to /// initialize objects of different types, including @@ -3882,7 +3974,7 @@ class InitListExpr : public Expr { /// - the semantic form, if this is in syntactic form. llvm::PointerIntPair<InitListExpr *, 1, bool> AltForm; - /// \brief Either: + /// Either: /// If this initializer list initializes an array with more elements than /// there are initializers in the list, specifies an expression to be used /// for value initialization of the rest of the elements. @@ -3895,16 +3987,16 @@ public: InitListExpr(const ASTContext &C, SourceLocation lbraceloc, ArrayRef<Expr*> initExprs, SourceLocation rbraceloc); - /// \brief Build an empty initializer list. + /// Build an empty initializer list. explicit InitListExpr(EmptyShell Empty) : Expr(InitListExprClass, Empty), AltForm(nullptr, true) { } unsigned getNumInits() const { return InitExprs.size(); } - /// \brief Retrieve the set of initializers. + /// Retrieve the set of initializers. Expr **getInits() { return reinterpret_cast<Expr **>(InitExprs.data()); } - /// \brief Retrieve the set of initializers. + /// Retrieve the set of initializers. Expr * const *getInits() const { return reinterpret_cast<Expr * const *>(InitExprs.data()); } @@ -3940,10 +4032,10 @@ public: } } - /// \brief Reserve space for some number of initializers. + /// Reserve space for some number of initializers. void reserveInits(const ASTContext &C, unsigned NumInits); - /// @brief Specify the number of initializers + /// Specify the number of initializers /// /// If there are more than @p NumInits initializers, the remaining /// initializers will be destroyed. If there are fewer than @p @@ -3951,7 +4043,7 @@ public: /// unknown initializers. void resizeInits(const ASTContext &Context, unsigned NumInits); - /// @brief Updates the initializer at index @p Init with the new + /// Updates the initializer at index @p Init with the new /// expression @p expr, and returns the old expression at that /// location. /// @@ -3960,7 +4052,7 @@ public: /// accommodate the new entry. Expr *updateInit(const ASTContext &C, unsigned Init, Expr *expr); - /// \brief If this initializer list initializes an array with more elements + /// If this initializer list initializes an array with more elements /// than there are initializers in the list, specifies an expression to be /// used for value initialization of the rest of the elements. Expr *getArrayFiller() { @@ -3971,11 +4063,11 @@ public: } void setArrayFiller(Expr *filler); - /// \brief Return true if this is an array initializer and its array "filler" + /// Return true if this is an array initializer and its array "filler" /// has been set. bool hasArrayFiller() const { return getArrayFiller(); } - /// \brief If this initializes a union, specifies which field in the + /// If this initializes a union, specifies which field in the /// union to initialize. /// /// Typically, this field is the first named field within the @@ -4083,7 +4175,7 @@ public: friend class ASTStmtWriter; }; -/// @brief Represents a C99 designated initializer expression. +/// Represents a C99 designated initializer expression. /// /// A designated initializer expression (C99 6.7.8) contains one or /// more designators (which can be field designators, array @@ -4107,7 +4199,7 @@ class DesignatedInitExpr final : public Expr, private llvm::TrailingObjects<DesignatedInitExpr, Stmt *> { public: - /// \brief Forward declaration of the Designator class. + /// Forward declaration of the Designator class. class Designator; private: @@ -4127,7 +4219,7 @@ private: /// expressions used by array and array-range designators. unsigned NumSubExprs : 16; - /// \brief The designators in this designated initialization + /// The designators in this designated initialization /// expression. Designator *Designators; @@ -4172,14 +4264,14 @@ public: unsigned RBracketLoc; }; - /// @brief Represents a single C99 designator. + /// Represents a single C99 designator. /// /// @todo This class is infuriatingly similar to clang::Designator, /// but minor differences (storing indices vs. storing pointers) /// keep us from reusing it. Try harder, later, to rectify these /// differences. class Designator { - /// @brief The kind of designator this describes. + /// The kind of designator this describes. enum { FieldDesignator, ArrayDesignator, @@ -4197,7 +4289,7 @@ public: public: Designator() {} - /// @brief Initializes a field designator. + /// Initializes a field designator. Designator(const IdentifierInfo *FieldName, SourceLocation DotLoc, SourceLocation FieldLoc) : Kind(FieldDesignator) { @@ -4206,7 +4298,7 @@ public: Field.FieldLoc = FieldLoc.getRawEncoding(); } - /// @brief Initializes an array designator. + /// Initializes an array designator. Designator(unsigned Index, SourceLocation LBracketLoc, SourceLocation RBracketLoc) : Kind(ArrayDesignator) { @@ -4216,7 +4308,7 @@ public: ArrayOrRange.RBracketLoc = RBracketLoc.getRawEncoding(); } - /// @brief Initializes a GNU array-range designator. + /// Initializes a GNU array-range designator. Designator(unsigned Index, SourceLocation LBracketLoc, SourceLocation EllipsisLoc, SourceLocation RBracketLoc) : Kind(ArrayRangeDesignator) { @@ -4302,7 +4394,7 @@ public: static DesignatedInitExpr *CreateEmpty(const ASTContext &C, unsigned NumIndexExprs); - /// @brief Returns the number of designators in this initializer. + /// Returns the number of designators in this initializer. unsigned size() const { return NumDesignators; } // Iterator access to the designators. @@ -4326,17 +4418,17 @@ public: Expr *getArrayRangeStart(const Designator &D) const; Expr *getArrayRangeEnd(const Designator &D) const; - /// @brief Retrieve the location of the '=' that precedes the + /// Retrieve the location of the '=' that precedes the /// initializer value itself, if present. SourceLocation getEqualOrColonLoc() const { return EqualOrColonLoc; } void setEqualOrColonLoc(SourceLocation L) { EqualOrColonLoc = L; } - /// @brief Determines whether this designated initializer used the + /// Determines whether this designated initializer used the /// deprecated GNU syntax for designated initializers. bool usesGNUSyntax() const { return GNUSyntax; } void setGNUSyntax(bool GNU) { GNUSyntax = GNU; } - /// @brief Retrieve the initializer value. + /// Retrieve the initializer value. Expr *getInit() const { return cast<Expr>(*const_cast<DesignatedInitExpr*>(this)->child_begin()); } @@ -4345,7 +4437,7 @@ public: *child_begin() = init; } - /// \brief Retrieve the total number of subexpressions in this + /// Retrieve the total number of subexpressions in this /// designated initializer expression, including the actual /// initialized value and any expressions that occur within array /// and array-range designators. @@ -4361,7 +4453,7 @@ public: getTrailingObjects<Stmt *>()[Idx] = E; } - /// \brief Replaces the designator at index @p Idx with the series + /// Replaces the designator at index @p Idx with the series /// of designators in [First, Last). void ExpandDesignator(const ASTContext &C, unsigned Idx, const Designator *First, const Designator *Last); @@ -4388,7 +4480,7 @@ public: friend TrailingObjects; }; -/// \brief Represents a place-holder for an object not to be initialized by +/// Represents a place-holder for an object not to be initialized by /// anything. /// /// This only makes sense when it appears as part of an updater of a @@ -4471,7 +4563,7 @@ public: } }; -/// \brief Represents a loop initializing the elements of an array. +/// Represents a loop initializing the elements of an array. /// /// The need to initialize the elements of an array occurs in a number of /// contexts: @@ -4539,7 +4631,7 @@ public: friend class ASTStmtWriter; }; -/// \brief Represents the index of the current element of an array being +/// Represents the index of the current element of an array being /// initialized by an ArrayInitLoopExpr. This can only appear within the /// subexpression of an ArrayInitLoopExpr. class ArrayInitIndexExpr : public Expr { @@ -4569,7 +4661,7 @@ public: friend class ASTStmtReader; }; -/// \brief Represents an implicitly-generated value initialization of +/// Represents an implicitly-generated value initialization of /// an object of a given type. /// /// Implicit value initializations occur within semantic initializer @@ -4583,7 +4675,7 @@ public: : Expr(ImplicitValueInitExprClass, ty, VK_RValue, OK_Ordinary, false, false, ty->isInstantiationDependentType(), false) { } - /// \brief Construct an empty implicit value initialization. + /// Construct an empty implicit value initialization. explicit ImplicitValueInitExpr(EmptyShell Empty) : Expr(ImplicitValueInitExprClass, Empty) { } @@ -4612,7 +4704,7 @@ public: ParenListExpr(const ASTContext& C, SourceLocation lparenloc, ArrayRef<Expr*> exprs, SourceLocation rparenloc); - /// \brief Build an empty paren list. + /// Build an empty paren list. explicit ParenListExpr(EmptyShell Empty) : Expr(ParenListExprClass, Empty) { } unsigned getNumExprs() const { return NumExprs; } @@ -4655,7 +4747,7 @@ public: friend class ASTStmtWriter; }; -/// \brief Represents a C11 generic selection. +/// Represents a C11 generic selection. /// /// A generic selection (C11 6.5.1.1) contains an unevaluated controlling /// expression, followed by one or more generic associations. Each generic @@ -4801,7 +4893,7 @@ public: base->containsUnexpandedParameterPack()), Base(base), Accessor(&accessor), AccessorLoc(loc) {} - /// \brief Build an empty vector element expression. + /// Build an empty vector element expression. explicit ExtVectorElementExpr(EmptyShell Empty) : Expr(ExtVectorElementExprClass, Empty) { } @@ -4859,7 +4951,7 @@ public: false), TheBlock(BD) {} - /// \brief Build an empty block expression. + /// Build an empty block expression. explicit BlockExpr(EmptyShell Empty) : Expr(BlockExprClass, Empty) { } const BlockDecl *getBlockDecl() const { return TheBlock; } @@ -5111,7 +5203,7 @@ public: }; private: - /// \brief Location of sub-expressions. + /// Location of sub-expressions. /// The location of Scope sub-expression is NumSubExprs - 1, which is /// not fixed, therefore is not defined in enum. enum { PTR, ORDER, VAL1, ORDER_FAIL, VAL2, WEAK, END_EXPR }; @@ -5125,11 +5217,11 @@ public: AtomicExpr(SourceLocation BLoc, ArrayRef<Expr*> args, QualType t, AtomicOp op, SourceLocation RP); - /// \brief Determine the number of arguments the specified atomic builtin + /// Determine the number of arguments the specified atomic builtin /// should have. static unsigned getNumSubExprs(AtomicOp Op); - /// \brief Build an empty AtomicExpr. + /// Build an empty AtomicExpr. explicit AtomicExpr(EmptyShell Empty) : Expr(AtomicExprClass, Empty) { } Expr *getPtr() const { @@ -5208,7 +5300,7 @@ public: return const_child_range(SubExprs, SubExprs + NumSubExprs); } - /// \brief Get atomic scope model for the atomic op code. + /// Get atomic scope model for the atomic op code. /// \return empty atomic scope model if the atomic op code does not have /// scope operand. static std::unique_ptr<AtomicScopeModel> getScopeModel(AtomicOp Op) { @@ -5219,7 +5311,7 @@ public: return AtomicScopeModel::create(Kind); } - /// \brief Get atomic scope model. + /// Get atomic scope model. /// \return empty atomic scope model if this atomic expression does not have /// scope operand. std::unique_ptr<AtomicScopeModel> getScopeModel() const { diff --git a/include/clang/AST/ExprCXX.h b/include/clang/AST/ExprCXX.h index 58054dda31aa8..8206a26b2c4b5 100644 --- a/include/clang/AST/ExprCXX.h +++ b/include/clang/AST/ExprCXX.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::Expr interface and subclasses for C++ expressions. +/// Defines the clang::Expr interface and subclasses for C++ expressions. // //===----------------------------------------------------------------------===// @@ -62,7 +62,7 @@ class TemplateParameterList; // C++ Expressions. //===--------------------------------------------------------------------===// -/// \brief A call to an overloaded operator written using operator +/// A call to an overloaded operator written using operator /// syntax. /// /// Represents a call to an overloaded operator written using operator @@ -76,7 +76,7 @@ class TemplateParameterList; /// function templates that were found by name lookup at template /// definition time. class CXXOperatorCallExpr : public CallExpr { - /// \brief The overloaded operator. + /// The overloaded operator. OverloadedOperatorKind Operator; SourceRange Range; @@ -101,7 +101,7 @@ public: explicit CXXOperatorCallExpr(ASTContext& C, EmptyShell Empty) : CallExpr(C, CXXOperatorCallExprClass, Empty) {} - /// \brief Returns the kind of overloaded operator that this + /// Returns the kind of overloaded operator that this /// expression refers to. OverloadedOperatorKind getOperator() const { return Operator; } @@ -115,10 +115,10 @@ public: } bool isAssignmentOp() const { return isAssignmentOp(getOperator()); } - /// \brief Is this written as an infix binary operator? + /// Is this written as an infix binary operator? bool isInfixBinaryOp() const; - /// \brief Returns the location of the operator symbol in the expression. + /// Returns the location of the operator symbol in the expression. /// /// When \c getOperator()==OO_Call, this is the location of the right /// parentheses; when \c getOperator()==OO_Subscript, this is the location @@ -170,15 +170,15 @@ public: CXXMemberCallExpr(ASTContext &C, EmptyShell Empty) : CallExpr(C, CXXMemberCallExprClass, Empty) {} - /// \brief Retrieves the implicit object argument for the member call. + /// Retrieves the implicit object argument for the member call. /// /// For example, in "x.f(5)", this returns the sub-expression "x". Expr *getImplicitObjectArgument() const; - /// \brief Retrieves the declaration of the called method. + /// Retrieves the declaration of the called method. CXXMethodDecl *getMethodDecl() const; - /// \brief Retrieves the CXXRecordDecl for the underlying type of + /// Retrieves the CXXRecordDecl for the underlying type of /// the implicit object argument. /// /// Note that this is may not be the same declaration as that of the class @@ -199,7 +199,7 @@ public: } }; -/// \brief Represents a call to a CUDA kernel function. +/// Represents a call to a CUDA kernel function. class CUDAKernelCallExpr : public CallExpr { private: enum { CONFIG, END_PREARG }; @@ -218,7 +218,7 @@ public: } CallExpr *getConfig() { return cast_or_null<CallExpr>(getPreArg(CONFIG)); } - /// \brief Sets the kernel configuration expression. + /// Sets the kernel configuration expression. /// /// Note that this method cannot be called if config has already been set to a /// non-null value. @@ -237,7 +237,7 @@ public: } }; -/// \brief Abstract class common to all of the C++ "named"/"keyword" casts. +/// Abstract class common to all of the C++ "named"/"keyword" casts. /// /// This abstract class is inherited by all of the classes /// representing "named" casts: CXXStaticCastExpr for \c static_cast, @@ -271,11 +271,11 @@ protected: public: const char *getCastName() const; - /// \brief Retrieve the location of the cast operator keyword, e.g., + /// Retrieve the location of the cast operator keyword, e.g., /// \c static_cast. SourceLocation getOperatorLoc() const { return Loc; } - /// \brief Retrieve the location of the closing parenthesis. + /// Retrieve the location of the closing parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } SourceLocation getLocStart() const LLVM_READONLY { return Loc; } @@ -295,7 +295,7 @@ public: } }; -/// \brief A C++ \c static_cast expression (C++ [expr.static.cast]). +/// A C++ \c static_cast expression (C++ [expr.static.cast]). /// /// This expression node represents a C++ static cast, e.g., /// \c static_cast<int>(1.0). @@ -330,7 +330,7 @@ public: } }; -/// \brief A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). +/// A C++ @c dynamic_cast expression (C++ [expr.dynamic.cast]). /// /// This expression node represents a dynamic cast, e.g., /// \c dynamic_cast<Derived*>(BasePtr). Such a cast may perform a run-time @@ -369,7 +369,7 @@ public: } }; -/// \brief A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). +/// A C++ @c reinterpret_cast expression (C++ [expr.reinterpret.cast]). /// /// This expression node represents a reinterpret cast, e.g., /// @c reinterpret_cast<int>(VoidPtr). @@ -410,7 +410,7 @@ public: } }; -/// \brief A C++ \c const_cast expression (C++ [expr.const.cast]). +/// A C++ \c const_cast expression (C++ [expr.const.cast]). /// /// This expression node represents a const cast, e.g., /// \c const_cast<char*>(PtrToConstChar). @@ -445,7 +445,7 @@ public: } }; -/// \brief A call to a literal operator (C++11 [over.literal]) +/// A call to a literal operator (C++11 [over.literal]) /// written as a user-defined literal (C++11 [lit.ext]). /// /// Represents a user-defined literal, e.g. "foo"_bar or 1.23_xyz. While this @@ -455,7 +455,7 @@ public: /// Since literal operators are never found by ADL and can only be declared at /// namespace scope, a user-defined literal is never dependent. class UserDefinedLiteral : public CallExpr { - /// \brief The location of a ud-suffix within the literal. + /// The location of a ud-suffix within the literal. SourceLocation UDSuffixLoc; public: @@ -492,11 +492,11 @@ public: LOK_Character }; - /// \brief Returns the kind of literal operator invocation + /// Returns the kind of literal operator invocation /// which this expression represents. LiteralOperatorKind getLiteralOperatorKind() const; - /// \brief If this is not a raw user-defined literal, get the + /// If this is not a raw user-defined literal, get the /// underlying cooked literal (representing the literal with the suffix /// removed). Expr *getCookedLiteral(); @@ -512,13 +512,13 @@ public: SourceLocation getLocEnd() const { return getRParenLoc(); } - /// \brief Returns the location of a ud-suffix in the expression. + /// Returns the location of a ud-suffix in the expression. /// /// For a string literal, there may be multiple identical suffixes. This /// returns the first. SourceLocation getUDSuffixLoc() const { return UDSuffixLoc; } - /// \brief Returns the ud-suffix specified for this literal. + /// Returns the ud-suffix specified for this literal. const IdentifierInfo *getUDSuffix() const; static bool classof(const Stmt *S) { @@ -526,7 +526,7 @@ public: } }; -/// \brief A boolean literal, per ([C++ lex.bool] Boolean literals). +/// A boolean literal, per ([C++ lex.bool] Boolean literals). class CXXBoolLiteralExpr : public Expr { bool Value; SourceLocation Loc; @@ -559,7 +559,7 @@ public: } }; -/// \brief The null pointer literal (C++11 [lex.nullptr]) +/// The null pointer literal (C++11 [lex.nullptr]) /// /// Introduced in C++11, the only literal of type \c nullptr_t is \c nullptr. class CXXNullPtrLiteralExpr : public Expr { @@ -589,7 +589,7 @@ public: } }; -/// \brief Implicit construction of a std::initializer_list<T> object from an +/// Implicit construction of a std::initializer_list<T> object from an /// array temporary within list-initialization (C++11 [dcl.init.list]p5). class CXXStdInitializerListExpr : public Expr { Stmt *SubExpr = nullptr; @@ -619,6 +619,7 @@ public: return SubExpr->getLocEnd(); } + /// Retrieve the source range of the expression. SourceRange getSourceRange() const LLVM_READONLY { return SubExpr->getSourceRange(); } @@ -677,11 +678,11 @@ public: bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } - /// \brief Retrieves the type operand of this typeid() expression after + /// Retrieves the type operand of this typeid() expression after /// various required adjustments (removing reference types, cv-qualifiers). QualType getTypeOperand(ASTContext &Context) const; - /// \brief Retrieve source information for the type operand. + /// Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { assert(isTypeOperand() && "Cannot call getTypeOperand for typeid(expr)"); return Operand.get<TypeSourceInfo *>(); @@ -715,12 +716,12 @@ public: child_range children() { if (isTypeOperand()) return child_range(child_iterator(), child_iterator()); - Stmt **begin = reinterpret_cast<Stmt**>(&Operand); + auto **begin = reinterpret_cast<Stmt **>(&Operand); return child_range(begin, begin + 1); } }; -/// \brief A member reference to an MSPropertyDecl. +/// A member reference to an MSPropertyDecl. /// /// This expression always has pseudo-object type, and therefore it is /// typically not encountered in a fully-typechecked expression except @@ -816,7 +817,7 @@ public: SubExprs[IDX_EXPR] = Idx; } - /// \brief Create an empty array subscript expression. + /// Create an empty array subscript expression. explicit MSPropertySubscriptExpr(EmptyShell Shell) : Expr(MSPropertySubscriptExprClass, Shell) {} @@ -884,11 +885,11 @@ public: bool isTypeOperand() const { return Operand.is<TypeSourceInfo *>(); } - /// \brief Retrieves the type operand of this __uuidof() expression after + /// Retrieves the type operand of this __uuidof() expression after /// various required adjustments (removing reference types, cv-qualifiers). QualType getTypeOperand(ASTContext &Context) const; - /// \brief Retrieve source information for the type operand. + /// Retrieve source information for the type operand. TypeSourceInfo *getTypeOperandSourceInfo() const { assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)"); return Operand.get<TypeSourceInfo *>(); @@ -925,12 +926,12 @@ public: child_range children() { if (isTypeOperand()) return child_range(child_iterator(), child_iterator()); - Stmt **begin = reinterpret_cast<Stmt**>(&Operand); + auto **begin = reinterpret_cast<Stmt **>(&Operand); return child_range(begin, begin + 1); } }; -/// \brief Represents the \c this expression in C++. +/// Represents the \c this expression in C++. /// /// This is a pointer to the object on which the current member function is /// executing (C++ [expr.prim]p3). Example: @@ -977,7 +978,7 @@ public: } }; -/// \brief A C++ throw-expression (C++ [except.throw]). +/// A C++ throw-expression (C++ [except.throw]). /// /// This handles 'throw' (for re-throwing the current exception) and /// 'throw' assignment-expression. When assignment-expression isn't @@ -988,7 +989,7 @@ class CXXThrowExpr : public Expr { Stmt *Op; SourceLocation ThrowLoc; - /// \brief Whether the thrown variable (if any) is in scope. + /// Whether the thrown variable (if any) is in scope. unsigned IsThrownVariableInScope : 1; public: @@ -1009,7 +1010,7 @@ public: SourceLocation getThrowLoc() const { return ThrowLoc; } - /// \brief Determines whether the variable thrown by this expression (if any!) + /// Determines whether the variable thrown by this expression (if any!) /// is within the innermost try block. /// /// This information is required to determine whether the NRVO can apply to @@ -1034,16 +1035,16 @@ public: } }; -/// \brief A default argument (C++ [dcl.fct.default]). +/// A default argument (C++ [dcl.fct.default]). /// /// This wraps up a function call argument that was created from the /// corresponding parameter's default argument, when the call did not /// explicitly supply arguments for all of the parameters. class CXXDefaultArgExpr final : public Expr { - /// \brief The parameter whose default is being used. + /// The parameter whose default is being used. ParmVarDecl *Param; - /// \brief The location where the default argument expression was used. + /// The location where the default argument expression was used. SourceLocation Loc; CXXDefaultArgExpr(StmtClass SC, SourceLocation Loc, ParmVarDecl *param) @@ -1081,7 +1082,7 @@ public: return getParam()->getDefaultArg(); } - /// \brief Retrieve the location where this default argument was actually + /// Retrieve the location where this default argument was actually /// used. SourceLocation getUsedLocation() const { return Loc; } @@ -1102,7 +1103,7 @@ public: } }; -/// \brief A use of a default initializer in a constructor or in aggregate +/// A use of a default initializer in a constructor or in aggregate /// initialization. /// /// This wraps a use of a C++ default initializer (technically, @@ -1111,10 +1112,10 @@ public: /// (C++11 [class.base.init]p8) or in aggregate initialization /// (C++1y [dcl.init.aggr]p7). class CXXDefaultInitExpr : public Expr { - /// \brief The field whose default is being used. + /// The field whose default is being used. FieldDecl *Field; - /// \brief The location where the default initializer expression was used. + /// The location where the default initializer expression was used. SourceLocation Loc; CXXDefaultInitExpr(const ASTContext &C, SourceLocation Loc, FieldDecl *Field, @@ -1133,11 +1134,11 @@ public: return new (C) CXXDefaultInitExpr(C, Loc, Field, Field->getType()); } - /// \brief Get the field whose initializer will be used. + /// Get the field whose initializer will be used. FieldDecl *getField() { return Field; } const FieldDecl *getField() const { return Field; } - /// \brief Get the initialization expression that will be used. + /// Get the initialization expression that will be used. const Expr *getExpr() const { assert(Field->getInClassInitializer() && "initializer hasn't been parsed"); return Field->getInClassInitializer(); @@ -1160,9 +1161,9 @@ public: } }; -/// \brief Represents a C++ temporary. +/// Represents a C++ temporary. class CXXTemporary { - /// \brief The destructor that needs to be called. + /// The destructor that needs to be called. const CXXDestructorDecl *Destructor; explicit CXXTemporary(const CXXDestructorDecl *destructor) @@ -1179,7 +1180,7 @@ public: } }; -/// \brief Represents binding an expression to a temporary. +/// Represents binding an expression to a temporary. /// /// This ensures the destructor is called for the temporary. It should only be /// needed for non-POD, non-trivially destructable class types. For example: @@ -1235,7 +1236,7 @@ public: child_range children() { return child_range(&SubExpr, &SubExpr + 1); } }; -/// \brief Represents a call to a C++ constructor. +/// Represents a call to a C++ constructor. class CXXConstructExpr : public Expr { public: enum ConstructionKind { @@ -1273,7 +1274,7 @@ protected: ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); - /// \brief Construct an empty C++ construction expression. + /// Construct an empty C++ construction expression. CXXConstructExpr(StmtClass SC, EmptyShell Empty) : Expr(SC, Empty), NumArgs(0), Elidable(false), HadMultipleCandidates(false), ListInitialization(false), @@ -1282,7 +1283,7 @@ protected: public: friend class ASTStmtReader; - /// \brief Construct an empty C++ construction expression. + /// Construct an empty C++ construction expression. explicit CXXConstructExpr(EmptyShell Empty) : CXXConstructExpr(CXXConstructExprClass, Empty) {} @@ -1298,40 +1299,40 @@ public: ConstructionKind ConstructKind, SourceRange ParenOrBraceRange); - /// \brief Get the constructor that this expression will (ultimately) call. + /// Get the constructor that this expression will (ultimately) call. CXXConstructorDecl *getConstructor() const { return Constructor; } SourceLocation getLocation() const { return Loc; } void setLocation(SourceLocation Loc) { this->Loc = Loc; } - /// \brief Whether this construction is elidable. + /// Whether this construction is elidable. bool isElidable() const { return Elidable; } void setElidable(bool E) { Elidable = E; } - /// \brief Whether the referred constructor was resolved from + /// Whether the referred constructor was resolved from /// an overloaded set having size greater than 1. bool hadMultipleCandidates() const { return HadMultipleCandidates; } void setHadMultipleCandidates(bool V) { HadMultipleCandidates = V; } - /// \brief Whether this constructor call was written as list-initialization. + /// Whether this constructor call was written as list-initialization. bool isListInitialization() const { return ListInitialization; } void setListInitialization(bool V) { ListInitialization = V; } - /// \brief Whether this constructor call was written as list-initialization, + /// Whether this constructor call was written as list-initialization, /// but was interpreted as forming a std::initializer_list<T> from the list /// and passing that as a single constructor argument. /// See C++11 [over.match.list]p1 bullet 1. bool isStdInitListInitialization() const { return StdInitListInitialization; } void setStdInitListInitialization(bool V) { StdInitListInitialization = V; } - /// \brief Whether this construction first requires + /// Whether this construction first requires /// zero-initialization before the initializer is called. bool requiresZeroInitialization() const { return ZeroInitialization; } void setRequiresZeroInitialization(bool ZeroInit) { ZeroInitialization = ZeroInit; } - /// \brief Determine whether this constructor is actually constructing + /// Determine whether this constructor is actually constructing /// a base class (rather than a complete object). ConstructionKind getConstructionKind() const { return (ConstructionKind)ConstructKind; @@ -1361,7 +1362,7 @@ public: } unsigned getNumArgs() const { return NumArgs; } - /// \brief Return the specified argument. + /// Return the specified argument. Expr *getArg(unsigned Arg) { assert(Arg < NumArgs && "Arg access out of range!"); return cast<Expr>(Args[Arg]); @@ -1371,7 +1372,7 @@ public: return cast<Expr>(Args[Arg]); } - /// \brief Set the specified argument. + /// Set the specified argument. void setArg(unsigned Arg, Expr *ArgExpr) { assert(Arg < NumArgs && "Arg access out of range!"); Args[Arg] = ArgExpr; @@ -1393,7 +1394,7 @@ public: } }; -/// \brief Represents a call to an inherited base class constructor from an +/// Represents a call to an inherited base class constructor from an /// inheriting constructor. This call implicitly forwards the arguments from /// the enclosing context (an inheriting constructor) to the specified inherited /// base class constructor. @@ -1414,7 +1415,7 @@ private: public: friend class ASTStmtReader; - /// \brief Construct a C++ inheriting construction expression. + /// Construct a C++ inheriting construction expression. CXXInheritedCtorInitExpr(SourceLocation Loc, QualType T, CXXConstructorDecl *Ctor, bool ConstructsVirtualBase, bool InheritedFromVirtualBase) @@ -1426,15 +1427,15 @@ public: assert(!T->isDependentType()); } - /// \brief Construct an empty C++ inheriting construction expression. + /// Construct an empty C++ inheriting construction expression. explicit CXXInheritedCtorInitExpr(EmptyShell Empty) : Expr(CXXInheritedCtorInitExprClass, Empty), ConstructsVirtualBase(false), InheritedFromVirtualBase(false) {} - /// \brief Get the constructor that this expression will call. + /// Get the constructor that this expression will call. CXXConstructorDecl *getConstructor() const { return Constructor; } - /// \brief Determine whether this constructor is actually constructing + /// Determine whether this constructor is actually constructing /// a base class (rather than a complete object). bool constructsVBase() const { return ConstructsVirtualBase; } CXXConstructExpr::ConstructionKind getConstructionKind() const { @@ -1442,7 +1443,7 @@ public: : CXXConstructExpr::CK_NonVirtualBase; } - /// \brief Determine whether the inherited constructor is inherited from a + /// Determine whether the inherited constructor is inherited from a /// virtual base of the object we construct. If so, we are not responsible /// for calling the inherited constructor (the complete object constructor /// does that), and so we don't need to pass any arguments. @@ -1461,7 +1462,7 @@ public: } }; -/// \brief Represents an explicit C++ type conversion that uses "functional" +/// Represents an explicit C++ type conversion that uses "functional" /// notation (C++ [expr.type.conv]). /// /// Example: @@ -1504,6 +1505,9 @@ public: SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } + /// Determine whether this expression models list-initialization. + bool isListInitialization() const { return LParenLoc.isInvalid(); } + SourceLocation getLocStart() const LLVM_READONLY; SourceLocation getLocEnd() const LLVM_READONLY; @@ -1512,7 +1516,7 @@ public: } }; -/// @brief Represents a C++ functional cast expression that builds a +/// Represents a C++ functional cast expression that builds a /// temporary object. /// /// This expression type represents a C++ "functional" cast @@ -1556,7 +1560,7 @@ public: } }; -/// \brief A C++ lambda expression, which produces a function object +/// A C++ lambda expression, which produces a function object /// (of unspecified type) that can be invoked later. /// /// Example: @@ -1579,27 +1583,27 @@ public: /// and which can never occur implicitly. class LambdaExpr final : public Expr, private llvm::TrailingObjects<LambdaExpr, Stmt *> { - /// \brief The source range that covers the lambda introducer ([...]). + /// The source range that covers the lambda introducer ([...]). SourceRange IntroducerRange; - /// \brief The source location of this lambda's capture-default ('=' or '&'). + /// The source location of this lambda's capture-default ('=' or '&'). SourceLocation CaptureDefaultLoc; - /// \brief The number of captures. + /// The number of captures. unsigned NumCaptures : 16; - /// \brief The default capture kind, which is a value of type + /// The default capture kind, which is a value of type /// LambdaCaptureDefault. unsigned CaptureDefault : 2; - /// \brief Whether this lambda had an explicit parameter list vs. an + /// Whether this lambda had an explicit parameter list vs. an /// implicit (and empty) parameter list. unsigned ExplicitParams : 1; - /// \brief Whether this lambda had the result type explicitly specified. + /// Whether this lambda had the result type explicitly specified. unsigned ExplicitResultType : 1; - /// \brief The location of the closing brace ('}') that completes + /// The location of the closing brace ('}') that completes /// the lambda. /// /// The location of the brace is also available by looking up the @@ -1609,7 +1613,7 @@ class LambdaExpr final : public Expr, /// module file just to determine the source range. SourceLocation ClosingBrace; - /// \brief Construct a lambda expression. + /// Construct a lambda expression. LambdaExpr(QualType T, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, ArrayRef<LambdaCapture> Captures, @@ -1617,7 +1621,7 @@ class LambdaExpr final : public Expr, ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); - /// \brief Construct an empty lambda expression. + /// Construct an empty lambda expression. LambdaExpr(EmptyShell Empty, unsigned NumCaptures) : Expr(LambdaExprClass, Empty), NumCaptures(NumCaptures), CaptureDefault(LCD_None), ExplicitParams(false), @@ -1634,7 +1638,7 @@ public: friend class ASTStmtWriter; friend TrailingObjects; - /// \brief Construct a new lambda expression. + /// Construct a new lambda expression. static LambdaExpr * Create(const ASTContext &C, CXXRecordDecl *Class, SourceRange IntroducerRange, LambdaCaptureDefault CaptureDefault, SourceLocation CaptureDefaultLoc, @@ -1642,143 +1646,143 @@ public: bool ExplicitResultType, ArrayRef<Expr *> CaptureInits, SourceLocation ClosingBrace, bool ContainsUnexpandedParameterPack); - /// \brief Construct a new lambda expression that will be deserialized from + /// Construct a new lambda expression that will be deserialized from /// an external source. static LambdaExpr *CreateDeserialized(const ASTContext &C, unsigned NumCaptures); - /// \brief Determine the default capture kind for this lambda. + /// Determine the default capture kind for this lambda. LambdaCaptureDefault getCaptureDefault() const { return static_cast<LambdaCaptureDefault>(CaptureDefault); } - /// \brief Retrieve the location of this lambda's capture-default, if any. + /// Retrieve the location of this lambda's capture-default, if any. SourceLocation getCaptureDefaultLoc() const { return CaptureDefaultLoc; } - /// \brief Determine whether one of this lambda's captures is an init-capture. + /// Determine whether one of this lambda's captures is an init-capture. bool isInitCapture(const LambdaCapture *Capture) const; - /// \brief An iterator that walks over the captures of the lambda, + /// An iterator that walks over the captures of the lambda, /// both implicit and explicit. using capture_iterator = const LambdaCapture *; - /// \brief An iterator over a range of lambda captures. + /// An iterator over a range of lambda captures. using capture_range = llvm::iterator_range<capture_iterator>; - /// \brief Retrieve this lambda's captures. + /// Retrieve this lambda's captures. capture_range captures() const; - /// \brief Retrieve an iterator pointing to the first lambda capture. + /// Retrieve an iterator pointing to the first lambda capture. capture_iterator capture_begin() const; - /// \brief Retrieve an iterator pointing past the end of the + /// Retrieve an iterator pointing past the end of the /// sequence of lambda captures. capture_iterator capture_end() const; - /// \brief Determine the number of captures in this lambda. + /// Determine the number of captures in this lambda. unsigned capture_size() const { return NumCaptures; } - /// \brief Retrieve this lambda's explicit captures. + /// Retrieve this lambda's explicit captures. capture_range explicit_captures() const; - /// \brief Retrieve an iterator pointing to the first explicit + /// Retrieve an iterator pointing to the first explicit /// lambda capture. capture_iterator explicit_capture_begin() const; - /// \brief Retrieve an iterator pointing past the end of the sequence of + /// Retrieve an iterator pointing past the end of the sequence of /// explicit lambda captures. capture_iterator explicit_capture_end() const; - /// \brief Retrieve this lambda's implicit captures. + /// Retrieve this lambda's implicit captures. capture_range implicit_captures() const; - /// \brief Retrieve an iterator pointing to the first implicit + /// Retrieve an iterator pointing to the first implicit /// lambda capture. capture_iterator implicit_capture_begin() const; - /// \brief Retrieve an iterator pointing past the end of the sequence of + /// Retrieve an iterator pointing past the end of the sequence of /// implicit lambda captures. capture_iterator implicit_capture_end() const; - /// \brief Iterator that walks over the capture initialization + /// Iterator that walks over the capture initialization /// arguments. using capture_init_iterator = Expr **; - /// \brief Const iterator that walks over the capture initialization + /// Const iterator that walks over the capture initialization /// arguments. using const_capture_init_iterator = Expr *const *; - /// \brief Retrieve the initialization expressions for this lambda's captures. + /// Retrieve the initialization expressions for this lambda's captures. llvm::iterator_range<capture_init_iterator> capture_inits() { return llvm::make_range(capture_init_begin(), capture_init_end()); } - /// \brief Retrieve the initialization expressions for this lambda's captures. + /// Retrieve the initialization expressions for this lambda's captures. llvm::iterator_range<const_capture_init_iterator> capture_inits() const { return llvm::make_range(capture_init_begin(), capture_init_end()); } - /// \brief Retrieve the first initialization argument for this + /// Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). capture_init_iterator capture_init_begin() { return reinterpret_cast<Expr **>(getStoredStmts()); } - /// \brief Retrieve the first initialization argument for this + /// Retrieve the first initialization argument for this /// lambda expression (which initializes the first capture field). const_capture_init_iterator capture_init_begin() const { return reinterpret_cast<Expr *const *>(getStoredStmts()); } - /// \brief Retrieve the iterator pointing one past the last + /// Retrieve the iterator pointing one past the last /// initialization argument for this lambda expression. capture_init_iterator capture_init_end() { return capture_init_begin() + NumCaptures; } - /// \brief Retrieve the iterator pointing one past the last + /// Retrieve the iterator pointing one past the last /// initialization argument for this lambda expression. const_capture_init_iterator capture_init_end() const { return capture_init_begin() + NumCaptures; } - /// \brief Retrieve the source range covering the lambda introducer, + /// Retrieve the source range covering the lambda introducer, /// which contains the explicit capture list surrounded by square /// brackets ([...]). SourceRange getIntroducerRange() const { return IntroducerRange; } - /// \brief Retrieve the class that corresponds to the lambda. + /// Retrieve the class that corresponds to the lambda. /// /// This is the "closure type" (C++1y [expr.prim.lambda]), and stores the /// captures in its fields and provides the various operations permitted /// on a lambda (copying, calling). CXXRecordDecl *getLambdaClass() const; - /// \brief Retrieve the function call operator associated with this + /// Retrieve the function call operator associated with this /// lambda expression. CXXMethodDecl *getCallOperator() const; - /// \brief If this is a generic lambda expression, retrieve the template + /// If this is a generic lambda expression, retrieve the template /// parameter list associated with it, or else return null. TemplateParameterList *getTemplateParameterList() const; - /// \brief Whether this is a generic lambda. + /// Whether this is a generic lambda. bool isGenericLambda() const { return getTemplateParameterList(); } - /// \brief Retrieve the body of the lambda. + /// Retrieve the body of the lambda. CompoundStmt *getBody() const; - /// \brief Determine whether the lambda is mutable, meaning that any + /// Determine whether the lambda is mutable, meaning that any /// captures values can be modified. bool isMutable() const; - /// \brief Determine whether this lambda has an explicit parameter + /// Determine whether this lambda has an explicit parameter /// list vs. an implicit (empty) parameter list. bool hasExplicitParameters() const { return ExplicitParams; } - /// \brief Whether this lambda had its result type explicitly specified. + /// Whether this lambda had its result type explicitly specified. bool hasExplicitResultType() const { return ExplicitResultType; } static bool classof(const Stmt *T) { @@ -1806,7 +1810,7 @@ class CXXScalarValueInitExpr : public Expr { TypeSourceInfo *TypeInfo; public: - /// \brief Create an explicitly-written scalar-value initialization + /// Create an explicitly-written scalar-value initialization /// expression. CXXScalarValueInitExpr(QualType Type, TypeSourceInfo *TypeInfo, SourceLocation rParenLoc) @@ -1837,7 +1841,7 @@ public: } }; -/// \brief Represents a new-expression for memory allocation and constructor +/// Represents a new-expression for memory allocation and constructor /// calls, e.g: "new CXXNewExpr(foo)". class CXXNewExpr : public Expr { friend class ASTStmtReader; @@ -1847,24 +1851,24 @@ class CXXNewExpr : public Expr { /// expression, and any number of optional placement arguments, in that order. Stmt **SubExprs = nullptr; - /// \brief Points to the allocation function used. + /// Points to the allocation function used. FunctionDecl *OperatorNew; - /// \brief Points to the deallocation function used in case of error. May be + /// Points to the deallocation function used in case of error. May be /// null. FunctionDecl *OperatorDelete; - /// \brief The allocated type-source information, as written in the source. + /// The allocated type-source information, as written in the source. TypeSourceInfo *AllocatedTypeInfo; - /// \brief If the allocated type was expressed as a parenthesized type-id, + /// If the allocated type was expressed as a parenthesized type-id, /// the source range covering the parenthesized type-id. SourceRange TypeIdParens; - /// \brief Range of the entire new expression. + /// Range of the entire new expression. SourceRange Range; - /// \brief Source-range of a paren-delimited initializer. + /// Source-range of a paren-delimited initializer. SourceRange DirectInitRange; /// Was the usage ::new, i.e. is the global new to be used? @@ -1922,7 +1926,7 @@ public: return AllocatedTypeInfo; } - /// \brief True if the allocation result needs to be null-checked. + /// True if the allocation result needs to be null-checked. /// /// C++11 [expr.new]p13: /// If the allocation function returns null, initialization shall @@ -1973,17 +1977,17 @@ public: bool isGlobalNew() const { return GlobalNew; } - /// \brief Whether this new-expression has any initializer at all. + /// Whether this new-expression has any initializer at all. bool hasInitializer() const { return StoredInitializationStyle > 0; } - /// \brief The kind of initializer this new-expression has. + /// The kind of initializer this new-expression has. InitializationStyle getInitializationStyle() const { if (StoredInitializationStyle == 0) return NoInit; return static_cast<InitializationStyle>(StoredInitializationStyle-1); } - /// \brief The initializer of this new-expression. + /// The initializer of this new-expression. Expr *getInitializer() { return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; } @@ -1991,7 +1995,7 @@ public: return hasInitializer() ? cast<Expr>(SubExprs[Array]) : nullptr; } - /// \brief Returns the CXXConstructExpr from this new-expression, or null. + /// Returns the CXXConstructExpr from this new-expression, or null. const CXXConstructExpr *getConstructExpr() const { return dyn_cast_or_null<CXXConstructExpr>(getInitializer()); } @@ -2066,7 +2070,7 @@ public: } }; -/// \brief Represents a \c delete expression for memory deallocation and +/// Represents a \c delete expression for memory deallocation and /// destructor calls, e.g. "delete[] pArray". class CXXDeleteExpr : public Expr { /// Points to the operator delete overload that is used. Could be a member. @@ -2125,7 +2129,7 @@ public: Expr *getArgument() { return cast<Expr>(Argument); } const Expr *getArgument() const { return cast<Expr>(Argument); } - /// \brief Retrieve the type being destroyed. + /// Retrieve the type being destroyed. /// /// If the type being destroyed is a dependent type which may or may not /// be a pointer, return an invalid type. @@ -2142,13 +2146,13 @@ public: child_range children() { return child_range(&Argument, &Argument+1); } }; -/// \brief Stores the type being destroyed by a pseudo-destructor expression. +/// Stores the type being destroyed by a pseudo-destructor expression. class PseudoDestructorTypeStorage { - /// \brief Either the type source information or the name of the type, if + /// Either the type source information or the name of the type, if /// it couldn't be resolved due to type-dependence. llvm::PointerUnion<TypeSourceInfo *, IdentifierInfo *> Type; - /// \brief The starting source location of the pseudo-destructor type. + /// The starting source location of the pseudo-destructor type. SourceLocation Location; public: @@ -2170,7 +2174,7 @@ public: SourceLocation getLocation() const { return Location; } }; -/// \brief Represents a C++ pseudo-destructor (C++ [expr.pseudo]). +/// Represents a C++ pseudo-destructor (C++ [expr.pseudo]). /// /// A pseudo-destructor is an expression that looks like a member access to a /// destructor of a scalar type, except that scalar types don't have @@ -2197,31 +2201,31 @@ public: class CXXPseudoDestructorExpr : public Expr { friend class ASTStmtReader; - /// \brief The base expression (that is being destroyed). + /// The base expression (that is being destroyed). Stmt *Base = nullptr; - /// \brief Whether the operator was an arrow ('->'); otherwise, it was a + /// Whether the operator was an arrow ('->'); otherwise, it was a /// period ('.'). bool IsArrow : 1; - /// \brief The location of the '.' or '->' operator. + /// The location of the '.' or '->' operator. SourceLocation OperatorLoc; - /// \brief The nested-name-specifier that follows the operator, if present. + /// The nested-name-specifier that follows the operator, if present. NestedNameSpecifierLoc QualifierLoc; - /// \brief The type that precedes the '::' in a qualified pseudo-destructor + /// The type that precedes the '::' in a qualified pseudo-destructor /// expression. TypeSourceInfo *ScopeType = nullptr; - /// \brief The location of the '::' in a qualified pseudo-destructor + /// The location of the '::' in a qualified pseudo-destructor /// expression. SourceLocation ColonColonLoc; - /// \brief The location of the '~'. + /// The location of the '~'. SourceLocation TildeLoc; - /// \brief The type being destroyed, or its name if we were unable to + /// The type being destroyed, or its name if we were unable to /// resolve the name. PseudoDestructorTypeStorage DestroyedType; @@ -2239,30 +2243,30 @@ public: Expr *getBase() const { return cast<Expr>(Base); } - /// \brief Determines whether this member expression actually had + /// Determines whether this member expression actually had /// a C++ nested-name-specifier prior to the name of the member, e.g., /// x->Base::foo. bool hasQualifier() const { return QualifierLoc.hasQualifier(); } - /// \brief Retrieves the nested-name-specifier that qualifies the type name, + /// Retrieves the nested-name-specifier that qualifies the type name, /// with source-location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief If the member name was qualified, retrieves the + /// If the member name was qualified, retrieves the /// nested-name-specifier that precedes the member name. Otherwise, returns /// null. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Determine whether this pseudo-destructor expression was written + /// Determine whether this pseudo-destructor expression was written /// using an '->' (otherwise, it used a '.'). bool isArrow() const { return IsArrow; } - /// \brief Retrieve the location of the '.' or '->' operator. + /// Retrieve the location of the '.' or '->' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Retrieve the scope type in a qualified pseudo-destructor + /// Retrieve the scope type in a qualified pseudo-destructor /// expression. /// /// Pseudo-destructor expressions can have extra qualification within them @@ -2273,14 +2277,14 @@ public: /// destructor expression. TypeSourceInfo *getScopeTypeInfo() const { return ScopeType; } - /// \brief Retrieve the location of the '::' in a qualified pseudo-destructor + /// Retrieve the location of the '::' in a qualified pseudo-destructor /// expression. SourceLocation getColonColonLoc() const { return ColonColonLoc; } - /// \brief Retrieve the location of the '~'. + /// Retrieve the location of the '~'. SourceLocation getTildeLoc() const { return TildeLoc; } - /// \brief Retrieve the source location information for the type + /// Retrieve the source location information for the type /// being destroyed. /// /// This type-source information is available for non-dependent @@ -2291,28 +2295,28 @@ public: return DestroyedType.getTypeSourceInfo(); } - /// \brief In a dependent pseudo-destructor expression for which we do not + /// In a dependent pseudo-destructor expression for which we do not /// have full type information on the destroyed type, provides the name /// of the destroyed type. IdentifierInfo *getDestroyedTypeIdentifier() const { return DestroyedType.getIdentifier(); } - /// \brief Retrieve the type being destroyed. + /// Retrieve the type being destroyed. QualType getDestroyedType() const; - /// \brief Retrieve the starting location of the type being destroyed. + /// Retrieve the starting location of the type being destroyed. SourceLocation getDestroyedTypeLoc() const { return DestroyedType.getLocation(); } - /// \brief Set the name of destroyed type for a dependent pseudo-destructor + /// Set the name of destroyed type for a dependent pseudo-destructor /// expression. void setDestroyedType(IdentifierInfo *II, SourceLocation Loc) { DestroyedType = PseudoDestructorTypeStorage(II, Loc); } - /// \brief Set the destroyed type. + /// Set the destroyed type. void setDestroyedType(TypeSourceInfo *Info) { DestroyedType = PseudoDestructorTypeStorage(Info); } @@ -2328,7 +2332,7 @@ public: child_range children() { return child_range(&Base, &Base + 1); } }; -/// \brief A type trait used in the implementation of various C++11 and +/// A type trait used in the implementation of various C++11 and /// Library TR1 trait templates. /// /// \code @@ -2339,10 +2343,10 @@ public: class TypeTraitExpr final : public Expr, private llvm::TrailingObjects<TypeTraitExpr, TypeSourceInfo *> { - /// \brief The location of the type trait keyword. + /// The location of the type trait keyword. SourceLocation Loc; - /// \brief The location of the closing parenthesis. + /// The location of the closing parenthesis. SourceLocation RParenLoc; // Note: The TypeSourceInfos for the arguments are allocated after the @@ -2364,7 +2368,7 @@ public: friend class ASTStmtWriter; friend TrailingObjects; - /// \brief Create a new type trait expression. + /// Create a new type trait expression. static TypeTraitExpr *Create(const ASTContext &C, QualType T, SourceLocation Loc, TypeTrait Kind, ArrayRef<TypeSourceInfo *> Args, @@ -2374,7 +2378,7 @@ public: static TypeTraitExpr *CreateDeserialized(const ASTContext &C, unsigned NumArgs); - /// \brief Determine which type trait this expression uses. + /// Determine which type trait this expression uses. TypeTrait getTrait() const { return static_cast<TypeTrait>(TypeTraitExprBits.Kind); } @@ -2384,16 +2388,16 @@ public: return TypeTraitExprBits.Value; } - /// \brief Determine the number of arguments to this type trait. + /// Determine the number of arguments to this type trait. unsigned getNumArgs() const { return TypeTraitExprBits.NumArgs; } - /// \brief Retrieve the Ith argument. + /// Retrieve the Ith argument. TypeSourceInfo *getArg(unsigned I) const { assert(I < getNumArgs() && "Argument out-of-range"); return getArgs()[I]; } - /// \brief Retrieve the argument types. + /// Retrieve the argument types. ArrayRef<TypeSourceInfo *> getArgs() const { return llvm::makeArrayRef(getTrailingObjects<TypeSourceInfo *>(), getNumArgs()); @@ -2412,7 +2416,7 @@ public: } }; -/// \brief An Embarcadero array type trait, as used in the implementation of +/// An Embarcadero array type trait, as used in the implementation of /// __array_rank and __array_extent. /// /// Example: @@ -2421,22 +2425,22 @@ public: /// __array_extent(int, 1) == 20 /// \endcode class ArrayTypeTraitExpr : public Expr { - /// \brief The trait. An ArrayTypeTrait enum in MSVC compat unsigned. + /// The trait. An ArrayTypeTrait enum in MSVC compat unsigned. unsigned ATT : 2; - /// \brief The value of the type trait. Unspecified if dependent. + /// The value of the type trait. Unspecified if dependent. uint64_t Value = 0; - /// \brief The array dimension being queried, or -1 if not used. + /// The array dimension being queried, or -1 if not used. Expr *Dimension; - /// \brief The location of the type trait keyword. + /// The location of the type trait keyword. SourceLocation Loc; - /// \brief The location of the closing paren. + /// The location of the closing paren. SourceLocation RParen; - /// \brief The type being queried. + /// The type being queried. TypeSourceInfo *QueriedType = nullptr; virtual void anchor(); @@ -2483,7 +2487,7 @@ public: } }; -/// \brief An expression trait intrinsic. +/// An expression trait intrinsic. /// /// Example: /// \code @@ -2491,19 +2495,19 @@ public: /// __is_lvalue_expr(1) == false /// \endcode class ExpressionTraitExpr : public Expr { - /// \brief The trait. A ExpressionTrait enum in MSVC compatible unsigned. + /// The trait. A ExpressionTrait enum in MSVC compatible unsigned. unsigned ET : 31; - /// \brief The value of the type trait. Unspecified if dependent. + /// The value of the type trait. Unspecified if dependent. unsigned Value : 1; - /// \brief The location of the type trait keyword. + /// The location of the type trait keyword. SourceLocation Loc; - /// \brief The location of the closing paren. + /// The location of the closing paren. SourceLocation RParen; - /// \brief The expression being queried. + /// The expression being queried. Expr* QueriedExpression = nullptr; public: @@ -2543,13 +2547,13 @@ public: } }; -/// \brief A reference to an overloaded function set, either an +/// A reference to an overloaded function set, either an /// \c UnresolvedLookupExpr or an \c UnresolvedMemberExpr. class OverloadExpr : public Expr { - /// \brief The common name of these declarations. + /// The common name of these declarations. DeclarationNameInfo NameInfo; - /// \brief The nested-name-specifier that qualifies the name, if any. + /// The nested-name-specifier that qualifies the name, if any. NestedNameSpecifierLoc QualifierLoc; /// The results. These are undesugared, which is to say, they may @@ -2561,7 +2565,7 @@ class OverloadExpr : public Expr { unsigned NumResults = 0; protected: - /// \brief Whether the name includes info for explicit template + /// Whether the name includes info for explicit template /// keyword and arguments. bool HasTemplateKWAndArgsInfo = false; @@ -2577,11 +2581,11 @@ protected: OverloadExpr(StmtClass K, EmptyShell Empty) : Expr(K, Empty) {} - /// \brief Return the optional template keyword and arguments info. + /// Return the optional template keyword and arguments info. ASTTemplateKWAndArgsInfo * getTrailingASTTemplateKWAndArgsInfo(); // defined far below. - /// \brief Return the optional template keyword and arguments info. + /// Return the optional template keyword and arguments info. const ASTTemplateKWAndArgsInfo *getTrailingASTTemplateKWAndArgsInfo() const { return const_cast<OverloadExpr *>(this) ->getTrailingASTTemplateKWAndArgsInfo(); @@ -2604,7 +2608,7 @@ public: bool HasFormOfMemberPointer; }; - /// \brief Finds the overloaded expression in the given expression \p E of + /// Finds the overloaded expression in the given expression \p E of /// OverloadTy. /// /// \return the expression (which must be there) and true if it has @@ -2618,7 +2622,7 @@ public: if (isa<UnaryOperator>(E)) { assert(cast<UnaryOperator>(E)->getOpcode() == UO_AddrOf); E = cast<UnaryOperator>(E)->getSubExpr(); - OverloadExpr *Ovl = cast<OverloadExpr>(E->IgnoreParens()); + auto *Ovl = cast<OverloadExpr>(E->IgnoreParens()); Result.HasFormOfMemberPointer = (E == Ovl && Ovl->getQualifier()); Result.IsAddressOfOperand = true; @@ -2632,7 +2636,7 @@ public: return Result; } - /// \brief Gets the naming class of this lookup, if any. + /// Gets the naming class of this lookup, if any. CXXRecordDecl *getNamingClass() const; using decls_iterator = UnresolvedSetImpl::iterator; @@ -2645,52 +2649,52 @@ public: return llvm::make_range(decls_begin(), decls_end()); } - /// \brief Gets the number of declarations in the unresolved set. + /// Gets the number of declarations in the unresolved set. unsigned getNumDecls() const { return NumResults; } - /// \brief Gets the full name info. + /// Gets the full name info. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - /// \brief Gets the name looked up. + /// Gets the name looked up. DeclarationName getName() const { return NameInfo.getName(); } - /// \brief Gets the location of the name. + /// Gets the location of the name. SourceLocation getNameLoc() const { return NameInfo.getLoc(); } - /// \brief Fetches the nested-name qualifier, if one was given. + /// Fetches the nested-name qualifier, if one was given. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Fetches the nested-name qualifier with source-location + /// Fetches the nested-name qualifier with source-location /// information, if one was given. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the location of the template keyword preceding + /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->TemplateKWLoc; } - /// \brief Retrieve the location of the left angle bracket starting the + /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->LAngleLoc; } - /// \brief Retrieve the location of the right angle bracket ending the + /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingASTTemplateKWAndArgsInfo()->RAngleLoc; } - /// \brief Determines whether the name was preceded by the template keyword. + /// Determines whether the name was preceded by the template keyword. bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - /// \brief Determines whether this expression had explicit template arguments. + /// Determines whether this expression had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } TemplateArgumentLoc const *getTemplateArgs() const { @@ -2710,7 +2714,7 @@ public: return {getTemplateArgs(), getNumTemplateArgs()}; } - /// \brief Copies the template arguments into the given structure. + /// Copies the template arguments into the given structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) getTrailingASTTemplateKWAndArgsInfo()->copyInto(getTemplateArgs(), List); @@ -2722,7 +2726,7 @@ public: } }; -/// \brief A reference to a name which we were able to look up during +/// A reference to a name which we were able to look up during /// parsing but could not resolve to a specific declaration. /// /// This arises in several ways: @@ -2837,7 +2841,7 @@ public: } }; -/// \brief A qualified reference to a name whose declaration cannot +/// A qualified reference to a name whose declaration cannot /// yet be resolved. /// /// DependentScopeDeclRefExpr is similar to DeclRefExpr in that @@ -2856,14 +2860,14 @@ class DependentScopeDeclRefExpr final private llvm::TrailingObjects<DependentScopeDeclRefExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { - /// \brief The nested-name-specifier that qualifies this unresolved + /// The nested-name-specifier that qualifies this unresolved /// declaration name. NestedNameSpecifierLoc QualifierLoc; - /// \brief The name of the entity we will be referencing. + /// The name of the entity we will be referencing. DeclarationNameInfo NameInfo; - /// \brief Whether the name includes info for explicit template + /// Whether the name includes info for explicit template /// keyword and arguments. bool HasTemplateKWAndArgsInfo; @@ -2892,42 +2896,42 @@ public: bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); - /// \brief Retrieve the name that this expression refers to. + /// Retrieve the name that this expression refers to. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - /// \brief Retrieve the name that this expression refers to. + /// Retrieve the name that this expression refers to. DeclarationName getDeclName() const { return NameInfo.getName(); } - /// \brief Retrieve the location of the name within the expression. + /// Retrieve the location of the name within the expression. /// /// For example, in "X<T>::value" this is the location of "value". SourceLocation getLocation() const { return NameInfo.getLoc(); } - /// \brief Retrieve the nested-name-specifier that qualifies the + /// Retrieve the nested-name-specifier that qualifies the /// name, with source location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies this + /// Retrieve the nested-name-specifier that qualifies this /// declaration. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the location of the template keyword preceding + /// Retrieve the location of the template keyword preceding /// this name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } - /// \brief Retrieve the location of the left angle bracket starting the + /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } - /// \brief Retrieve the location of the right angle bracket ending the + /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); @@ -2940,7 +2944,7 @@ public: /// Determines whether this lookup had explicit template arguments. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Copies the template arguments (if present) into the given + /// Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) @@ -3063,7 +3067,7 @@ public: child_range children() { return child_range(&SubExpr, &SubExpr + 1); } }; -/// \brief Describes an explicit type conversion that uses functional +/// Describes an explicit type conversion that uses functional /// notion but could not be resolved because one or more arguments are /// type-dependent. /// @@ -3090,16 +3094,16 @@ class CXXUnresolvedConstructExpr final friend class ASTStmtReader; friend TrailingObjects; - /// \brief The type being constructed. + /// The type being constructed. TypeSourceInfo *Type = nullptr; - /// \brief The location of the left parentheses ('('). + /// The location of the left parentheses ('('). SourceLocation LParenLoc; - /// \brief The location of the right parentheses (')'). + /// The location of the right parentheses (')'). SourceLocation RParenLoc; - /// \brief The number of arguments used to construct the type. + /// The number of arguments used to construct the type. unsigned NumArgs; CXXUnresolvedConstructExpr(TypeSourceInfo *Type, @@ -3120,20 +3124,20 @@ public: static CXXUnresolvedConstructExpr *CreateEmpty(const ASTContext &C, unsigned NumArgs); - /// \brief Retrieve the type that is being constructed, as specified + /// Retrieve the type that is being constructed, as specified /// in the source code. QualType getTypeAsWritten() const { return Type->getType(); } - /// \brief Retrieve the type source information for the type being + /// Retrieve the type source information for the type being /// constructed. TypeSourceInfo *getTypeSourceInfo() const { return Type; } - /// \brief Retrieve the location of the left parentheses ('(') that + /// Retrieve the location of the left parentheses ('(') that /// precedes the argument list. SourceLocation getLParenLoc() const { return LParenLoc; } void setLParenLoc(SourceLocation L) { LParenLoc = L; } - /// \brief Retrieve the location of the right parentheses (')') that + /// Retrieve the location of the right parentheses (')') that /// follows the argument list. SourceLocation getRParenLoc() const { return RParenLoc; } void setRParenLoc(SourceLocation L) { RParenLoc = L; } @@ -3143,7 +3147,7 @@ public: /// an InitListExpr. bool isListInitialization() const { return LParenLoc.isInvalid(); } - /// \brief Retrieve the number of arguments. + /// Retrieve the number of arguments. unsigned arg_size() const { return NumArgs; } using arg_iterator = Expr **; @@ -3187,12 +3191,12 @@ public: // Iterators child_range children() { - Stmt **begin = reinterpret_cast<Stmt **>(arg_begin()); + auto **begin = reinterpret_cast<Stmt **>(arg_begin()); return child_range(begin, begin + NumArgs); } }; -/// \brief Represents a C++ member access expression where the actual +/// Represents a C++ member access expression where the actual /// member referenced could not be resolved because the base /// expression or the member name was dependent. /// @@ -3204,29 +3208,29 @@ class CXXDependentScopeMemberExpr final private llvm::TrailingObjects<CXXDependentScopeMemberExpr, ASTTemplateKWAndArgsInfo, TemplateArgumentLoc> { - /// \brief The expression for the base pointer or class reference, + /// The expression for the base pointer or class reference, /// e.g., the \c x in x.f. Can be null in implicit accesses. Stmt *Base; - /// \brief The type of the base expression. Never null, even for + /// The type of the base expression. Never null, even for /// implicit accesses. QualType BaseType; - /// \brief Whether this member expression used the '->' operator or + /// Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; - /// \brief Whether this member expression has info for explicit template + /// Whether this member expression has info for explicit template /// keyword and arguments. bool HasTemplateKWAndArgsInfo : 1; - /// \brief The location of the '->' or '.' operator. + /// The location of the '->' or '.' operator. SourceLocation OperatorLoc; - /// \brief The nested-name-specifier that precedes the member name, if any. + /// The nested-name-specifier that precedes the member name, if any. NestedNameSpecifierLoc QualifierLoc; - /// \brief In a qualified member access expression such as t->Base::f, this + /// In a qualified member access expression such as t->Base::f, this /// member stores the resolves of name lookup in the context of the member /// access expression, to be used at instantiation time. /// @@ -3235,7 +3239,7 @@ class CXXDependentScopeMemberExpr final /// the CXXDependentScopeMemberExpr, to save space in the common case. NamedDecl *FirstQualifierFoundInScope; - /// \brief The member to which this member expression refers, which + /// The member to which this member expression refers, which /// can be name, overloaded operator, or destructor. /// /// FIXME: could also be a template-id @@ -3277,12 +3281,12 @@ public: CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); - /// \brief True if this is an implicit access, i.e. one in which the + /// True if this is an implicit access, i.e. one in which the /// member being accessed was not written in the source. The source /// location of the operator is invalid in this case. bool isImplicitAccess() const; - /// \brief Retrieve the base object of this member expressions, + /// Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. Expr *getBase() const { assert(!isImplicitAccess()); @@ -3291,24 +3295,24 @@ public: QualType getBaseType() const { return BaseType; } - /// \brief Determine whether this member expression used the '->' + /// Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - /// \brief Retrieve the location of the '->' or '.' operator. + /// Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Retrieve the nested-name-specifier that qualifies the member + /// Retrieve the nested-name-specifier that qualifies the member /// name. NestedNameSpecifier *getQualifier() const { return QualifierLoc.getNestedNameSpecifier(); } - /// \brief Retrieve the nested-name-specifier that qualifies the member + /// Retrieve the nested-name-specifier that qualifies the member /// name, with source location information. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the first part of the nested-name-specifier that was + /// Retrieve the first part of the nested-name-specifier that was /// found in the scope of the member access expression when the member access /// was initially parsed. /// @@ -3323,35 +3327,35 @@ public: return FirstQualifierFoundInScope; } - /// \brief Retrieve the name of the member that this expression + /// Retrieve the name of the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return MemberNameInfo; } - /// \brief Retrieve the name of the member that this expression + /// Retrieve the name of the member that this expression /// refers to. DeclarationName getMember() const { return MemberNameInfo.getName(); } - // \brief Retrieve the location of the name of the member that this + // Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return MemberNameInfo.getLoc(); } - /// \brief Retrieve the location of the template keyword preceding the + /// Retrieve the location of the template keyword preceding the /// member name, if any. SourceLocation getTemplateKeywordLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->TemplateKWLoc; } - /// \brief Retrieve the location of the left angle bracket starting the + /// Retrieve the location of the left angle bracket starting the /// explicit template argument list following the member name, if any. SourceLocation getLAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); return getTrailingObjects<ASTTemplateKWAndArgsInfo>()->LAngleLoc; } - /// \brief Retrieve the location of the right angle bracket ending the + /// Retrieve the location of the right angle bracket ending the /// explicit template argument list following the member name, if any. SourceLocation getRAngleLoc() const { if (!HasTemplateKWAndArgsInfo) return SourceLocation(); @@ -3361,11 +3365,11 @@ public: /// Determines whether the member name was preceded by the template keyword. bool hasTemplateKeyword() const { return getTemplateKeywordLoc().isValid(); } - /// \brief Determines whether this member expression actually had a C++ + /// Determines whether this member expression actually had a C++ /// template argument list explicitly specified, e.g., x.f<int>. bool hasExplicitTemplateArgs() const { return getLAngleLoc().isValid(); } - /// \brief Copies the template arguments (if present) into the given + /// Copies the template arguments (if present) into the given /// structure. void copyTemplateArgumentsInto(TemplateArgumentListInfo &List) const { if (hasExplicitTemplateArgs()) @@ -3373,7 +3377,7 @@ public: getTrailingObjects<TemplateArgumentLoc>(), List); } - /// \brief Retrieve the template arguments provided as part of this + /// Retrieve the template arguments provided as part of this /// template-id. const TemplateArgumentLoc *getTemplateArgs() const { if (!hasExplicitTemplateArgs()) @@ -3382,7 +3386,7 @@ public: return getTrailingObjects<TemplateArgumentLoc>(); } - /// \brief Retrieve the number of template arguments provided as part of this + /// Retrieve the number of template arguments provided as part of this /// template-id. unsigned getNumTemplateArgs() const { if (!hasExplicitTemplateArgs()) @@ -3421,7 +3425,7 @@ public: } }; -/// \brief Represents a C++ member access expression for which lookup +/// Represents a C++ member access expression for which lookup /// produced a set of overloaded functions. /// /// The member access may be explicit or implicit: @@ -3444,24 +3448,24 @@ class UnresolvedMemberExpr final friend class OverloadExpr; friend TrailingObjects; - /// \brief Whether this member expression used the '->' operator or + /// Whether this member expression used the '->' operator or /// the '.' operator. bool IsArrow : 1; - /// \brief Whether the lookup results contain an unresolved using + /// Whether the lookup results contain an unresolved using /// declaration. bool HasUnresolvedUsing : 1; - /// \brief The expression for the base pointer or class reference, + /// The expression for the base pointer or class reference, /// e.g., the \c x in x.f. /// /// This can be null if this is an 'unbased' member expression. Stmt *Base = nullptr; - /// \brief The type of the base expression; never null. + /// The type of the base expression; never null. QualType BaseType; - /// \brief The location of the '->' or '.' operator. + /// The location of the '->' or '.' operator. SourceLocation OperatorLoc; UnresolvedMemberExpr(const ASTContext &C, bool HasUnresolvedUsing, @@ -3496,13 +3500,13 @@ public: CreateEmpty(const ASTContext &C, bool HasTemplateKWAndArgsInfo, unsigned NumTemplateArgs); - /// \brief True if this is an implicit access, i.e., one in which the + /// True if this is an implicit access, i.e., one in which the /// member being accessed was not written in the source. /// /// The source location of the operator is invalid in this case. bool isImplicitAccess() const; - /// \brief Retrieve the base object of this member expressions, + /// Retrieve the base object of this member expressions, /// e.g., the \c x in \c x.m. Expr *getBase() { assert(!isImplicitAccess()); @@ -3515,33 +3519,33 @@ public: QualType getBaseType() const { return BaseType; } - /// \brief Determine whether the lookup results contain an unresolved using + /// Determine whether the lookup results contain an unresolved using /// declaration. bool hasUnresolvedUsing() const { return HasUnresolvedUsing; } - /// \brief Determine whether this member expression used the '->' + /// Determine whether this member expression used the '->' /// operator; otherwise, it used the '.' operator. bool isArrow() const { return IsArrow; } - /// \brief Retrieve the location of the '->' or '.' operator. + /// Retrieve the location of the '->' or '.' operator. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Retrieve the naming class of this lookup. + /// Retrieve the naming class of this lookup. CXXRecordDecl *getNamingClass() const; - /// \brief Retrieve the full name info for the member that this expression + /// Retrieve the full name info for the member that this expression /// refers to. const DeclarationNameInfo &getMemberNameInfo() const { return getNameInfo(); } - /// \brief Retrieve the name of the member that this expression + /// Retrieve the name of the member that this expression /// refers to. DeclarationName getMemberName() const { return getName(); } - // \brief Retrieve the location of the name of the member that this + // Retrieve the location of the name of the member that this // expression refers to. SourceLocation getMemberLoc() const { return getNameLoc(); } - // \brief Return the preferred location (the member name) for the arrow when + // Return the preferred location (the member name) for the arrow when // diagnosing a problem with this expression. SourceLocation getExprLoc() const LLVM_READONLY { return getMemberLoc(); } @@ -3593,7 +3597,7 @@ inline TemplateArgumentLoc *OverloadExpr::getTrailingTemplateArgumentLoc() { ->getTrailingObjects<TemplateArgumentLoc>(); } -/// \brief Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). +/// Represents a C++11 noexcept expression (C++ [expr.unary.noexcept]). /// /// The noexcept expression tests whether a given expression might throw. Its /// result is a boolean constant. @@ -3632,7 +3636,7 @@ public: child_range children() { return child_range(&Operand, &Operand + 1); } }; -/// \brief Represents a C++11 pack expansion that produces a sequence of +/// Represents a C++11 pack expansion that produces a sequence of /// expressions. /// /// A pack expansion expression contains a pattern (which itself is an @@ -3655,7 +3659,7 @@ class PackExpansionExpr : public Expr { SourceLocation EllipsisLoc; - /// \brief The number of expansions that will be produced by this pack + /// The number of expansions that will be produced by this pack /// expansion expression, if known. /// /// When zero, the number of expansions is not known. Otherwise, this value @@ -3677,17 +3681,17 @@ public: PackExpansionExpr(EmptyShell Empty) : Expr(PackExpansionExprClass, Empty) {} - /// \brief Retrieve the pattern of the pack expansion. + /// Retrieve the pattern of the pack expansion. Expr *getPattern() { return reinterpret_cast<Expr *>(Pattern); } - /// \brief Retrieve the pattern of the pack expansion. + /// Retrieve the pattern of the pack expansion. const Expr *getPattern() const { return reinterpret_cast<Expr *>(Pattern); } - /// \brief Retrieve the location of the ellipsis that describes this pack + /// Retrieve the location of the ellipsis that describes this pack /// expansion. SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - /// \brief Determine the number of expansions that will be produced when + /// Determine the number of expansions that will be produced when /// this pack expansion is instantiated, if already known. Optional<unsigned> getNumExpansions() const { if (NumExpansions) @@ -3712,7 +3716,7 @@ public: } }; -/// \brief Represents an expression that computes the length of a parameter +/// Represents an expression that computes the length of a parameter /// pack. /// /// \code @@ -3728,16 +3732,16 @@ class SizeOfPackExpr final friend class ASTStmtWriter; friend TrailingObjects; - /// \brief The location of the \c sizeof keyword. + /// The location of the \c sizeof keyword. SourceLocation OperatorLoc; - /// \brief The location of the name of the parameter pack. + /// The location of the name of the parameter pack. SourceLocation PackLoc; - /// \brief The location of the closing parenthesis. + /// The location of the closing parenthesis. SourceLocation RParenLoc; - /// \brief The length of the parameter pack, if known. + /// The length of the parameter pack, if known. /// /// When this expression is not value-dependent, this is the length of /// the pack. When the expression was parsed rather than instantiated @@ -3749,10 +3753,10 @@ class SizeOfPackExpr final /// and this is the length of that array. unsigned Length; - /// \brief The parameter pack. + /// The parameter pack. NamedDecl *Pack = nullptr; - /// \brief Create an expression that computes the length of + /// Create an expression that computes the length of /// the given parameter pack. SizeOfPackExpr(QualType SizeType, SourceLocation OperatorLoc, NamedDecl *Pack, SourceLocation PackLoc, SourceLocation RParenLoc, @@ -3765,11 +3769,11 @@ class SizeOfPackExpr final Length(Length ? *Length : PartialArgs.size()), Pack(Pack) { assert((!Length || PartialArgs.empty()) && "have partial args for non-dependent sizeof... expression"); - TemplateArgument *Args = getTrailingObjects<TemplateArgument>(); + auto *Args = getTrailingObjects<TemplateArgument>(); std::uninitialized_copy(PartialArgs.begin(), PartialArgs.end(), Args); } - /// \brief Create an empty expression. + /// Create an empty expression. SizeOfPackExpr(EmptyShell Empty, unsigned NumPartialArgs) : Expr(SizeOfPackExprClass, Empty), Length(NumPartialArgs) {} @@ -3782,19 +3786,19 @@ public: static SizeOfPackExpr *CreateDeserialized(ASTContext &Context, unsigned NumPartialArgs); - /// \brief Determine the location of the 'sizeof' keyword. + /// Determine the location of the 'sizeof' keyword. SourceLocation getOperatorLoc() const { return OperatorLoc; } - /// \brief Determine the location of the parameter pack. + /// Determine the location of the parameter pack. SourceLocation getPackLoc() const { return PackLoc; } - /// \brief Determine the location of the right parenthesis. + /// Determine the location of the right parenthesis. SourceLocation getRParenLoc() const { return RParenLoc; } - /// \brief Retrieve the parameter pack. + /// Retrieve the parameter pack. NamedDecl *getPack() const { return Pack; } - /// \brief Retrieve the length of the parameter pack. + /// Retrieve the length of the parameter pack. /// /// This routine may only be invoked when the expression is not /// value-dependent. @@ -3804,7 +3808,7 @@ public: return Length; } - /// \brief Determine whether this represents a partially-substituted sizeof... + /// Determine whether this represents a partially-substituted sizeof... /// expression, such as is produced for: /// /// template<typename ...Ts> using X = int[sizeof...(Ts)]; @@ -3813,10 +3817,10 @@ public: return isValueDependent() && Length; } - /// \brief Get + /// Get ArrayRef<TemplateArgument> getPartialArguments() const { assert(isPartiallySubstituted()); - const TemplateArgument *Args = getTrailingObjects<TemplateArgument>(); + const auto *Args = getTrailingObjects<TemplateArgument>(); return llvm::makeArrayRef(Args, Args + Length); } @@ -3833,19 +3837,19 @@ public: } }; -/// \brief Represents a reference to a non-type template parameter +/// Represents a reference to a non-type template parameter /// that has been substituted with a template argument. class SubstNonTypeTemplateParmExpr : public Expr { friend class ASTReader; friend class ASTStmtReader; - /// \brief The replaced parameter. + /// The replaced parameter. NonTypeTemplateParmDecl *Param; - /// \brief The replacement expression. + /// The replacement expression. Stmt *Replacement; - /// \brief The location of the non-type template parameter reference. + /// The location of the non-type template parameter reference. SourceLocation NameLoc; explicit SubstNonTypeTemplateParmExpr(EmptyShell Empty) @@ -3879,7 +3883,7 @@ public: child_range children() { return child_range(&Replacement, &Replacement+1); } }; -/// \brief Represents a reference to a non-type template parameter pack that +/// Represents a reference to a non-type template parameter pack that /// has been substituted with a non-template argument pack. /// /// When a pack expansion in the source code contains multiple parameter packs @@ -3895,17 +3899,17 @@ class SubstNonTypeTemplateParmPackExpr : public Expr { friend class ASTReader; friend class ASTStmtReader; - /// \brief The non-type template parameter pack itself. + /// The non-type template parameter pack itself. NonTypeTemplateParmDecl *Param; - /// \brief A pointer to the set of template arguments that this + /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - /// \brief The number of template arguments in \c Arguments. + /// The number of template arguments in \c Arguments. unsigned NumArguments; - /// \brief The location of the non-type template parameter pack reference. + /// The location of the non-type template parameter pack reference. SourceLocation NameLoc; explicit SubstNonTypeTemplateParmPackExpr(EmptyShell Empty) @@ -3913,17 +3917,18 @@ class SubstNonTypeTemplateParmPackExpr : public Expr { public: SubstNonTypeTemplateParmPackExpr(QualType T, + ExprValueKind ValueKind, NonTypeTemplateParmDecl *Param, SourceLocation NameLoc, const TemplateArgument &ArgPack); - /// \brief Retrieve the non-type template parameter pack being substituted. + /// Retrieve the non-type template parameter pack being substituted. NonTypeTemplateParmDecl *getParameterPack() const { return Param; } - /// \brief Retrieve the location of the parameter pack name. + /// Retrieve the location of the parameter pack name. SourceLocation getParameterPackLocation() const { return NameLoc; } - /// \brief Retrieve the template argument pack containing the substituted + /// Retrieve the template argument pack containing the substituted /// template arguments. TemplateArgument getArgumentPack() const; @@ -3940,7 +3945,7 @@ public: } }; -/// \brief Represents a reference to a function parameter pack that has been +/// Represents a reference to a function parameter pack that has been /// substituted but not yet expanded. /// /// When a pack expansion contains multiple parameter packs at different levels, @@ -3961,13 +3966,13 @@ class FunctionParmPackExpr final friend class ASTStmtReader; friend TrailingObjects; - /// \brief The function parameter pack which was referenced. + /// The function parameter pack which was referenced. ParmVarDecl *ParamPack; - /// \brief The location of the function parameter pack reference. + /// The location of the function parameter pack reference. SourceLocation NameLoc; - /// \brief The number of expansions of this pack. + /// The number of expansions of this pack. unsigned NumParameters; FunctionParmPackExpr(QualType T, ParmVarDecl *ParamPack, @@ -3982,22 +3987,22 @@ public: static FunctionParmPackExpr *CreateEmpty(const ASTContext &Context, unsigned NumParams); - /// \brief Get the parameter pack which this expression refers to. + /// Get the parameter pack which this expression refers to. ParmVarDecl *getParameterPack() const { return ParamPack; } - /// \brief Get the location of the parameter pack. + /// Get the location of the parameter pack. SourceLocation getParameterPackLocation() const { return NameLoc; } - /// \brief Iterators over the parameters which the parameter pack expanded + /// Iterators over the parameters which the parameter pack expanded /// into. using iterator = ParmVarDecl * const *; iterator begin() const { return getTrailingObjects<ParmVarDecl *>(); } iterator end() const { return begin() + NumParameters; } - /// \brief Get the number of parameters in this parameter pack. + /// Get the number of parameters in this parameter pack. unsigned getNumExpansions() const { return NumParameters; } - /// \brief Get an expansion of the parameter pack by index. + /// Get an expansion of the parameter pack by index. ParmVarDecl *getExpansion(unsigned I) const { return begin()[I]; } SourceLocation getLocStart() const LLVM_READONLY { return NameLoc; } @@ -4012,7 +4017,7 @@ public: } }; -/// \brief Represents a prvalue temporary that is written into memory so that +/// Represents a prvalue temporary that is written into memory so that /// a reference can bind to it. /// /// Prvalue expressions are materialized when they need to have an address @@ -4038,11 +4043,11 @@ private: friend class ASTStmtWriter; struct ExtraState { - /// \brief The temporary-generating expression whose value will be + /// The temporary-generating expression whose value will be /// materialized. Stmt *Temporary; - /// \brief The declaration which lifetime-extended this reference, if any. + /// The declaration which lifetime-extended this reference, if any. /// Either a VarDecl, or (for a ctor-initializer) a FieldDecl. const ValueDecl *ExtendingDecl; @@ -4071,11 +4076,11 @@ public: : State.get<ExtraState *>()->Temporary; } - /// \brief Retrieve the temporary-generating subexpression whose value will + /// Retrieve the temporary-generating subexpression whose value will /// be materialized into a glvalue. Expr *GetTemporaryExpr() const { return static_cast<Expr *>(getTemporary()); } - /// \brief Retrieve the storage duration for the materialized temporary. + /// Retrieve the storage duration for the materialized temporary. StorageDuration getStorageDuration() const { const ValueDecl *ExtendingDecl = getExtendingDecl(); if (!ExtendingDecl) @@ -4093,7 +4098,7 @@ public: return cast<VarDecl>(ExtendingDecl)->getStorageDuration(); } - /// \brief Get the declaration which triggered the lifetime-extension of this + /// Get the declaration which triggered the lifetime-extension of this /// temporary, if any. const ValueDecl *getExtendingDecl() const { return State.is<Stmt *>() ? nullptr @@ -4106,7 +4111,7 @@ public: return State.is<Stmt *>() ? 0 : State.get<ExtraState *>()->ManglingNumber; } - /// \brief Determine whether this materialized temporary is bound to an + /// Determine whether this materialized temporary is bound to an /// lvalue reference; otherwise, it's bound to an rvalue reference. bool isBoundToLvalueReference() const { return getValueKind() == VK_LValue; @@ -4134,7 +4139,7 @@ public: } }; -/// \brief Represents a folding of a pack over an operator. +/// Represents a folding of a pack over an operator. /// /// This expression is always dependent and represents a pack expansion of the /// forms: @@ -4203,7 +4208,7 @@ public: child_range children() { return child_range(SubExprs, SubExprs + 2); } }; -/// \brief Represents an expression that might suspend coroutine execution; +/// Represents an expression that might suspend coroutine execution; /// either a co_await or co_yield expression. /// /// Evaluation of this expression first evaluates its 'ready' expression. If @@ -4267,7 +4272,7 @@ public: return static_cast<Expr*>(SubExprs[SubExpr::Common]); } - /// \brief getOpaqueValue - Return the opaque value placeholder. + /// getOpaqueValue - Return the opaque value placeholder. OpaqueValueExpr *getOpaqueValue() const { return OpaqueValue; } Expr *getReadyExpr() const { @@ -4300,7 +4305,7 @@ public: } }; -/// \brief Represents a 'co_await' expression. +/// Represents a 'co_await' expression. class CoawaitExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; @@ -4335,7 +4340,7 @@ public: } }; -/// \brief Represents a 'co_await' expression while the type of the promise +/// Represents a 'co_await' expression while the type of the promise /// is dependent. class DependentCoawaitExpr : public Expr { friend class ASTStmtReader; @@ -4383,7 +4388,7 @@ public: } }; -/// \brief Represents a 'co_yield' expression. +/// Represents a 'co_yield' expression. class CoyieldExpr : public CoroutineSuspendExpr { friend class ASTStmtReader; diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h index ab2df8a34819e..5dac0e037da11 100644 --- a/include/clang/AST/ExprObjC.h +++ b/include/clang/AST/ExprObjC.h @@ -25,7 +25,6 @@ #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" @@ -36,6 +35,7 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/TrailingObjects.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Support/type_traits.h" #include <cassert> #include <cstddef> @@ -198,10 +198,10 @@ public: SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } SourceRange getSourceRange() const LLVM_READONLY { return Range; } - /// \brief Retrieve elements of array of literals. + /// Retrieve elements of array of literals. Expr **getElements() { return getTrailingObjects<Expr *>(); } - /// \brief Retrieve elements of array of literals. + /// Retrieve elements of array of literals. const Expr * const *getElements() const { return getTrailingObjects<Expr *>(); } @@ -212,11 +212,11 @@ public: /// getElement - Return the Element at the specified index. Expr *getElement(unsigned Index) { assert((Index < NumElements) && "Arg access out of range!"); - return cast<Expr>(getElements()[Index]); + return getElements()[Index]; } const Expr *getElement(unsigned Index) const { assert((Index < NumElements) && "Arg access out of range!"); - return cast<Expr>(getElements()[Index]); + return getElements()[Index]; } ObjCMethodDecl *getArrayWithObjectsMethod() const { @@ -234,23 +234,23 @@ public: } }; -/// \brief An element in an Objective-C dictionary literal. +/// An element in an Objective-C dictionary literal. /// struct ObjCDictionaryElement { - /// \brief The key for the dictionary element. + /// The key for the dictionary element. Expr *Key; - /// \brief The value of the dictionary element. + /// The value of the dictionary element. Expr *Value; - /// \brief The location of the ellipsis, if this is a pack expansion. + /// The location of the ellipsis, if this is a pack expansion. SourceLocation EllipsisLoc; - /// \brief The number of elements this pack expansion will expand to, if + /// The number of elements this pack expansion will expand to, if /// this is a pack expansion and is known. Optional<unsigned> NumExpansions; - /// \brief Determines whether this dictionary element is a pack expansion. + /// Determines whether this dictionary element is a pack expansion. bool isPackExpansion() const { return EllipsisLoc.isValid(); } }; @@ -264,21 +264,21 @@ template <> struct isPodLike<clang::ObjCDictionaryElement> : std::true_type {}; namespace clang { -/// \brief Internal struct for storing Key/value pair. +/// Internal struct for storing Key/value pair. struct ObjCDictionaryLiteral_KeyValuePair { Expr *Key; Expr *Value; }; -/// \brief Internal struct to describes an element that is a pack +/// Internal struct to describes an element that is a pack /// expansion, used if any of the elements in the dictionary literal /// are pack expansions. struct ObjCDictionaryLiteral_ExpansionData { - /// \brief The location of the ellipsis, if this element is a pack + /// The location of the ellipsis, if this element is a pack /// expansion. SourceLocation EllipsisLoc; - /// \brief If non-zero, the number of elements that this pack + /// If non-zero, the number of elements that this pack /// expansion will expand to (+1). unsigned NumExpansionsPlusOne; }; @@ -290,10 +290,10 @@ class ObjCDictionaryLiteral final private llvm::TrailingObjects<ObjCDictionaryLiteral, ObjCDictionaryLiteral_KeyValuePair, ObjCDictionaryLiteral_ExpansionData> { - /// \brief The number of elements in this dictionary literal. + /// The number of elements in this dictionary literal. unsigned NumElements : 31; - /// \brief Determine whether this dictionary literal has any pack expansions. + /// Determine whether this dictionary literal has any pack expansions. /// /// If the dictionary literal has pack expansions, then there will /// be an array of pack expansion data following the array of @@ -582,7 +582,7 @@ private: /// the pointer is an ObjCPropertyDecl and Setter is always null. llvm::PointerIntPair<NamedDecl *, 1, bool> PropertyOrGetter; - /// \brief Indicates whether the property reference will result in a message + /// Indicates whether the property reference will result in a message /// to the getter, the setter, or both. /// This applies to both implicit and explicit property references. enum MethodRefFlags { @@ -591,7 +591,7 @@ private: MethodRef_Setter = 0x2 }; - /// \brief Contains the Setter method pointer and MethodRefFlags bit flags. + /// Contains the Setter method pointer and MethodRefFlags bit flags. llvm::PointerIntPair<ObjCMethodDecl *, 2, unsigned> SetterAndMethodRefFlags; // FIXME: Maybe we should store the property identifier here, @@ -601,7 +601,7 @@ private: SourceLocation IdLoc; - /// \brief When the receiver in property access is 'super', this is + /// When the receiver in property access is 'super', this is /// the location of the 'super' keyword. When it's an interface, /// this is that interface. SourceLocation ReceiverLoc; @@ -694,14 +694,14 @@ public: return getExplicitProperty()->getSetterName(); } - /// \brief True if the property reference will result in a message to the + /// True if the property reference will result in a message to the /// getter. /// This applies to both implicit and explicit property references. bool isMessagingGetter() const { return SetterAndMethodRefFlags.getInt() & MethodRef_Getter; } - /// \brief True if the property reference will result in a message to the + /// True if the property reference will result in a message to the /// setter. /// This applies to both implicit and explicit property references. bool isMessagingSetter() const { @@ -874,7 +874,7 @@ private: friend class ASTStmtReader; }; -/// \brief An expression that sends a message to the given Objective-C +/// An expression that sends a message to the given Objective-C /// object or class. /// /// The following contains two message send expressions: @@ -903,47 +903,47 @@ private: class ObjCMessageExpr final : public Expr, private llvm::TrailingObjects<ObjCMessageExpr, void *, SourceLocation> { - /// \brief Stores either the selector that this message is sending + /// Stores either the selector that this message is sending /// to (when \c HasMethod is zero) or an \c ObjCMethodDecl pointer /// referring to the method that we type-checked against. uintptr_t SelectorOrMethod = 0; enum { NumArgsBitWidth = 16 }; - /// \brief The number of arguments in the message send, not + /// The number of arguments in the message send, not /// including the receiver. unsigned NumArgs : NumArgsBitWidth; - /// \brief The kind of message send this is, which is one of the + /// The kind of message send this is, which is one of the /// ReceiverKind values. /// /// We pad this out to a byte to avoid excessive masking and shifting. unsigned Kind : 8; - /// \brief Whether we have an actual method prototype in \c + /// Whether we have an actual method prototype in \c /// SelectorOrMethod. /// /// When non-zero, we have a method declaration; otherwise, we just /// have a selector. unsigned HasMethod : 1; - /// \brief Whether this message send is a "delegate init call", + /// Whether this message send is a "delegate init call", /// i.e. a call of an init method on self from within an init method. unsigned IsDelegateInitCall : 1; - /// \brief Whether this message send was implicitly generated by + /// Whether this message send was implicitly generated by /// the implementation rather than explicitly written by the user. unsigned IsImplicit : 1; - /// \brief Whether the locations of the selector identifiers are in a + /// Whether the locations of the selector identifiers are in a /// "standard" position, a enum SelectorLocationsKind. unsigned SelLocsKind : 2; - /// \brief When the message expression is a send to 'super', this is + /// When the message expression is a send to 'super', this is /// the location of the 'super' keyword. SourceLocation SuperLoc; - /// \brief The source locations of the open and close square + /// The source locations of the open and close square /// brackets ('[' and ']', respectively). SourceLocation LBracLoc, RBracLoc; @@ -997,10 +997,10 @@ class ObjCMessageExpr final ArrayRef<SourceLocation> SelLocs, SelectorLocationsKind SelLocsK); - /// \brief Retrieve the pointer value of the message receiver. + /// Retrieve the pointer value of the message receiver. void *getReceiverPointer() const { return *getTrailingObjects<void *>(); } - /// \brief Set the pointer value of the message receiver. + /// Set the pointer value of the message receiver. void setReceiverPointer(void *Value) { *getTrailingObjects<void *>() = Value; } @@ -1013,7 +1013,7 @@ class ObjCMessageExpr final return getSelLocsKind() != SelLoc_NonStandard; } - /// \brief Get a pointer to the stored selector identifiers locations array. + /// Get a pointer to the stored selector identifiers locations array. /// No locations will be stored if HasStandardSelLocs is true. SourceLocation *getStoredSelLocs() { return getTrailingObjects<SourceLocation>(); @@ -1022,7 +1022,7 @@ class ObjCMessageExpr final return getTrailingObjects<SourceLocation>(); } - /// \brief Get the number of stored selector identifiers locations. + /// Get the number of stored selector identifiers locations. /// No locations will be stored if HasStandardSelLocs is true. unsigned getNumStoredSelLocs() const { if (hasStandardSelLocs()) @@ -1045,22 +1045,22 @@ public: friend class ASTStmtWriter; friend TrailingObjects; - /// \brief The kind of receiver this message is sending to. + /// The kind of receiver this message is sending to. enum ReceiverKind { - /// \brief The receiver is a class. + /// The receiver is a class. Class = 0, - /// \brief The receiver is an object instance. + /// The receiver is an object instance. Instance, - /// \brief The receiver is a superclass. + /// The receiver is a superclass. SuperClass, - /// \brief The receiver is the instance of the superclass object. + /// The receiver is the instance of the superclass object. SuperInstance }; - /// \brief Create a message send to super. + /// Create a message send to super. /// /// \param Context The ASTContext in which this expression will be created. /// @@ -1098,7 +1098,7 @@ public: SourceLocation RBracLoc, bool isImplicit); - /// \brief Create a class message send. + /// Create a class message send. /// /// \param Context The ASTContext in which this expression will be created. /// @@ -1132,7 +1132,7 @@ public: SourceLocation RBracLoc, bool isImplicit); - /// \brief Create an instance message send. + /// Create an instance message send. /// /// \param Context The ASTContext in which this expression will be created. /// @@ -1166,7 +1166,7 @@ public: SourceLocation RBracLoc, bool isImplicit); - /// \brief Create an empty Objective-C message expression, to be + /// Create an empty Objective-C message expression, to be /// filled in by subsequent calls. /// /// \param Context The context in which the message send will be created. @@ -1177,31 +1177,31 @@ public: unsigned NumArgs, unsigned NumStoredSelLocs); - /// \brief Indicates whether the message send was implicitly + /// Indicates whether the message send was implicitly /// generated by the implementation. If false, it was written explicitly /// in the source code. bool isImplicit() const { return IsImplicit; } - /// \brief Determine the kind of receiver that this message is being + /// Determine the kind of receiver that this message is being /// sent to. ReceiverKind getReceiverKind() const { return (ReceiverKind)Kind; } - /// \brief Source range of the receiver. + /// Source range of the receiver. SourceRange getReceiverRange() const; - /// \brief Determine whether this is an instance message to either a + /// Determine whether this is an instance message to either a /// computed object or to super. bool isInstanceMessage() const { return getReceiverKind() == Instance || getReceiverKind() == SuperInstance; } - /// \brief Determine whether this is an class message to either a + /// Determine whether this is an class message to either a /// specified class or to super. bool isClassMessage() const { return getReceiverKind() == Class || getReceiverKind() == SuperClass; } - /// \brief Returns the object expression (receiver) for an instance message, + /// Returns the object expression (receiver) for an instance message, /// or null for a message that is not an instance message. Expr *getInstanceReceiver() { if (getReceiverKind() == Instance) @@ -1213,14 +1213,14 @@ public: return const_cast<ObjCMessageExpr*>(this)->getInstanceReceiver(); } - /// \brief Turn this message send into an instance message that + /// Turn this message send into an instance message that /// computes the receiver object with the given expression. void setInstanceReceiver(Expr *rec) { Kind = Instance; setReceiverPointer(rec); } - /// \brief Returns the type of a class message send, or NULL if the + /// Returns the type of a class message send, or NULL if the /// message is not a class message. QualType getClassReceiver() const { if (TypeSourceInfo *TSInfo = getClassReceiverTypeInfo()) @@ -1229,7 +1229,7 @@ public: return {}; } - /// \brief Returns a type-source information of a class message + /// Returns a type-source information of a class message /// send, or nullptr if the message is not a class message. TypeSourceInfo *getClassReceiverTypeInfo() const { if (getReceiverKind() == Class) @@ -1242,7 +1242,7 @@ public: setReceiverPointer(TSInfo); } - /// \brief Retrieve the location of the 'super' keyword for a class + /// Retrieve the location of the 'super' keyword for a class /// or instance message to 'super', otherwise an invalid source location. SourceLocation getSuperLoc() const { if (getReceiverKind() == SuperInstance || getReceiverKind() == SuperClass) @@ -1251,7 +1251,7 @@ public: return SourceLocation(); } - /// \brief Retrieve the receiver type to which this message is being directed. + /// Retrieve the receiver type to which this message is being directed. /// /// This routine cross-cuts all of the different kinds of message /// sends to determine what the underlying (statically known) type @@ -1262,7 +1262,7 @@ public: /// \returns The type of the receiver. QualType getReceiverType() const; - /// \brief Retrieve the Objective-C interface to which this message + /// Retrieve the Objective-C interface to which this message /// is being directed, if known. /// /// This routine cross-cuts all of the different kinds of message @@ -1274,7 +1274,7 @@ public: /// \returns The Objective-C interface if known, otherwise nullptr. ObjCInterfaceDecl *getReceiverInterface() const; - /// \brief Retrieve the type referred to by 'super'. + /// Retrieve the type referred to by 'super'. /// /// The returned type will either be an ObjCInterfaceType (for an /// class message to super) or an ObjCObjectPointerType that refers @@ -1323,11 +1323,11 @@ public: return getSelector().getMethodFamily(); } - /// \brief Return the number of actual arguments in this message, + /// Return the number of actual arguments in this message, /// not counting the receiver. unsigned getNumArgs() const { return NumArgs; } - /// \brief Retrieve the arguments to this message, not including the + /// Retrieve the arguments to this message, not including the /// receiver. Expr **getArgs() { return reinterpret_cast<Expr **>(getTrailingObjects<void *>() + 1); @@ -1455,7 +1455,7 @@ public: /*ContainsUnexpandedParameterPack=*/false), Base(base), IsaMemberLoc(l), OpLoc(oploc), IsArrow(isarrow) {} - /// \brief Build an empty expression. + /// Build an empty expression. explicit ObjCIsaExpr(EmptyShell Empty) : Expr(ObjCIsaExprClass, Empty) {} void setBase(Expr *E) { Base = E; } @@ -1563,7 +1563,7 @@ public: } }; -/// \brief An Objective-C "bridged" cast expression, which casts between +/// An Objective-C "bridged" cast expression, which casts between /// Objective-C pointers and C pointers, transferring ownership in the process. /// /// \code @@ -1589,21 +1589,21 @@ public: CK, Operand, 0, TSInfo), LParenLoc(LParenLoc), BridgeKeywordLoc(BridgeKeywordLoc), Kind(Kind) {} - /// \brief Construct an empty Objective-C bridged cast. + /// Construct an empty Objective-C bridged cast. explicit ObjCBridgedCastExpr(EmptyShell Shell) : ExplicitCastExpr(ObjCBridgedCastExprClass, Shell, 0) {} SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Determine which kind of bridge is being performed via this cast. + /// Determine which kind of bridge is being performed via this cast. ObjCBridgeCastKind getBridgeKind() const { return static_cast<ObjCBridgeCastKind>(Kind); } - /// \brief Retrieve the kind of bridge being performed as a string. + /// Retrieve the kind of bridge being performed as a string. StringRef getBridgeKindName() const; - /// \brief The location of the bridge keyword. + /// The location of the bridge keyword. SourceLocation getBridgeKeywordLoc() const { return BridgeKeywordLoc; } SourceLocation getLocStart() const LLVM_READONLY { return LParenLoc; } @@ -1617,7 +1617,7 @@ public: } }; -/// \brief A runtime availability query. +/// A runtime availability query. /// /// There are 2 ways to spell this node: /// \code @@ -1650,7 +1650,7 @@ public: SourceLocation getLocEnd() const { return RParen; } SourceRange getSourceRange() const { return {AtLoc, RParen}; } - /// \brief This may be '*', in which case this should fold to true. + /// This may be '*', in which case this should fold to true. bool hasVersion() const { return !VersionToCheck.empty(); } VersionTuple getVersion() { return VersionToCheck; } diff --git a/include/clang/AST/ExprOpenMP.h b/include/clang/AST/ExprOpenMP.h index a4ef93ba8b14a..2b4b5ec4d0e43 100644 --- a/include/clang/AST/ExprOpenMP.h +++ b/include/clang/AST/ExprOpenMP.h @@ -17,7 +17,7 @@ #include "clang/AST/Expr.h" namespace clang { -/// \brief OpenMP 4.0 [2.4, Array Sections]. +/// OpenMP 4.0 [2.4, Array Sections]. /// To specify an array section in an OpenMP construct, array subscript /// expressions are extended with the following syntax: /// \code @@ -72,33 +72,33 @@ public: SubExprs[LENGTH] = Length; } - /// \brief Create an empty array section expression. + /// Create an empty array section expression. explicit OMPArraySectionExpr(EmptyShell Shell) : Expr(OMPArraySectionExprClass, Shell) {} /// An array section can be written only as Base[LowerBound:Length]. - /// \brief Get base of the array section. + /// Get base of the array section. Expr *getBase() { return cast<Expr>(SubExprs[BASE]); } const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); } - /// \brief Set base of the array section. + /// Set base of the array section. void setBase(Expr *E) { SubExprs[BASE] = E; } - /// \brief Return original type of the base expression for array section. + /// Return original type of the base expression for array section. static QualType getBaseOriginalType(const Expr *Base); - /// \brief Get lower bound of array section. + /// Get lower bound of array section. Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); } const Expr *getLowerBound() const { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); } - /// \brief Set lower bound of the array section. + /// Set lower bound of the array section. void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; } - /// \brief Get length of array section. + /// Get length of array section. Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); } const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); } - /// \brief Set length of the array section. + /// Set length of the array section. void setLength(Expr *E) { SubExprs[LENGTH] = E; } SourceLocation getLocStart() const LLVM_READONLY { diff --git a/include/clang/AST/ExternalASTMerger.h b/include/clang/AST/ExternalASTMerger.h index 81492aec6e13e..ae8a761e127e5 100644 --- a/include/clang/AST/ExternalASTMerger.h +++ b/include/clang/AST/ExternalASTMerger.h @@ -97,7 +97,7 @@ public: /// Add a set of ASTContexts as possible origins. /// /// Usually the set will be initialized in the constructor, but long-lived - /// ExternalASTMergers may neeed to import from new sources (for example, + /// ExternalASTMergers may need to import from new sources (for example, /// newly-parsed source files). /// /// Ensures that Importers does not gain duplicate entries as a result. diff --git a/include/clang/AST/ExternalASTSource.h b/include/clang/AST/ExternalASTSource.h index be013c5d6b6a1..82255bb1c44c8 100644 --- a/include/clang/AST/ExternalASTSource.h +++ b/include/clang/AST/ExternalASTSource.h @@ -19,7 +19,6 @@ #include "clang/AST/DeclBase.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/Module.h" -#include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" @@ -54,7 +53,7 @@ class Selector; class Stmt; class TagDecl; -/// \brief Abstract interface for external sources of AST nodes. +/// Abstract interface for external sources of AST nodes. /// /// External AST sources provide AST nodes constructed from some /// external source, such as a precompiled header. External AST @@ -68,7 +67,7 @@ class ExternalASTSource : public RefCountedBase<ExternalASTSource> { /// whenever we might have added new redeclarations for existing decls. uint32_t CurrentGeneration = 0; - /// \brief Whether this AST source also provides information for + /// Whether this AST source also provides information for /// semantic analysis. bool SemaSource = false; @@ -76,7 +75,7 @@ public: ExternalASTSource() = default; virtual ~ExternalASTSource(); - /// \brief RAII class for safely pairing a StartedDeserializing call + /// RAII class for safely pairing a StartedDeserializing call /// with FinishedDeserializing. class Deserializing { ExternalASTSource *Source; @@ -92,12 +91,12 @@ public: } }; - /// \brief Get the current generation of this AST source. This number + /// Get the current generation of this AST source. This number /// is incremented each time the AST source lazily extends an existing /// entity. uint32_t getGeneration() const { return CurrentGeneration; } - /// \brief Resolve a declaration ID into a declaration, potentially + /// Resolve a declaration ID into a declaration, potentially /// building a new declaration. /// /// This method only needs to be implemented if the AST source ever @@ -106,7 +105,7 @@ public: /// The default implementation of this method is a no-op. virtual Decl *GetExternalDecl(uint32_t ID); - /// \brief Resolve a selector ID into a selector. + /// Resolve a selector ID into a selector. /// /// This operation only needs to be implemented if the AST source /// returns non-zero for GetNumKnownSelectors(). @@ -114,13 +113,13 @@ public: /// The default implementation of this method is a no-op. virtual Selector GetExternalSelector(uint32_t ID); - /// \brief Returns the number of selectors known to the external AST + /// Returns the number of selectors known to the external AST /// source. /// /// The default implementation of this method is a no-op. virtual uint32_t GetNumExternalSelectors(); - /// \brief Resolve the offset of a statement in the decl stream into + /// Resolve the offset of a statement in the decl stream into /// a statement. /// /// This operation is meant to be used via a LazyOffsetPtr. It only @@ -130,22 +129,22 @@ public: /// The default implementation of this method is a no-op. virtual Stmt *GetExternalDeclStmt(uint64_t Offset); - /// \brief Resolve the offset of a set of C++ constructor initializers in + /// Resolve the offset of a set of C++ constructor initializers in /// the decl stream into an array of initializers. /// /// The default implementation of this method is a no-op. virtual CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset); - /// \brief Resolve the offset of a set of C++ base specifiers in the decl + /// Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. /// /// The default implementation of this method is a no-op. virtual CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset); - /// \brief Update an out-of-date identifier. + /// Update an out-of-date identifier. virtual void updateOutOfDateIdentifier(IdentifierInfo &II) {} - /// \brief Find all declarations with the given name in the given context, + /// Find all declarations with the given name in the given context, /// and add them to the context by calling SetExternalVisibleDeclsForName /// or SetNoExternalVisibleDeclsForName. /// \return \c true if any declarations might have been found, \c false if @@ -155,15 +154,19 @@ public: virtual bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name); - /// \brief Ensures that the table of all visible declarations inside this + /// Ensures that the table of all visible declarations inside this /// context is up to date. /// /// The default implementation of this function is a no-op. virtual void completeVisibleDeclsMap(const DeclContext *DC); - /// \brief Retrieve the module that corresponds to the given module ID. + /// Retrieve the module that corresponds to the given module ID. virtual Module *getModule(unsigned ID) { return nullptr; } + /// Determine whether D comes from a PCH which was built with a corresponding + /// object file. + virtual bool DeclIsFromPCHWithObjectFile(const Decl *D) { return false; } + /// Abstracts clang modules and precompiled header files and holds /// everything needed to generate debug info for an imported module /// or PCH. @@ -196,7 +199,7 @@ public: virtual ExtKind hasExternalDefinitions(const Decl *D); - /// \brief Finds all declarations lexically contained within the given + /// Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// /// \param IsKindWeWant a predicate function that returns true if the passed @@ -208,31 +211,31 @@ public: llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl<Decl *> &Result); - /// \brief Finds all declarations lexically contained within the given + /// Finds all declarations lexically contained within the given /// DeclContext. void FindExternalLexicalDecls(const DeclContext *DC, SmallVectorImpl<Decl *> &Result) { FindExternalLexicalDecls(DC, [](Decl::Kind) { return true; }, Result); } - /// \brief Get the decls that are contained in a file in the Offset/Length + /// Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. virtual void FindFileRegionDecls(FileID File, unsigned Offset, unsigned Length, SmallVectorImpl<Decl *> &Decls); - /// \brief Gives the external AST source an opportunity to complete + /// Gives the external AST source an opportunity to complete /// the redeclaration chain for a declaration. Called each time we /// need the most recent declaration of a declaration after the /// generation count is incremented. virtual void CompleteRedeclChain(const Decl *D); - /// \brief Gives the external AST source an opportunity to complete + /// Gives the external AST source an opportunity to complete /// an incomplete type. virtual void CompleteType(TagDecl *Tag); - /// \brief Gives the external AST source an opportunity to complete an + /// Gives the external AST source an opportunity to complete an /// incomplete Objective-C class. /// /// This routine will only be invoked if the "externally completed" bit is @@ -240,35 +243,35 @@ public: /// \c ObjCInterfaceDecl::setExternallyCompleted(). virtual void CompleteType(ObjCInterfaceDecl *Class); - /// \brief Loads comment ranges. + /// Loads comment ranges. virtual void ReadComments(); - /// \brief Notify ExternalASTSource that we started deserialization of + /// Notify ExternalASTSource that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. /// /// The default implementation of this method is a no-op. virtual void StartedDeserializing(); - /// \brief Notify ExternalASTSource that we finished the deserialization of + /// Notify ExternalASTSource that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. /// /// The default implementation of this method is a no-op. virtual void FinishedDeserializing(); - /// \brief Function that will be invoked when we begin parsing a new + /// Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// /// The default implementation of this method is a no-op. virtual void StartTranslationUnit(ASTConsumer *Consumer); - /// \brief Print any statistics that have been gathered regarding + /// Print any statistics that have been gathered regarding /// the external AST source. /// /// The default implementation of this method is a no-op. virtual void PrintStats(); - /// \brief Perform layout on the given record. + /// Perform layout on the given record. /// /// This routine allows the external AST source to provide an specific /// layout for a record, overriding the layout that would normally be @@ -333,11 +336,11 @@ protected: SetNoExternalVisibleDeclsForName(const DeclContext *DC, DeclarationName Name); - /// \brief Increment the current generation. + /// Increment the current generation. uint32_t incrementGeneration(ASTContext &C); }; -/// \brief A lazy pointer to an AST node (of base type T) that resides +/// A lazy pointer to an AST node (of base type T) that resides /// within an external AST source. /// /// The AST node is identified within the external AST source by a @@ -345,7 +348,7 @@ protected: /// external AST source itself. template<typename T, typename OffsT, T* (ExternalASTSource::*Get)(OffsT Offset)> struct LazyOffsetPtr { - /// \brief Either a pointer to an AST node or the offset within the + /// Either a pointer to an AST node or the offset within the /// external AST source where the AST node can be found. /// /// If the low bit is clear, a pointer to the AST node. If the low @@ -377,20 +380,20 @@ public: return *this; } - /// \brief Whether this pointer is non-NULL. + /// Whether this pointer is non-NULL. /// /// This operation does not require the AST node to be deserialized. explicit operator bool() const { return Ptr != 0; } - /// \brief Whether this pointer is non-NULL. + /// Whether this pointer is non-NULL. /// /// This operation does not require the AST node to be deserialized. bool isValid() const { return Ptr != 0; } - /// \brief Whether this pointer is currently stored as an offset. + /// Whether this pointer is currently stored as an offset. bool isOffset() const { return Ptr & 0x01; } - /// \brief Retrieve the pointer to the AST node that this lazy pointer + /// Retrieve the pointer to the AST node that this lazy pointer points to. /// /// \param Source the external AST source. /// @@ -405,7 +408,7 @@ public: } }; -/// \brief A lazy value (of type T) that is within an AST node of type Owner, +/// A lazy value (of type T) that is within an AST node of type Owner, /// where the value might change in later generations of the external AST /// source. template<typename Owner, typename T, void (ExternalASTSource::*Update)(Owner)> @@ -447,7 +450,7 @@ public: /// Set the value of this pointer, in the current generation. void set(T NewValue) { - if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { + if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) { LazyVal->LastValue = NewValue; return; } @@ -459,7 +462,7 @@ public: /// Get the value of this pointer, updating its owner if necessary. T get(Owner O) { - if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) { + if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) { if (LazyVal->LastGeneration != LazyVal->ExternalSource->getGeneration()) { LazyVal->LastGeneration = LazyVal->ExternalSource->getGeneration(); (LazyVal->ExternalSource->*Update)(O); @@ -471,7 +474,7 @@ public: /// Get the most recently computed value of this pointer without updating it. T getNotUpdated() const { - if (LazyData *LazyVal = Value.template dyn_cast<LazyData*>()) + if (auto *LazyVal = Value.template dyn_cast<LazyData *>()) return LazyVal->LastValue; return Value.template get<T>(); } @@ -506,7 +509,7 @@ struct PointerLikeTypeTraits< namespace clang { -/// \brief Represents a lazily-loaded vector of data. +/// Represents a lazily-loaded vector of data. /// /// The lazily-loaded vector of data contains data that is partially loaded /// from an external source and partially added by local translation. The @@ -590,20 +593,20 @@ public: } }; -/// \brief A lazy pointer to a statement. +/// A lazy pointer to a statement. using LazyDeclStmtPtr = LazyOffsetPtr<Stmt, uint64_t, &ExternalASTSource::GetExternalDeclStmt>; -/// \brief A lazy pointer to a declaration. +/// A lazy pointer to a declaration. using LazyDeclPtr = LazyOffsetPtr<Decl, uint32_t, &ExternalASTSource::GetExternalDecl>; -/// \brief A lazy pointer to a set of CXXCtorInitializers. +/// A lazy pointer to a set of CXXCtorInitializers. using LazyCXXCtorInitializersPtr = LazyOffsetPtr<CXXCtorInitializer *, uint64_t, &ExternalASTSource::GetExternalCXXCtorInitializers>; -/// \brief A lazy pointer to a set of CXXBaseSpecifiers. +/// A lazy pointer to a set of CXXBaseSpecifiers. using LazyCXXBaseSpecifiersPtr = LazyOffsetPtr<CXXBaseSpecifier, uint64_t, &ExternalASTSource::GetExternalCXXBaseSpecifiers>; diff --git a/include/clang/AST/LambdaCapture.h b/include/clang/AST/LambdaCapture.h index 6517d656878ee..bcc5352c1c9dd 100644 --- a/include/clang/AST/LambdaCapture.h +++ b/include/clang/AST/LambdaCapture.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the LambdaCapture class. +/// Defines the LambdaCapture class. /// //===----------------------------------------------------------------------===// @@ -21,21 +21,21 @@ namespace clang { -/// \brief Describes the capture of a variable or of \c this, or of a +/// Describes the capture of a variable or of \c this, or of a /// C++1y init-capture. class LambdaCapture { enum { - /// \brief Flag used by the Capture class to indicate that the given + /// Flag used by the Capture class to indicate that the given /// capture was implicit. Capture_Implicit = 0x01, - /// \brief Flag used by the Capture class to indicate that the + /// Flag used by the Capture class to indicate that the /// given capture was by-copy. /// /// This includes the case of a non-reference init-capture. Capture_ByCopy = 0x02, - /// \brief Flag used by the Capture class to distinguish between a capture + /// Flag used by the Capture class to distinguish between a capture /// of '*this' and a capture of a VLA type. Capture_This = 0x04 }; @@ -56,7 +56,7 @@ class LambdaCapture { friend class ASTStmtWriter; public: - /// \brief Create a new capture of a variable or of \c this. + /// Create a new capture of a variable or of \c this. /// /// \param Loc The source location associated with this capture. /// @@ -75,29 +75,29 @@ public: VarDecl *Var = nullptr, SourceLocation EllipsisLoc = SourceLocation()); - /// \brief Determine the kind of capture. + /// Determine the kind of capture. LambdaCaptureKind getCaptureKind() const; - /// \brief Determine whether this capture handles the C++ \c this + /// Determine whether this capture handles the C++ \c this /// pointer. bool capturesThis() const { return DeclAndBits.getPointer() == nullptr && (DeclAndBits.getInt() & Capture_This); } - /// \brief Determine whether this capture handles a variable. + /// 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 + /// Determine whether this captures a variable length array bound /// expression. bool capturesVLAType() const { return DeclAndBits.getPointer() == nullptr && !(DeclAndBits.getInt() & Capture_This); } - /// \brief Retrieve the declaration of the local variable being + /// Retrieve the declaration of the local variable being /// captured. /// /// This operation is only valid if this capture is a variable capture @@ -107,17 +107,17 @@ public: return static_cast<VarDecl *>(DeclAndBits.getPointer()); } - /// \brief Determine whether this was an implicit capture (not + /// Determine whether this was an implicit capture (not /// written between the square brackets introducing the lambda). bool isImplicit() const { return DeclAndBits.getInt() & Capture_Implicit; } - /// \brief Determine whether this was an explicit capture (written + /// Determine whether this was an explicit capture (written /// between the square brackets introducing the lambda). bool isExplicit() const { return !isImplicit(); } - /// \brief Retrieve the source location of the capture. + /// Retrieve the source location of the capture. /// /// For an explicit capture, this returns the location of the /// explicit capture in the source. For an implicit capture, this @@ -125,11 +125,11 @@ public: /// used. SourceLocation getLocation() const { return Loc; } - /// \brief Determine whether this capture is a pack expansion, + /// Determine whether this capture is a pack expansion, /// which captures a function parameter pack. bool isPackExpansion() const { return EllipsisLoc.isValid(); } - /// \brief Retrieve the location of the ellipsis for a capture + /// Retrieve the location of the ellipsis for a capture /// that is a pack expansion. SourceLocation getEllipsisLoc() const { assert(isPackExpansion() && "No ellipsis location for a non-expansion"); diff --git a/include/clang/AST/LocInfoType.h b/include/clang/AST/LocInfoType.h index 7e573bd7bac44..802d9134ebde8 100644 --- a/include/clang/AST/LocInfoType.h +++ b/include/clang/AST/LocInfoType.h @@ -20,7 +20,7 @@ namespace clang { class TypeSourceInfo; -/// \brief Holds a QualType and a TypeSourceInfo* that came out of a declarator +/// Holds a QualType and a TypeSourceInfo* that came out of a declarator /// parsing. /// /// LocInfoType is a "transient" type, only needed for passing to/from Parser diff --git a/include/clang/AST/Mangle.h b/include/clang/AST/Mangle.h index 7a45d88c23c8f..401574b265b0e 100644 --- a/include/clang/AST/Mangle.h +++ b/include/clang/AST/Mangle.h @@ -30,6 +30,7 @@ namespace clang { class CXXDestructorDecl; class CXXMethodDecl; class FunctionDecl; + struct MethodVFTableLocation; class NamedDecl; class ObjCMethodDecl; class StringLiteral; @@ -182,14 +183,14 @@ public: explicit MicrosoftMangleContext(ASTContext &C, DiagnosticsEngine &D) : MangleContext(C, D, MK_Microsoft) {} - /// \brief Mangle vftable symbols. Only a subset of the bases along the path + /// Mangle vftable symbols. Only a subset of the bases along the path /// to the vftable are included in the name. It's up to the caller to pick /// them correctly. virtual void mangleCXXVFTable(const CXXRecordDecl *Derived, ArrayRef<const CXXRecordDecl *> BasePath, raw_ostream &Out) = 0; - /// \brief Mangle vbtable symbols. Only a subset of the bases along the path + /// Mangle vbtable symbols. Only a subset of the bases along the path /// to the vbtable are included in the name. It's up to the caller to pick /// them correctly. virtual void mangleCXXVBTable(const CXXRecordDecl *Derived, @@ -201,7 +202,8 @@ public: raw_ostream &Out) = 0; virtual void mangleVirtualMemPtrThunk(const CXXMethodDecl *MD, - raw_ostream &) = 0; + const MethodVFTableLocation &ML, + raw_ostream &Out) = 0; virtual void mangleCXXVirtualDisplacementMap(const CXXRecordDecl *SrcRD, const CXXRecordDecl *DstRD, diff --git a/include/clang/AST/MangleNumberingContext.h b/include/clang/AST/MangleNumberingContext.h index 869221dbf31b6..ff2148e3516db 100644 --- a/include/clang/AST/MangleNumberingContext.h +++ b/include/clang/AST/MangleNumberingContext.h @@ -27,29 +27,29 @@ class TagDecl; class Type; class VarDecl; -/// \brief Keeps track of the mangled names of lambda expressions and block +/// Keeps track of the mangled names of lambda expressions and block /// literals within a particular context. class MangleNumberingContext { public: virtual ~MangleNumberingContext() {} - /// \brief Retrieve the mangling number of a new lambda expression with the + /// Retrieve the mangling number of a new lambda expression with the /// given call operator within this context. virtual unsigned getManglingNumber(const CXXMethodDecl *CallOperator) = 0; - /// \brief Retrieve the mangling number of a new block literal within this + /// Retrieve the mangling number of a new block literal within this /// context. virtual unsigned getManglingNumber(const BlockDecl *BD) = 0; /// Static locals are numbered by source order. virtual unsigned getStaticLocalNumber(const VarDecl *VD) = 0; - /// \brief Retrieve the mangling number of a static local variable within + /// Retrieve the mangling number of a static local variable within /// this context. virtual unsigned getManglingNumber(const VarDecl *VD, unsigned MSLocalManglingNumber) = 0; - /// \brief Retrieve the mangling number of a static local variable within + /// Retrieve the mangling number of a static local variable within /// this context. virtual unsigned getManglingNumber(const TagDecl *TD, unsigned MSLocalManglingNumber) = 0; diff --git a/include/clang/AST/NSAPI.h b/include/clang/AST/NSAPI.h index 3757116e7c70e..ee07745b1242f 100644 --- a/include/clang/AST/NSAPI.h +++ b/include/clang/AST/NSAPI.h @@ -20,7 +20,7 @@ namespace clang { class QualType; class Expr; -// \brief Provides info and caches identifiers/selectors for NSFoundation API. +// Provides info and caches identifiers/selectors for NSFoundation API. class NSAPI { public: explicit NSAPI(ASTContext &Ctx); @@ -53,25 +53,25 @@ public: IdentifierInfo *getNSClassId(NSClassIdKindKind K) const; - /// \brief The Objective-C NSString selectors. + /// The Objective-C NSString selectors. Selector getNSStringSelector(NSStringMethodKind MK) const; - /// \brief Return NSStringMethodKind if \param Sel is such a selector. + /// Return NSStringMethodKind if \param Sel is such a selector. Optional<NSStringMethodKind> getNSStringMethodKind(Selector Sel) const; - /// \brief Returns true if the expression \param E is a reference of + /// Returns true if the expression \param E is a reference of /// "NSUTF8StringEncoding" enum constant. bool isNSUTF8StringEncodingConstant(const Expr *E) const { return isObjCEnumerator(E, "NSUTF8StringEncoding", NSUTF8StringEncodingId); } - /// \brief Returns true if the expression \param E is a reference of + /// Returns true if the expression \param E is a reference of /// "NSASCIIStringEncoding" enum constant. bool isNSASCIIStringEncodingConstant(const Expr *E) const { return isObjCEnumerator(E, "NSASCIIStringEncoding",NSASCIIStringEncodingId); } - /// \brief Enumerates the NSArray/NSMutableArray methods used to generate + /// Enumerates the NSArray/NSMutableArray methods used to generate /// literals and to apply some checks. enum NSArrayMethodKind { NSArr_array, @@ -89,13 +89,13 @@ public: }; static const unsigned NumNSArrayMethods = 12; - /// \brief The Objective-C NSArray selectors. + /// The Objective-C NSArray selectors. Selector getNSArraySelector(NSArrayMethodKind MK) const; - /// \brief Return NSArrayMethodKind if \p Sel is such a selector. + /// Return NSArrayMethodKind if \p Sel is such a selector. Optional<NSArrayMethodKind> getNSArrayMethodKind(Selector Sel); - /// \brief Enumerates the NSDictionary/NSMutableDictionary methods used + /// Enumerates the NSDictionary/NSMutableDictionary methods used /// to generate literals and to apply some checks. enum NSDictionaryMethodKind { NSDict_dictionary, @@ -114,13 +114,13 @@ public: }; static const unsigned NumNSDictionaryMethods = 13; - /// \brief The Objective-C NSDictionary selectors. + /// The Objective-C NSDictionary selectors. Selector getNSDictionarySelector(NSDictionaryMethodKind MK) const; - /// \brief Return NSDictionaryMethodKind if \p Sel is such a selector. + /// Return NSDictionaryMethodKind if \p Sel is such a selector. Optional<NSDictionaryMethodKind> getNSDictionaryMethodKind(Selector Sel); - /// \brief Enumerates the NSMutableSet/NSOrderedSet methods used + /// Enumerates the NSMutableSet/NSOrderedSet methods used /// to apply some checks. enum NSSetMethodKind { NSMutableSet_addObject, @@ -131,42 +131,42 @@ public: }; static const unsigned NumNSSetMethods = 5; - /// \brief The Objective-C NSSet selectors. + /// The Objective-C NSSet selectors. Selector getNSSetSelector(NSSetMethodKind MK) const; - /// \brief Return NSSetMethodKind if \p Sel is such a selector. + /// Return NSSetMethodKind if \p Sel is such a selector. Optional<NSSetMethodKind> getNSSetMethodKind(Selector Sel); - /// \brief Returns selector for "objectForKeyedSubscript:". + /// Returns selector for "objectForKeyedSubscript:". Selector getObjectForKeyedSubscriptSelector() const { return getOrInitSelector(StringRef("objectForKeyedSubscript"), objectForKeyedSubscriptSel); } - /// \brief Returns selector for "objectAtIndexedSubscript:". + /// Returns selector for "objectAtIndexedSubscript:". Selector getObjectAtIndexedSubscriptSelector() const { return getOrInitSelector(StringRef("objectAtIndexedSubscript"), objectAtIndexedSubscriptSel); } - /// \brief Returns selector for "setObject:forKeyedSubscript". + /// Returns selector for "setObject:forKeyedSubscript". Selector getSetObjectForKeyedSubscriptSelector() const { StringRef Ids[] = { "setObject", "forKeyedSubscript" }; return getOrInitSelector(Ids, setObjectForKeyedSubscriptSel); } - /// \brief Returns selector for "setObject:atIndexedSubscript". + /// Returns selector for "setObject:atIndexedSubscript". Selector getSetObjectAtIndexedSubscriptSelector() const { StringRef Ids[] = { "setObject", "atIndexedSubscript" }; return getOrInitSelector(Ids, setObjectAtIndexedSubscriptSel); } - /// \brief Returns selector for "isEqual:". + /// Returns selector for "isEqual:". Selector getIsEqualSelector() const { return getOrInitSelector(StringRef("isEqual"), isEqualSel); } - /// \brief Enumerates the NSNumber methods used to generate literals. + /// Enumerates the NSNumber methods used to generate literals. enum NSNumberLiteralMethodKind { NSNumberWithChar, NSNumberWithUnsignedChar, @@ -186,7 +186,7 @@ public: }; static const unsigned NumNSNumberLiteralMethods = 15; - /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. + /// The Objective-C NSNumber selectors used to create NSNumber literals. /// \param Instance if true it will return the selector for the init* method /// otherwise it will return the selector for the number* method. Selector getNSNumberLiteralSelector(NSNumberLiteralMethodKind MK, @@ -198,29 +198,29 @@ public: Sel == getNSNumberLiteralSelector(MK, true); } - /// \brief Return NSNumberLiteralMethodKind if \p Sel is such a selector. + /// Return NSNumberLiteralMethodKind if \p Sel is such a selector. Optional<NSNumberLiteralMethodKind> getNSNumberLiteralMethodKind(Selector Sel) const; - /// \brief Determine the appropriate NSNumber factory method kind for a + /// Determine the appropriate NSNumber factory method kind for a /// literal of the given type. Optional<NSNumberLiteralMethodKind> getNSNumberFactoryMethodKind(QualType T) const; - /// \brief Returns true if \param T is a typedef of "BOOL" in objective-c. + /// Returns true if \param T is a typedef of "BOOL" in objective-c. bool isObjCBOOLType(QualType T) const; - /// \brief Returns true if \param T is a typedef of "NSInteger" in objective-c. + /// Returns true if \param T is a typedef of "NSInteger" in objective-c. bool isObjCNSIntegerType(QualType T) const; - /// \brief Returns true if \param T is a typedef of "NSUInteger" in objective-c. + /// 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 + /// Returns one of NSIntegral typedef names if \param T is a typedef /// of that name in objective-c. StringRef GetNSIntegralKind(QualType T) const; - /// \brief Returns \c true if \p Id is currently defined as a macro. + /// Returns \c true if \p Id is currently defined as a macro. bool isMacroDefined(StringRef Id) const; - /// \brief Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind + /// Returns \c true if \p InterfaceDecl is subclass of \p NSClassKind bool isSubclassOfNSClass(ObjCInterfaceDecl *InterfaceDecl, NSClassIdKindKind NSClassKind) const; @@ -236,16 +236,16 @@ private: mutable Selector NSStringSelectors[NumNSStringMethods]; - /// \brief The selectors for Objective-C NSArray methods. + /// The selectors for Objective-C NSArray methods. mutable Selector NSArraySelectors[NumNSArrayMethods]; - /// \brief The selectors for Objective-C NSDictionary methods. + /// The selectors for Objective-C NSDictionary methods. mutable Selector NSDictionarySelectors[NumNSDictionaryMethods]; - /// \brief The selectors for Objective-C NSSet methods. + /// The selectors for Objective-C NSSet methods. mutable Selector NSSetSelectors[NumNSSetMethods]; - /// \brief The Objective-C NSNumber selectors used to create NSNumber literals. + /// The Objective-C NSNumber selectors used to create NSNumber literals. mutable Selector NSNumberClassSelectors[NumNSNumberLiteralMethods]; mutable Selector NSNumberInstanceSelectors[NumNSNumberLiteralMethods]; diff --git a/include/clang/AST/NestedNameSpecifier.h b/include/clang/AST/NestedNameSpecifier.h index e2cb45c36de6b..2255d5114350e 100644 --- a/include/clang/AST/NestedNameSpecifier.h +++ b/include/clang/AST/NestedNameSpecifier.h @@ -36,7 +36,7 @@ struct PrintingPolicy; class Type; class TypeLoc; -/// \brief Represents a C++ nested name specifier, such as +/// Represents a C++ nested name specifier, such as /// "\::std::vector<int>::". /// /// C++ nested name specifiers are the prefixes to qualified @@ -47,7 +47,7 @@ class TypeLoc; /// The last two specifiers can only appear at the start of a /// nested-namespace-specifier. class NestedNameSpecifier : public llvm::FoldingSetNode { - /// \brief Enumeration describing + /// Enumeration describing enum StoredSpecifierKind { StoredIdentifier = 0, StoredDecl = 1, @@ -55,7 +55,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { StoredTypeSpecWithTemplate = 3 }; - /// \brief The nested name specifier that precedes this nested name + /// The nested name specifier that precedes this nested name /// specifier. /// /// The pointer is the nested-name-specifier that precedes this @@ -63,7 +63,7 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { /// SpecifierKind. llvm::PointerIntPair<NestedNameSpecifier *, 2, StoredSpecifierKind> Prefix; - /// \brief The last component in the nested name specifier, which + /// The last component in the nested name specifier, which /// can be an identifier, a declaration, or a type. /// /// When the pointer is NULL, this specifier represents the global @@ -73,42 +73,42 @@ class NestedNameSpecifier : public llvm::FoldingSetNode { void* Specifier = nullptr; public: - /// \brief The kind of specifier that completes this nested name + /// The kind of specifier that completes this nested name /// specifier. enum SpecifierKind { - /// \brief An identifier, stored as an IdentifierInfo*. + /// An identifier, stored as an IdentifierInfo*. Identifier, - /// \brief A namespace, stored as a NamespaceDecl*. + /// A namespace, stored as a NamespaceDecl*. Namespace, - /// \brief A namespace alias, stored as a NamespaceAliasDecl*. + /// A namespace alias, stored as a NamespaceAliasDecl*. NamespaceAlias, - /// \brief A type, stored as a Type*. + /// A type, stored as a Type*. TypeSpec, - /// \brief A type that was preceded by the 'template' keyword, + /// A type that was preceded by the 'template' keyword, /// stored as a Type*. TypeSpecWithTemplate, - /// \brief The global specifier '::'. There is no stored value. + /// The global specifier '::'. There is no stored value. Global, - /// \brief Microsoft's '__super' specifier, stored as a CXXRecordDecl* of + /// Microsoft's '__super' specifier, stored as a CXXRecordDecl* of /// the class it appeared in. Super }; private: - /// \brief Builds the global specifier. + /// Builds the global specifier. NestedNameSpecifier() : Prefix(nullptr, StoredIdentifier) {} - /// \brief Copy constructor used internally to clone nested name + /// Copy constructor used internally to clone nested name /// specifiers. NestedNameSpecifier(const NestedNameSpecifier &Other) = default; - /// \brief Either find or insert the given nested name specifier + /// Either find or insert the given nested name specifier /// mockup in the given context. static NestedNameSpecifier *FindOrInsert(const ASTContext &Context, const NestedNameSpecifier &Mockup); @@ -116,7 +116,7 @@ private: public: NestedNameSpecifier &operator=(const NestedNameSpecifier &) = delete; - /// \brief Builds a specifier combining a prefix and an identifier. + /// Builds a specifier combining a prefix and an identifier. /// /// The prefix must be dependent, since nested name specifiers /// referencing an identifier are only permitted when the identifier @@ -125,22 +125,22 @@ public: NestedNameSpecifier *Prefix, IdentifierInfo *II); - /// \brief Builds a nested name specifier that names a namespace. + /// Builds a nested name specifier that names a namespace. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, const NamespaceDecl *NS); - /// \brief Builds a nested name specifier that names a namespace alias. + /// Builds a nested name specifier that names a namespace alias. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, NamespaceAliasDecl *Alias); - /// \brief Builds a nested name specifier that names a type. + /// Builds a nested name specifier that names a type. static NestedNameSpecifier *Create(const ASTContext &Context, NestedNameSpecifier *Prefix, bool Template, const Type *T); - /// \brief Builds a specifier that consists of just an identifier. + /// Builds a specifier that consists of just an identifier. /// /// The nested-name-specifier is assumed to be dependent, but has no /// prefix because the prefix is implied by something outside of the @@ -149,16 +149,16 @@ public: static NestedNameSpecifier *Create(const ASTContext &Context, IdentifierInfo *II); - /// \brief Returns the nested name specifier representing the global + /// Returns the nested name specifier representing the global /// scope. static NestedNameSpecifier *GlobalSpecifier(const ASTContext &Context); - /// \brief Returns the nested name specifier representing the __super scope + /// 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. + /// Return the prefix of this nested name specifier. /// /// The prefix contains all of the parts of the nested name /// specifier that preced this current specifier. For example, for a @@ -167,10 +167,10 @@ public: /// "foo::". NestedNameSpecifier *getPrefix() const { return Prefix.getPointer(); } - /// \brief Determine what kind of nested name specifier is stored. + /// Determine what kind of nested name specifier is stored. SpecifierKind getKind() const; - /// \brief Retrieve the identifier stored in this nested name + /// Retrieve the identifier stored in this nested name /// specifier. IdentifierInfo *getAsIdentifier() const { if (Prefix.getInt() == StoredIdentifier) @@ -179,19 +179,19 @@ public: return nullptr; } - /// \brief Retrieve the namespace stored in this nested name + /// Retrieve the namespace stored in this nested name /// specifier. NamespaceDecl *getAsNamespace() const; - /// \brief Retrieve the namespace alias stored in this nested name + /// Retrieve the namespace alias stored in this nested name /// specifier. NamespaceAliasDecl *getAsNamespaceAlias() const; - /// \brief Retrieve the record declaration stored in this nested name + /// Retrieve the record declaration stored in this nested name /// specifier. CXXRecordDecl *getAsRecordDecl() const; - /// \brief Retrieve the type stored in this nested name specifier. + /// Retrieve the type stored in this nested name specifier. const Type *getAsType() const { if (Prefix.getInt() == StoredTypeSpec || Prefix.getInt() == StoredTypeSpecWithTemplate) @@ -200,19 +200,19 @@ public: return nullptr; } - /// \brief Whether this nested name specifier refers to a dependent + /// Whether this nested name specifier refers to a dependent /// type or not. bool isDependent() const; - /// \brief Whether this nested name specifier involves a template + /// Whether this nested name specifier involves a template /// parameter. bool isInstantiationDependent() const; - /// \brief Whether this nested-name-specifier contains an unexpanded + /// Whether this nested-name-specifier contains an unexpanded /// parameter pack (for C++11 variadic templates). bool containsUnexpandedParameterPack() const; - /// \brief Print this nested name specifier to the given output + /// Print this nested name specifier to the given output /// stream. void print(raw_ostream &OS, const PrintingPolicy &Policy) const; @@ -221,53 +221,53 @@ public: ID.AddPointer(Specifier); } - /// \brief Dump the nested name specifier to standard output to aid + /// Dump the nested name specifier to standard output to aid /// in debugging. void dump(const LangOptions &LO) const; void dump() const; }; -/// \brief A C++ nested-name-specifier augmented with source location +/// A C++ nested-name-specifier augmented with source location /// information. class NestedNameSpecifierLoc { NestedNameSpecifier *Qualifier = nullptr; void *Data = nullptr; - /// \brief Determines the data length for the last component in the + /// Determines the data length for the last component in the /// given nested-name-specifier. static unsigned getLocalDataLength(NestedNameSpecifier *Qualifier); - /// \brief Determines the data length for the entire + /// Determines the data length for the entire /// nested-name-specifier. static unsigned getDataLength(NestedNameSpecifier *Qualifier); public: - /// \brief Construct an empty nested-name-specifier. + /// Construct an empty nested-name-specifier. NestedNameSpecifierLoc() = default; - /// \brief Construct a nested-name-specifier with source location information + /// Construct a nested-name-specifier with source location information /// from NestedNameSpecifierLoc(NestedNameSpecifier *Qualifier, void *Data) : Qualifier(Qualifier), Data(Data) {} - /// \brief Evalutes true when this nested-name-specifier location is + /// Evaluates true when this nested-name-specifier location is /// non-empty. explicit operator bool() const { return Qualifier; } - /// \brief Evalutes true when this nested-name-specifier location is + /// Evaluates true when this nested-name-specifier location is /// empty. bool hasQualifier() const { return Qualifier; } - /// \brief Retrieve the nested-name-specifier to which this instance + /// Retrieve the nested-name-specifier to which this instance /// refers. NestedNameSpecifier *getNestedNameSpecifier() const { return Qualifier; } - /// \brief Retrieve the opaque pointer that refers to source-location data. + /// Retrieve the opaque pointer that refers to source-location data. void *getOpaqueData() const { return Data; } - /// \brief Retrieve the source range covering the entirety of this + /// Retrieve the source range covering the entirety of this /// nested-name-specifier. /// /// For example, if this instance refers to a nested-name-specifier @@ -275,7 +275,7 @@ public: /// from the initial '::' to the last '::'. SourceRange getSourceRange() const LLVM_READONLY; - /// \brief Retrieve the source range covering just the last part of + /// Retrieve the source range covering just the last part of /// this nested-name-specifier, not including the prefix. /// /// For example, if this instance refers to a nested-name-specifier @@ -283,31 +283,31 @@ public: /// from "vector" to the last '::'. SourceRange getLocalSourceRange() const; - /// \brief Retrieve the location of the beginning of this + /// Retrieve the location of the beginning of this /// nested-name-specifier. SourceLocation getBeginLoc() const { return getSourceRange().getBegin(); } - /// \brief Retrieve the location of the end of this + /// Retrieve the location of the end of this /// nested-name-specifier. SourceLocation getEndLoc() const { return getSourceRange().getEnd(); } - /// \brief Retrieve the location of the beginning of this + /// Retrieve the location of the beginning of this /// component of the nested-name-specifier. SourceLocation getLocalBeginLoc() const { return getLocalSourceRange().getBegin(); } - /// \brief Retrieve the location of the end of this component of the + /// Retrieve the location of the end of this component of the /// nested-name-specifier. SourceLocation getLocalEndLoc() const { return getLocalSourceRange().getEnd(); } - /// \brief Return the prefix of this nested-name-specifier. + /// Return the prefix of this nested-name-specifier. /// /// For example, if this instance refers to a nested-name-specifier /// \c \::std::vector<int>::, the prefix is \c \::std::. Note that the @@ -320,11 +320,11 @@ public: return NestedNameSpecifierLoc(Qualifier->getPrefix(), Data); } - /// \brief For a nested-name-specifier that refers to a type, + /// For a nested-name-specifier that refers to a type, /// retrieve the type with source-location information. TypeLoc getTypeLoc() const; - /// \brief Determines the data length for the entire + /// Determines the data length for the entire /// nested-name-specifier. unsigned getDataLength() const { return getDataLength(Qualifier); } @@ -339,15 +339,15 @@ public: } }; -/// \brief Class that aids in the construction of nested-name-specifiers along +/// Class that aids in the construction of nested-name-specifiers along /// with source-location information for all of the components of the /// nested-name-specifier. class NestedNameSpecifierLocBuilder { - /// \brief The current representation of the nested-name-specifier we're + /// The current representation of the nested-name-specifier we're /// building. NestedNameSpecifier *Representation = nullptr; - /// \brief Buffer used to store source-location information for the + /// Buffer used to store source-location information for the /// nested-name-specifier. /// /// Note that we explicitly manage the buffer (rather than using a @@ -355,11 +355,11 @@ class NestedNameSpecifierLocBuilder { /// a \c CXXScopeSpec, and CXXScopeSpec uses a NestedNameSpecifierLocBuilder. char *Buffer = nullptr; - /// \brief The size of the buffer used to store source-location information + /// The size of the buffer used to store source-location information /// for the nested-name-specifier. unsigned BufferSize = 0; - /// \brief The capacity of the buffer used to store source-location + /// The capacity of the buffer used to store source-location /// information for the nested-name-specifier. unsigned BufferCapacity = 0; @@ -375,10 +375,10 @@ public: free(Buffer); } - /// \brief Retrieve the representation of the nested-name-specifier. + /// Retrieve the representation of the nested-name-specifier. NestedNameSpecifier *getRepresentation() const { return Representation; } - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'type::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -392,7 +392,7 @@ public: void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc); - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'identifier::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -406,7 +406,7 @@ public: void Extend(ASTContext &Context, IdentifierInfo *Identifier, SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -420,7 +420,7 @@ public: void Extend(ASTContext &Context, NamespaceDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace-alias::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -435,11 +435,11 @@ public: void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, SourceLocation AliasLoc, SourceLocation ColonColonLoc); - /// \brief Turn this (empty) nested-name-specifier into the global + /// 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' + /// Turns this (empty) nested-name-specifier into '__super' /// nested-name-specifier. /// /// \param Context The AST context in which this nested-name-specifier @@ -455,7 +455,7 @@ public: void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc, SourceLocation ColonColonLoc); - /// \brief Make a new nested-name-specifier from incomplete source-location + /// Make a new nested-name-specifier from incomplete source-location /// information. /// /// This routine should be used very, very rarely, in cases where we @@ -464,23 +464,23 @@ public: void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R); - /// \brief Adopt an existing nested-name-specifier (with source-range + /// Adopt an existing nested-name-specifier (with source-range /// information). void Adopt(NestedNameSpecifierLoc Other); - /// \brief Retrieve the source range covered by this nested-name-specifier. + /// Retrieve the source range covered by this nested-name-specifier. SourceRange getSourceRange() const LLVM_READONLY { return NestedNameSpecifierLoc(Representation, Buffer).getSourceRange(); } - /// \brief Retrieve a nested-name-specifier with location information, + /// Retrieve a nested-name-specifier with location information, /// copied into the given AST context. /// /// \param Context The context into which this nested-name-specifier will be /// copied. NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; - /// \brief Retrieve a nested-name-specifier with location + /// Retrieve a nested-name-specifier with location /// information based on the information in this builder. /// /// This loc will contain references to the builder's internal data and may @@ -489,14 +489,14 @@ public: return NestedNameSpecifierLoc(Representation, Buffer); } - /// \brief Clear out this builder, and prepare it to build another + /// Clear out this builder, and prepare it to build another /// nested-name-specifier with source-location information. void Clear() { Representation = nullptr; BufferSize = 0; } - /// \brief Retrieve the underlying buffer. + /// Retrieve the underlying buffer. /// /// \returns A pair containing a pointer to the buffer of source-location /// data and the size of the source-location data that resides in that diff --git a/include/clang/AST/NonTrivialTypeVisitor.h b/include/clang/AST/NonTrivialTypeVisitor.h new file mode 100644 index 0000000000000..bab373dbb2986 --- /dev/null +++ b/include/clang/AST/NonTrivialTypeVisitor.h @@ -0,0 +1,113 @@ +//===-- NonTrivialTypeVisitor.h - Visitor for non-trivial Types *- 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 visitor classes that are used to traverse non-trivial +// structs. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H +#define LLVM_CLANG_NON_TRIVIAL_TYPE_VISITOR_H + +#include "clang/AST/Type.h" + +namespace clang { + +template <class Derived, class RetTy = void> struct DestructedTypeVisitor { + template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) { + return asDerived().visitWithKind(FT.isDestructedType(), FT, + std::forward<Ts>(Args)...); + } + + template <class... Ts> + RetTy visitWithKind(QualType::DestructionKind DK, QualType FT, + Ts &&... Args) { + switch (DK) { + case QualType::DK_objc_strong_lifetime: + return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); + case QualType::DK_nontrivial_c_struct: + return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); + case QualType::DK_none: + return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...); + case QualType::DK_cxx_destructor: + return asDerived().visitCXXDestructor(FT, std::forward<Ts>(Args)...); + case QualType::DK_objc_weak_lifetime: + return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); + } + + llvm_unreachable("unknown destruction kind"); + } + + Derived &asDerived() { return static_cast<Derived &>(*this); } +}; + +template <class Derived, class RetTy = void> +struct DefaultInitializedTypeVisitor { + template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) { + return asDerived().visitWithKind( + FT.isNonTrivialToPrimitiveDefaultInitialize(), FT, + std::forward<Ts>(Args)...); + } + + template <class... Ts> + RetTy visitWithKind(QualType::PrimitiveDefaultInitializeKind PDIK, + QualType FT, Ts &&... Args) { + switch (PDIK) { + case QualType::PDIK_ARCStrong: + return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); + case QualType::PDIK_ARCWeak: + return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); + case QualType::PDIK_Struct: + return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); + case QualType::PDIK_Trivial: + return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...); + } + + llvm_unreachable("unknown default-initialize kind"); + } + + Derived &asDerived() { return static_cast<Derived &>(*this); } +}; + +template <class Derived, bool IsMove, class RetTy = void> +struct CopiedTypeVisitor { + template <class... Ts> RetTy visit(QualType FT, Ts &&... Args) { + QualType::PrimitiveCopyKind PCK = + IsMove ? FT.isNonTrivialToPrimitiveDestructiveMove() + : FT.isNonTrivialToPrimitiveCopy(); + return asDerived().visitWithKind(PCK, FT, std::forward<Ts>(Args)...); + } + + template <class... Ts> + RetTy visitWithKind(QualType::PrimitiveCopyKind PCK, QualType FT, + Ts &&... Args) { + asDerived().preVisit(PCK, FT, std::forward<Ts>(Args)...); + + switch (PCK) { + case QualType::PCK_ARCStrong: + return asDerived().visitARCStrong(FT, std::forward<Ts>(Args)...); + case QualType::PCK_ARCWeak: + return asDerived().visitARCWeak(FT, std::forward<Ts>(Args)...); + case QualType::PCK_Struct: + return asDerived().visitStruct(FT, std::forward<Ts>(Args)...); + case QualType::PCK_Trivial: + return asDerived().visitTrivial(FT, std::forward<Ts>(Args)...); + case QualType::PCK_VolatileTrivial: + return asDerived().visitVolatileTrivial(FT, std::forward<Ts>(Args)...); + } + + llvm_unreachable("unknown primitive copy kind"); + } + + Derived &asDerived() { return static_cast<Derived &>(*this); } +}; + +} // end namespace clang + +#endif diff --git a/include/clang/AST/ODRHash.h b/include/clang/AST/ODRHash.h index ed648bb8afb11..75b3617892110 100644 --- a/include/clang/AST/ODRHash.h +++ b/include/clang/AST/ODRHash.h @@ -37,9 +37,9 @@ class TemplateParameterList; // Typically, only one Add* call is needed. clear can be called to reuse the // object. class ODRHash { - // Use DenseMaps to convert between Decl and Type pointers and an index value. - llvm::DenseMap<const Decl*, unsigned> DeclMap; - llvm::DenseMap<const Type*, unsigned> TypeMap; + // Use DenseMaps to convert from DeclarationName and Type pointers + // to an index value. + llvm::DenseMap<DeclarationName, unsigned> DeclNameMap; // Save space by processing bools at the end. llvm::SmallVector<bool, 128> Bools; @@ -54,8 +54,13 @@ public: void AddCXXRecordDecl(const CXXRecordDecl *Record); // Use this for ODR checking functions between modules. This method compares + // more information than the AddDecl class. SkipBody will process the + // hash as if the function has no body. + void AddFunctionDecl(const FunctionDecl *Function, bool SkipBody = false); + + // Use this for ODR checking enums between modules. This method compares // more information than the AddDecl class. - void AddFunctionDecl(const FunctionDecl *Function); + void AddEnumDecl(const EnumDecl *Enum); // Process SubDecls of the main Decl. This method calls the DeclVisitor // while AddDecl does not. @@ -82,7 +87,7 @@ public: // Save booleans until the end to lower the size of data to process. void AddBoolean(bool value); - static bool isWhitelistedDecl(const Decl* D, const CXXRecordDecl *Record); + static bool isWhitelistedDecl(const Decl* D, const DeclContext *Parent); }; } // end namespace clang diff --git a/include/clang/AST/OpenMPClause.h b/include/clang/AST/OpenMPClause.h index 1f732f67517a4..a28609f8cdf96 100644 --- a/include/clang/AST/OpenMPClause.h +++ b/include/clang/AST/OpenMPClause.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief This file defines OpenMP AST classes for clauses. +/// This file defines OpenMP AST classes for clauses. /// There are clauses for executable directives, clauses for declarative /// directives and clauses which can be used in both kinds of directives. // @@ -47,15 +47,15 @@ class ASTContext; // AST classes for clauses. //===----------------------------------------------------------------------===// -/// \brief This is a basic class for representing single OpenMP clause. +/// This is a basic class for representing single OpenMP clause. class OMPClause { - /// \brief Starting location of the clause (the clause keyword). + /// Starting location of the clause (the clause keyword). SourceLocation StartLoc; - /// \brief Ending location of the clause. + /// Ending location of the clause. SourceLocation EndLoc; - /// \brief Kind of the clause. + /// Kind of the clause. OpenMPClauseKind Kind; protected: @@ -63,19 +63,19 @@ protected: : StartLoc(StartLoc), EndLoc(EndLoc), Kind(K) {} public: - /// \brief Returns the starting location of the clause. + /// Returns the starting location of the clause. SourceLocation getLocStart() const { return StartLoc; } - /// \brief Returns the ending location of the clause. + /// Returns the ending location of the clause. SourceLocation getLocEnd() const { return EndLoc; } - /// \brief Sets the starting location of the clause. + /// Sets the starting location of the clause. void setLocStart(SourceLocation Loc) { StartLoc = Loc; } - /// \brief Sets the ending location of the clause. + /// Sets the ending location of the clause. void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } - /// \brief Returns kind of OpenMP clause (private, shared, reduction, etc.). + /// Returns kind of OpenMP clause (private, shared, reduction, etc.). OpenMPClauseKind getClauseKind() const { return Kind; } bool isImplicit() const { return StartLoc.isInvalid(); } @@ -124,7 +124,7 @@ public: Stmt *getPreInitStmt() { return PreInit; } /// Get capture region for the stmt in the clause. - OpenMPDirectiveKind getCaptureRegion() { return CaptureRegion; } + OpenMPDirectiveKind getCaptureRegion() const { return CaptureRegion; } static OMPClauseWithPreInit *get(OMPClause *C); static const OMPClauseWithPreInit *get(const OMPClause *C); @@ -157,20 +157,20 @@ public: static const OMPClauseWithPostUpdate *get(const OMPClause *C); }; -/// \brief This represents clauses with the list of variables like 'private', +/// This represents clauses with the list of variables like 'private', /// 'firstprivate', 'copyin', 'shared', or 'reduction' clauses in the /// '#pragma omp ...' directives. template <class T> class OMPVarListClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Number of variables in the list. + /// Number of variables in the list. unsigned NumVars; protected: - /// \brief Build a clause with \a N variables + /// Build a clause with \a N variables /// /// \param K Kind of the clause. /// \param StartLoc Starting location of the clause (the clause keyword). @@ -181,13 +181,13 @@ protected: SourceLocation LParenLoc, SourceLocation EndLoc, unsigned N) : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc), NumVars(N) {} - /// \brief Fetches list of variables associated with this clause. + /// Fetches list of variables associated with this clause. MutableArrayRef<Expr *> getVarRefs() { return MutableArrayRef<Expr *>( static_cast<T *>(this)->template getTrailingObjects<Expr *>(), NumVars); } - /// \brief Sets the list of variables for this clause. + /// Sets the list of variables for this clause. void setVarRefs(ArrayRef<Expr *> VL) { assert(VL.size() == NumVars && "Number of variables is not the same as the preallocated buffer"); @@ -216,13 +216,13 @@ public: varlist_const_iterator varlist_begin() const { return getVarRefs().begin(); } varlist_const_iterator varlist_end() const { return getVarRefs().end(); } - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Fetches list of all variables in the clause. + /// Fetches list of all variables in the clause. ArrayRef<const Expr *> getVarRefs() const { return llvm::makeArrayRef( static_cast<const T *>(this)->template getTrailingObjects<Expr *>(), @@ -230,7 +230,7 @@ public: } }; -/// \brief This represents 'if' clause in the '#pragma omp ...' directive. +/// This represents 'if' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp parallel if(parallel:a > 5) @@ -240,35 +240,35 @@ public: class OMPIfClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Condition of the 'if' clause. + /// Condition of the 'if' clause. Stmt *Condition = nullptr; - /// \brief Location of ':' (if any). + /// Location of ':' (if any). SourceLocation ColonLoc; - /// \brief Directive name modifier for the clause. + /// Directive name modifier for the clause. OpenMPDirectiveKind NameModifier = OMPD_unknown; - /// \brief Name modifier location. + /// Name modifier location. SourceLocation NameModifierLoc; - /// \brief Set condition. + /// Set condition. void setCondition(Expr *Cond) { Condition = Cond; } - /// \brief Set directive name modifier for the clause. + /// Set directive name modifier for the clause. void setNameModifier(OpenMPDirectiveKind NM) { NameModifier = NM; } - /// \brief Set location of directive name modifier for the clause. + /// Set location of directive name modifier for the clause. void setNameModifierLoc(SourceLocation Loc) { NameModifierLoc = Loc; } - /// \brief Set location of ':'. + /// Set location of ':'. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } public: - /// \brief Build 'if' clause with condition \a Cond. + /// Build 'if' clause with condition \a Cond. /// /// \param NameModifier [OpenMP 4.1] Directive name modifier of clause. /// \param Cond Condition of the clause. @@ -290,27 +290,27 @@ public: setPreInitStmt(HelperCond, CaptureRegion); } - /// \brief Build an empty clause. + /// Build an empty clause. OMPIfClause() : OMPClause(OMPC_if, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return the location of ':'. + /// Return the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Returns condition. + /// Returns condition. Expr *getCondition() const { return cast_or_null<Expr>(Condition); } - /// \brief Return directive name modifier associated with the clause. + /// Return directive name modifier associated with the clause. OpenMPDirectiveKind getNameModifier() const { return NameModifier; } - /// \brief Return the location of directive name modifier. + /// Return the location of directive name modifier. SourceLocation getNameModifierLoc() const { return NameModifierLoc; } child_range children() { return child_range(&Condition, &Condition + 1); } @@ -320,7 +320,7 @@ public: } }; -/// \brief This represents 'final' clause in the '#pragma omp ...' directive. +/// This represents 'final' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp task final(a > 5) @@ -330,17 +330,17 @@ public: class OMPFinalClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Condition of the 'if' clause. + /// Condition of the 'if' clause. Stmt *Condition = nullptr; - /// \brief Set condition. + /// Set condition. void setCondition(Expr *Cond) { Condition = Cond; } public: - /// \brief Build 'final' clause with condition \a Cond. + /// Build 'final' clause with condition \a Cond. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -351,17 +351,17 @@ public: : OMPClause(OMPC_final, StartLoc, EndLoc), LParenLoc(LParenLoc), Condition(Cond) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPFinalClause() : OMPClause(OMPC_final, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Returns condition. + /// Returns condition. Expr *getCondition() const { return cast_or_null<Expr>(Condition); } child_range children() { return child_range(&Condition, &Condition + 1); } @@ -371,7 +371,7 @@ public: } }; -/// \brief This represents 'num_threads' clause in the '#pragma omp ...' +/// This represents 'num_threads' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -382,17 +382,17 @@ public: class OMPNumThreadsClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Condition of the 'num_threads' clause. + /// Condition of the 'num_threads' clause. Stmt *NumThreads = nullptr; - /// \brief Set condition. + /// Set condition. void setNumThreads(Expr *NThreads) { NumThreads = NThreads; } public: - /// \brief Build 'num_threads' clause with condition \a NumThreads. + /// Build 'num_threads' clause with condition \a NumThreads. /// /// \param NumThreads Number of threads for the construct. /// \param HelperNumThreads Helper Number of threads for the construct. @@ -411,18 +411,18 @@ public: setPreInitStmt(HelperNumThreads, CaptureRegion); } - /// \brief Build an empty clause. + /// Build an empty clause. OMPNumThreadsClause() : OMPClause(OMPC_num_threads, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Returns number of threads. + /// Returns number of threads. Expr *getNumThreads() const { return cast_or_null<Expr>(NumThreads); } child_range children() { return child_range(&NumThreads, &NumThreads + 1); } @@ -432,7 +432,7 @@ public: } }; -/// \brief This represents 'safelen' clause in the '#pragma omp ...' +/// This represents 'safelen' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -447,17 +447,17 @@ public: class OMPSafelenClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Safe iteration space distance. + /// Safe iteration space distance. Stmt *Safelen = nullptr; - /// \brief Set safelen. + /// Set safelen. void setSafelen(Expr *Len) { Safelen = Len; } public: - /// \brief Build 'safelen' clause. + /// Build 'safelen' clause. /// /// \param Len Expression associated with this clause. /// \param StartLoc Starting location of the clause. @@ -467,17 +467,17 @@ public: : OMPClause(OMPC_safelen, StartLoc, EndLoc), LParenLoc(LParenLoc), Safelen(Len) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPSafelenClause() : OMPClause(OMPC_safelen, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return safe iteration space distance. + /// Return safe iteration space distance. Expr *getSafelen() const { return cast_or_null<Expr>(Safelen); } child_range children() { return child_range(&Safelen, &Safelen + 1); } @@ -487,7 +487,7 @@ public: } }; -/// \brief This represents 'simdlen' clause in the '#pragma omp ...' +/// This represents 'simdlen' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -501,17 +501,17 @@ public: class OMPSimdlenClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Safe iteration space distance. + /// Safe iteration space distance. Stmt *Simdlen = nullptr; - /// \brief Set simdlen. + /// Set simdlen. void setSimdlen(Expr *Len) { Simdlen = Len; } public: - /// \brief Build 'simdlen' clause. + /// Build 'simdlen' clause. /// /// \param Len Expression associated with this clause. /// \param StartLoc Starting location of the clause. @@ -521,17 +521,17 @@ public: : OMPClause(OMPC_simdlen, StartLoc, EndLoc), LParenLoc(LParenLoc), Simdlen(Len) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPSimdlenClause() : OMPClause(OMPC_simdlen, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return safe iteration space distance. + /// Return safe iteration space distance. Expr *getSimdlen() const { return cast_or_null<Expr>(Simdlen); } child_range children() { return child_range(&Simdlen, &Simdlen + 1); } @@ -541,7 +541,7 @@ public: } }; -/// \brief This represents 'collapse' clause in the '#pragma omp ...' +/// This represents 'collapse' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -555,17 +555,17 @@ public: class OMPCollapseClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Number of for-loops. + /// Number of for-loops. Stmt *NumForLoops = nullptr; - /// \brief Set the number of associated for-loops. + /// Set the number of associated for-loops. void setNumForLoops(Expr *Num) { NumForLoops = Num; } public: - /// \brief Build 'collapse' clause. + /// Build 'collapse' clause. /// /// \param Num Expression associated with this clause. /// \param StartLoc Starting location of the clause. @@ -576,17 +576,17 @@ public: : OMPClause(OMPC_collapse, StartLoc, EndLoc), LParenLoc(LParenLoc), NumForLoops(Num) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPCollapseClause() : OMPClause(OMPC_collapse, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return the number of associated for-loops. + /// Return the number of associated for-loops. Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } @@ -596,7 +596,7 @@ public: } }; -/// \brief This represents 'default' clause in the '#pragma omp ...' directive. +/// This represents 'default' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp parallel default(shared) @@ -606,27 +606,27 @@ public: class OMPDefaultClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief A kind of the 'default' clause. + /// A kind of the 'default' clause. OpenMPDefaultClauseKind Kind = OMPC_DEFAULT_unknown; - /// \brief Start location of the kind in source code. + /// Start location of the kind in source code. SourceLocation KindKwLoc; - /// \brief Set kind of the clauses. + /// Set kind of the clauses. /// /// \param K Argument of clause. void setDefaultKind(OpenMPDefaultClauseKind K) { Kind = K; } - /// \brief Set argument location. + /// Set argument location. /// /// \param KLoc Argument location. void setDefaultKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } public: - /// \brief Build 'default' clause with argument \a A ('none' or 'shared'). + /// Build 'default' clause with argument \a A ('none' or 'shared'). /// /// \param A Argument of the clause ('none' or 'shared'). /// \param ALoc Starting location of the argument. @@ -639,20 +639,20 @@ public: : OMPClause(OMPC_default, StartLoc, EndLoc), LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPDefaultClause() : OMPClause(OMPC_default, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Returns kind of the clause. + /// Returns kind of the clause. OpenMPDefaultClauseKind getDefaultKind() const { return Kind; } - /// \brief Returns location of clause kind. + /// Returns location of clause kind. SourceLocation getDefaultKindKwLoc() const { return KindKwLoc; } child_range children() { @@ -664,7 +664,7 @@ public: } }; -/// \brief This represents 'proc_bind' clause in the '#pragma omp ...' +/// This represents 'proc_bind' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -675,27 +675,27 @@ public: class OMPProcBindClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief A kind of the 'proc_bind' clause. + /// A kind of the 'proc_bind' clause. OpenMPProcBindClauseKind Kind = OMPC_PROC_BIND_unknown; - /// \brief Start location of the kind in source code. + /// Start location of the kind in source code. SourceLocation KindKwLoc; - /// \brief Set kind of the clause. + /// Set kind of the clause. /// /// \param K Kind of clause. void setProcBindKind(OpenMPProcBindClauseKind K) { Kind = K; } - /// \brief Set clause kind location. + /// Set clause kind location. /// /// \param KLoc Kind location. void setProcBindKindKwLoc(SourceLocation KLoc) { KindKwLoc = KLoc; } public: - /// \brief Build 'proc_bind' clause with argument \a A ('master', 'close' or + /// Build 'proc_bind' clause with argument \a A ('master', 'close' or /// 'spread'). /// /// \param A Argument of the clause ('master', 'close' or 'spread'). @@ -709,20 +709,20 @@ public: : OMPClause(OMPC_proc_bind, StartLoc, EndLoc), LParenLoc(LParenLoc), Kind(A), KindKwLoc(ALoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPProcBindClause() : OMPClause(OMPC_proc_bind, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Returns kind of the clause. + /// Returns kind of the clause. OpenMPProcBindClauseKind getProcBindKind() const { return Kind; } - /// \brief Returns location of clause kind. + /// Returns location of clause kind. SourceLocation getProcBindKindKwLoc() const { return KindKwLoc; } child_range children() { @@ -734,7 +734,7 @@ public: } }; -/// \brief This represents 'schedule' clause in the '#pragma omp ...' directive. +/// This represents 'schedule' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp for schedule(static, 3) @@ -744,58 +744,58 @@ public: class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief A kind of the 'schedule' clause. + /// A kind of the 'schedule' clause. OpenMPScheduleClauseKind Kind = OMPC_SCHEDULE_unknown; - /// \brief Modifiers for 'schedule' clause. + /// Modifiers for 'schedule' clause. enum {FIRST, SECOND, NUM_MODIFIERS}; OpenMPScheduleClauseModifier Modifiers[NUM_MODIFIERS]; - /// \brief Locations of modifiers. + /// Locations of modifiers. SourceLocation ModifiersLoc[NUM_MODIFIERS]; - /// \brief Start location of the schedule ind in source code. + /// Start location of the schedule ind in source code. SourceLocation KindLoc; - /// \brief Location of ',' (if any). + /// Location of ',' (if any). SourceLocation CommaLoc; - /// \brief Chunk size. + /// Chunk size. Expr *ChunkSize = nullptr; - /// \brief Set schedule kind. + /// Set schedule kind. /// /// \param K Schedule kind. void setScheduleKind(OpenMPScheduleClauseKind K) { Kind = K; } - /// \brief Set the first schedule modifier. + /// Set the first schedule modifier. /// /// \param M Schedule modifier. void setFirstScheduleModifier(OpenMPScheduleClauseModifier M) { Modifiers[FIRST] = M; } - /// \brief Set the second schedule modifier. + /// Set the second schedule modifier. /// /// \param M Schedule modifier. void setSecondScheduleModifier(OpenMPScheduleClauseModifier M) { Modifiers[SECOND] = M; } - /// \brief Set location of the first schedule modifier. + /// Set location of the first schedule modifier. void setFirstScheduleModifierLoc(SourceLocation Loc) { ModifiersLoc[FIRST] = Loc; } - /// \brief Set location of the second schedule modifier. + /// Set location of the second schedule modifier. void setSecondScheduleModifierLoc(SourceLocation Loc) { ModifiersLoc[SECOND] = Loc; } - /// \brief Set schedule modifier location. + /// Set schedule modifier location. /// /// \param M Schedule modifier location. void setScheduleModifer(OpenMPScheduleClauseModifier M) { @@ -807,28 +807,28 @@ class OMPScheduleClause : public OMPClause, public OMPClauseWithPreInit { } } - /// \brief Sets the location of '('. + /// Sets the location of '('. /// /// \param Loc Location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Set schedule kind start location. + /// Set schedule kind start location. /// /// \param KLoc Schedule kind location. void setScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } - /// \brief Set location of ','. + /// Set location of ','. /// /// \param Loc Location of ','. void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } - /// \brief Set chunk size. + /// Set chunk size. /// /// \param E Chunk size. void setChunkSize(Expr *E) { ChunkSize = E; } public: - /// \brief Build 'schedule' clause with schedule kind \a Kind and chunk size + /// Build 'schedule' clause with schedule kind \a Kind and chunk size /// expression \a ChunkSize. /// /// \param StartLoc Starting location of the clause. @@ -859,7 +859,7 @@ public: ModifiersLoc[SECOND] = M2Loc; } - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPScheduleClause() : OMPClause(OMPC_schedule, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) { @@ -867,42 +867,42 @@ public: Modifiers[SECOND] = OMPC_SCHEDULE_MODIFIER_unknown; } - /// \brief Get kind of the clause. + /// Get kind of the clause. OpenMPScheduleClauseKind getScheduleKind() const { return Kind; } - /// \brief Get the first modifier of the clause. + /// Get the first modifier of the clause. OpenMPScheduleClauseModifier getFirstScheduleModifier() const { return Modifiers[FIRST]; } - /// \brief Get the second modifier of the clause. + /// Get the second modifier of the clause. OpenMPScheduleClauseModifier getSecondScheduleModifier() const { return Modifiers[SECOND]; } - /// \brief Get location of '('. + /// Get location of '('. SourceLocation getLParenLoc() { return LParenLoc; } - /// \brief Get kind location. + /// Get kind location. SourceLocation getScheduleKindLoc() { return KindLoc; } - /// \brief Get the first modifier location. + /// Get the first modifier location. SourceLocation getFirstScheduleModifierLoc() const { return ModifiersLoc[FIRST]; } - /// \brief Get the second modifier location. + /// Get the second modifier location. SourceLocation getSecondScheduleModifierLoc() const { return ModifiersLoc[SECOND]; } - /// \brief Get location of ','. + /// Get location of ','. SourceLocation getCommaLoc() { return CommaLoc; } - /// \brief Get chunk size. + /// Get chunk size. Expr *getChunkSize() { return ChunkSize; } - /// \brief Get chunk size. + /// Get chunk size. const Expr *getChunkSize() const { return ChunkSize; } child_range children() { @@ -915,7 +915,7 @@ public: } }; -/// \brief This represents 'ordered' clause in the '#pragma omp ...' directive. +/// This represents 'ordered' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp for ordered (2) @@ -925,17 +925,17 @@ public: class OMPOrderedClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Number of for-loops. + /// Number of for-loops. Stmt *NumForLoops = nullptr; - /// \brief Set the number of associated for-loops. + /// Set the number of associated for-loops. void setNumForLoops(Expr *Num) { NumForLoops = Num; } public: - /// \brief Build 'ordered' clause. + /// Build 'ordered' clause. /// /// \param Num Expression, possibly associated with this clause. /// \param StartLoc Starting location of the clause. @@ -946,17 +946,17 @@ public: : OMPClause(OMPC_ordered, StartLoc, EndLoc), LParenLoc(LParenLoc), NumForLoops(Num) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPOrderedClause() : OMPClause(OMPC_ordered, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return the number of associated for-loops. + /// Return the number of associated for-loops. Expr *getNumForLoops() const { return cast_or_null<Expr>(NumForLoops); } child_range children() { return child_range(&NumForLoops, &NumForLoops + 1); } @@ -966,7 +966,7 @@ public: } }; -/// \brief This represents 'nowait' clause in the '#pragma omp ...' directive. +/// This represents 'nowait' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp for nowait @@ -974,14 +974,14 @@ public: /// In this example directive '#pragma omp for' has 'nowait' clause. class OMPNowaitClause : public OMPClause { public: - /// \brief Build 'nowait' clause. + /// Build 'nowait' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_nowait, StartLoc, EndLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPNowaitClause() : OMPClause(OMPC_nowait, SourceLocation(), SourceLocation()) {} @@ -994,7 +994,7 @@ public: } }; -/// \brief This represents 'untied' clause in the '#pragma omp ...' directive. +/// This represents 'untied' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp task untied @@ -1002,14 +1002,14 @@ public: /// In this example directive '#pragma omp task' has 'untied' clause. class OMPUntiedClause : public OMPClause { public: - /// \brief Build 'untied' clause. + /// Build 'untied' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_untied, StartLoc, EndLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPUntiedClause() : OMPClause(OMPC_untied, SourceLocation(), SourceLocation()) {} @@ -1022,7 +1022,7 @@ public: } }; -/// \brief This represents 'mergeable' clause in the '#pragma omp ...' +/// This represents 'mergeable' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -1031,14 +1031,14 @@ public: /// In this example directive '#pragma omp task' has 'mergeable' clause. class OMPMergeableClause : public OMPClause { public: - /// \brief Build 'mergeable' clause. + /// Build 'mergeable' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_mergeable, StartLoc, EndLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPMergeableClause() : OMPClause(OMPC_mergeable, SourceLocation(), SourceLocation()) {} @@ -1051,7 +1051,7 @@ public: } }; -/// \brief This represents 'read' clause in the '#pragma omp atomic' directive. +/// This represents 'read' clause in the '#pragma omp atomic' directive. /// /// \code /// #pragma omp atomic read @@ -1059,14 +1059,14 @@ public: /// In this example directive '#pragma omp atomic' has 'read' clause. class OMPReadClause : public OMPClause { public: - /// \brief Build 'read' clause. + /// 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. + /// Build an empty clause. OMPReadClause() : OMPClause(OMPC_read, SourceLocation(), SourceLocation()) {} child_range children() { @@ -1078,7 +1078,7 @@ public: } }; -/// \brief This represents 'write' clause in the '#pragma omp atomic' directive. +/// This represents 'write' clause in the '#pragma omp atomic' directive. /// /// \code /// #pragma omp atomic write @@ -1086,14 +1086,14 @@ public: /// In this example directive '#pragma omp atomic' has 'write' clause. class OMPWriteClause : public OMPClause { public: - /// \brief Build 'write' clause. + /// 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. + /// Build an empty clause. OMPWriteClause() : OMPClause(OMPC_write, SourceLocation(), SourceLocation()) {} @@ -1106,7 +1106,7 @@ public: } }; -/// \brief This represents 'update' clause in the '#pragma omp atomic' +/// This represents 'update' clause in the '#pragma omp atomic' /// directive. /// /// \code @@ -1115,14 +1115,14 @@ public: /// In this example directive '#pragma omp atomic' has 'update' clause. class OMPUpdateClause : public OMPClause { public: - /// \brief Build 'update' clause. + /// 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. + /// Build an empty clause. OMPUpdateClause() : OMPClause(OMPC_update, SourceLocation(), SourceLocation()) {} @@ -1135,7 +1135,7 @@ public: } }; -/// \brief This represents 'capture' clause in the '#pragma omp atomic' +/// This represents 'capture' clause in the '#pragma omp atomic' /// directive. /// /// \code @@ -1144,14 +1144,14 @@ public: /// In this example directive '#pragma omp atomic' has 'capture' clause. class OMPCaptureClause : public OMPClause { public: - /// \brief Build 'capture' clause. + /// 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. + /// Build an empty clause. OMPCaptureClause() : OMPClause(OMPC_capture, SourceLocation(), SourceLocation()) {} @@ -1164,7 +1164,7 @@ public: } }; -/// \brief This represents 'seq_cst' clause in the '#pragma omp atomic' +/// This represents 'seq_cst' clause in the '#pragma omp atomic' /// directive. /// /// \code @@ -1173,14 +1173,14 @@ public: /// In this example directive '#pragma omp atomic' has 'seq_cst' clause. class OMPSeqCstClause : public OMPClause { public: - /// \brief Build 'seq_cst' clause. + /// 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. + /// Build an empty clause. OMPSeqCstClause() : OMPClause(OMPC_seq_cst, SourceLocation(), SourceLocation()) {} @@ -1193,7 +1193,7 @@ public: } }; -/// \brief This represents clause 'private' in the '#pragma omp ...' directives. +/// This represents clause 'private' in the '#pragma omp ...' directives. /// /// \code /// #pragma omp parallel private(a,b) @@ -1207,7 +1207,7 @@ class OMPPrivateClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -1218,7 +1218,7 @@ class OMPPrivateClause final : OMPVarListClause<OMPPrivateClause>(OMPC_private, StartLoc, LParenLoc, EndLoc, N) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPPrivateClause(unsigned N) @@ -1226,12 +1226,12 @@ class OMPPrivateClause final SourceLocation(), SourceLocation(), N) {} - /// \brief Sets the list of references to private copies with initializers for + /// 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 + /// Gets the list of references to private copies with initializers for /// new private variables. MutableArrayRef<Expr *> getPrivateCopies() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); @@ -1241,7 +1241,7 @@ class OMPPrivateClause final } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -1254,7 +1254,7 @@ public: SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL); - /// \brief Creates an empty clause with the place for \a N variables. + /// Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -1286,7 +1286,7 @@ public: } }; -/// \brief This represents clause 'firstprivate' in the '#pragma omp ...' +/// This represents clause 'firstprivate' in the '#pragma omp ...' /// directives. /// /// \code @@ -1302,7 +1302,7 @@ class OMPFirstprivateClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -1314,7 +1314,7 @@ class OMPFirstprivateClause final LParenLoc, EndLoc, N), OMPClauseWithPreInit(this) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPFirstprivateClause(unsigned N) @@ -1323,12 +1323,12 @@ class OMPFirstprivateClause final SourceLocation(), N), OMPClauseWithPreInit(this) {} - /// \brief Sets the list of references to private copies with initializers for + /// 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 + /// Gets the list of references to private copies with initializers for /// new private variables. MutableArrayRef<Expr *> getPrivateCopies() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); @@ -1337,12 +1337,12 @@ class OMPFirstprivateClause final return llvm::makeArrayRef(varlist_end(), varlist_size()); } - /// \brief Sets the list of references to initializer variables for new + /// 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 + /// Gets the list of references to initializer variables for new /// private variables. MutableArrayRef<Expr *> getInits() { return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); @@ -1352,7 +1352,7 @@ class OMPFirstprivateClause final } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -1370,7 +1370,7 @@ public: SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> PrivateVL, ArrayRef<Expr *> InitVL, Stmt *PreInit); - /// \brief Creates an empty clause with the place for \a N variables. + /// Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -1413,7 +1413,7 @@ public: } }; -/// \brief This represents clause 'lastprivate' in the '#pragma omp ...' +/// This represents clause 'lastprivate' in the '#pragma omp ...' /// directives. /// /// \code @@ -1445,7 +1445,7 @@ class OMPLastprivateClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -1457,7 +1457,7 @@ class OMPLastprivateClause final LParenLoc, EndLoc, N), OMPClauseWithPostUpdate(this) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPLastprivateClause(unsigned N) @@ -1466,7 +1466,7 @@ class OMPLastprivateClause final SourceLocation(), N), OMPClauseWithPostUpdate(this) {} - /// \brief Get the list of helper expressions for initialization of private + /// Get the list of helper expressions for initialization of private /// copies for lastprivate variables. MutableArrayRef<Expr *> getPrivateCopies() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); @@ -1475,13 +1475,13 @@ class OMPLastprivateClause final return llvm::makeArrayRef(varlist_end(), varlist_size()); } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent private variables (for arrays, single /// array element) in the final assignment statement performed by the /// lastprivate clause. void setSourceExprs(ArrayRef<Expr *> SrcExprs); - /// \brief Get the list of helper source expressions. + /// Get the list of helper source expressions. MutableArrayRef<Expr *> getSourceExprs() { return MutableArrayRef<Expr *>(getPrivateCopies().end(), varlist_size()); } @@ -1489,13 +1489,13 @@ class OMPLastprivateClause final return llvm::makeArrayRef(getPrivateCopies().end(), varlist_size()); } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent original variables (for arrays, single /// array element) in the final assignment statement performed by the /// lastprivate clause. void setDestinationExprs(ArrayRef<Expr *> DstExprs); - /// \brief Get the list of helper destination expressions. + /// Get the list of helper destination expressions. MutableArrayRef<Expr *> getDestinationExprs() { return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); } @@ -1503,12 +1503,12 @@ class OMPLastprivateClause final return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); } - /// \brief Set list of helper assignment expressions, required for proper + /// Set list of helper assignment expressions, required for proper /// codegen of the clause. These expressions are assignment expressions that /// assign private copy of the variable to original variable. void setAssignmentOps(ArrayRef<Expr *> AssignmentOps); - /// \brief Get the list of helper assignment expressions. + /// Get the list of helper assignment expressions. MutableArrayRef<Expr *> getAssignmentOps() { return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); } @@ -1517,7 +1517,7 @@ class OMPLastprivateClause final } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -1547,7 +1547,7 @@ public: ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps, Stmt *PreInit, Expr *PostUpdate); - /// \brief Creates an empty clause with the place for \a N variables. + /// Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -1559,7 +1559,7 @@ public: using helper_expr_const_range = llvm::iterator_range<helper_expr_const_iterator>; - /// \brief Set list of helper expressions, required for generation of private + /// Set list of helper expressions, required for generation of private /// copies of original lastprivate variables. void setPrivateCopies(ArrayRef<Expr *> PrivateCopies); @@ -1612,7 +1612,7 @@ public: } }; -/// \brief This represents clause 'shared' in the '#pragma omp ...' directives. +/// This represents clause 'shared' in the '#pragma omp ...' directives. /// /// \code /// #pragma omp parallel shared(a,b) @@ -1625,7 +1625,7 @@ class OMPSharedClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -1636,7 +1636,7 @@ class OMPSharedClause final : OMPVarListClause<OMPSharedClause>(OMPC_shared, StartLoc, LParenLoc, EndLoc, N) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPSharedClause(unsigned N) @@ -1645,7 +1645,7 @@ class OMPSharedClause final N) {} public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -1656,7 +1656,7 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. + /// Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -1672,7 +1672,7 @@ public: } }; -/// \brief This represents clause 'reduction' in the '#pragma omp ...' +/// This represents clause 'reduction' in the '#pragma omp ...' /// directives. /// /// \code @@ -1688,16 +1688,16 @@ class OMPReductionClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Location of ':'. + /// Location of ':'. SourceLocation ColonLoc; - /// \brief Nested name specifier for C++. + /// Nested name specifier for C++. NestedNameSpecifierLoc QualifierLoc; - /// \brief Name of custom operator. + /// Name of custom operator. DeclarationNameInfo NameInfo; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -1715,7 +1715,7 @@ class OMPReductionClause final OMPClauseWithPostUpdate(this), ColonLoc(ColonLoc), QualifierLoc(QualifierLoc), NameInfo(NameInfo) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPReductionClause(unsigned N) @@ -1724,21 +1724,21 @@ class OMPReductionClause final N), OMPClauseWithPostUpdate(this) {} - /// \brief Sets location of ':' symbol in clause. + /// Sets location of ':' symbol in clause. void setColonLoc(SourceLocation CL) { ColonLoc = CL; } - /// \brief Sets the name info for specified reduction identifier. + /// Sets the name info for specified reduction identifier. void setNameInfo(DeclarationNameInfo DNI) { NameInfo = DNI; } - /// \brief Sets the nested name specifier. + /// Sets the nested name specifier. void setQualifierLoc(NestedNameSpecifierLoc NSL) { QualifierLoc = NSL; } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent private copy of the reduction /// variable. void setPrivates(ArrayRef<Expr *> Privates); - /// \brief Get the list of helper privates. + /// Get the list of helper privates. MutableArrayRef<Expr *> getPrivates() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } @@ -1746,12 +1746,12 @@ class OMPReductionClause final return llvm::makeArrayRef(varlist_end(), varlist_size()); } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent LHS expression in the final /// reduction expression performed by the reduction clause. void setLHSExprs(ArrayRef<Expr *> LHSExprs); - /// \brief Get the list of helper LHS expressions. + /// Get the list of helper LHS expressions. MutableArrayRef<Expr *> getLHSExprs() { return MutableArrayRef<Expr *>(getPrivates().end(), varlist_size()); } @@ -1759,14 +1759,14 @@ class OMPReductionClause final return llvm::makeArrayRef(getPrivates().end(), varlist_size()); } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent RHS expression in the final /// reduction expression performed by the reduction clause. /// Also, variables in these expressions are used for proper initialization of /// reduction copies. void setRHSExprs(ArrayRef<Expr *> RHSExprs); - /// \brief Get the list of helper destination expressions. + /// Get the list of helper destination expressions. MutableArrayRef<Expr *> getRHSExprs() { return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size()); } @@ -1774,13 +1774,13 @@ class OMPReductionClause final return llvm::makeArrayRef(getLHSExprs().end(), varlist_size()); } - /// \brief Set list of helper reduction expressions, required for proper + /// Set list of helper reduction expressions, required for proper /// codegen of the clause. These expressions are binary expressions or /// operator/custom reduction call that calculates new value from source /// helper expressions to destination helper expressions. void setReductionOps(ArrayRef<Expr *> ReductionOps); - /// \brief Get the list of helper reduction expressions. + /// Get the list of helper reduction expressions. MutableArrayRef<Expr *> getReductionOps() { return MutableArrayRef<Expr *>(getRHSExprs().end(), varlist_size()); } @@ -1789,7 +1789,7 @@ class OMPReductionClause final } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -1829,19 +1829,19 @@ public: ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps, Stmt *PreInit, Expr *PostUpdate); - /// \brief Creates an empty clause with the place for \a N variables. + /// Creates an empty clause with the place for \a N variables. /// /// \param C AST context. /// \param N The number of variables. static OMPReductionClause *CreateEmpty(const ASTContext &C, unsigned N); - /// \brief Gets location of ':' symbol in clause. + /// Gets location of ':' symbol in clause. SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Gets the name info for specified reduction identifier. + /// Gets the name info for specified reduction identifier. const DeclarationNameInfo &getNameInfo() const { return NameInfo; } - /// \brief Gets the nested name specifier. + /// Gets the nested name specifier. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } using helper_expr_iterator = MutableArrayRef<Expr *>::iterator; @@ -2357,7 +2357,7 @@ public: } }; -/// \brief This represents clause 'linear' in the '#pragma omp ...' +/// This represents clause 'linear' in the '#pragma omp ...' /// directives. /// /// \code @@ -2373,22 +2373,22 @@ class OMPLinearClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Modifier of 'linear' clause. + /// Modifier of 'linear' clause. OpenMPLinearClauseKind Modifier = OMPC_LINEAR_val; - /// \brief Location of linear modifier if any. + /// Location of linear modifier if any. SourceLocation ModifierLoc; - /// \brief Location of ':'. + /// Location of ':'. SourceLocation ColonLoc; - /// \brief Sets the linear step for clause. + /// Sets the linear step for clause. void setStep(Expr *Step) { *(getFinals().end()) = Step; } - /// \brief Sets the expression to calculate linear step for clause. + /// Sets the expression to calculate linear step for clause. void setCalcStep(Expr *CalcStep) { *(getFinals().end() + 1) = CalcStep; } - /// \brief Build 'linear' clause with given number of variables \a NumVars. + /// Build 'linear' clause with given number of variables \a NumVars. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -2404,7 +2404,7 @@ class OMPLinearClause final OMPClauseWithPostUpdate(this), Modifier(Modifier), ModifierLoc(ModifierLoc), ColonLoc(ColonLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param NumVars Number of variables. explicit OMPLinearClause(unsigned NumVars) @@ -2413,7 +2413,7 @@ class OMPLinearClause final NumVars), OMPClauseWithPostUpdate(this) {} - /// \brief Gets the list of initial values for linear variables. + /// Gets the list of initial values for linear variables. /// /// There are NumVars expressions with initial values allocated after the /// varlist, they are followed by NumVars update expressions (used to update @@ -2439,7 +2439,7 @@ class OMPLinearClause final return llvm::makeArrayRef(getPrivates().end(), varlist_size()); } - /// \brief Sets the list of update expressions for linear variables. + /// Sets the list of update expressions for linear variables. MutableArrayRef<Expr *> getUpdates() { return MutableArrayRef<Expr *>(getInits().end(), varlist_size()); } @@ -2447,7 +2447,7 @@ class OMPLinearClause final return llvm::makeArrayRef(getInits().end(), varlist_size()); } - /// \brief Sets the list of final update expressions for linear variables. + /// Sets the list of final update expressions for linear variables. MutableArrayRef<Expr *> getFinals() { return MutableArrayRef<Expr *>(getUpdates().end(), varlist_size()); } @@ -2455,16 +2455,16 @@ class OMPLinearClause final return llvm::makeArrayRef(getUpdates().end(), varlist_size()); } - /// \brief Sets the list of the copies of original linear variables. + /// Sets the list of the copies of original linear variables. /// \param PL List of expressions. void setPrivates(ArrayRef<Expr *> PL); - /// \brief Sets the list of the initial values for linear variables. + /// Sets the list of the initial values for linear variables. /// \param IL List of expressions. void setInits(ArrayRef<Expr *> IL); public: - /// \brief Creates clause with a list of variables \a VL and a linear step + /// Creates clause with a list of variables \a VL and a linear step /// \a Step. /// /// \param C AST Context. @@ -2490,47 +2490,47 @@ public: ArrayRef<Expr *> PL, ArrayRef<Expr *> IL, Expr *Step, Expr *CalcStep, Stmt *PreInit, Expr *PostUpdate); - /// \brief Creates an empty clause with the place for \a NumVars variables. + /// Creates an empty clause with the place for \a NumVars variables. /// /// \param C AST context. /// \param NumVars Number of variables. static OMPLinearClause *CreateEmpty(const ASTContext &C, unsigned NumVars); - /// \brief Set modifier. + /// Set modifier. void setModifier(OpenMPLinearClauseKind Kind) { Modifier = Kind; } - /// \brief Return modifier. + /// Return modifier. OpenMPLinearClauseKind getModifier() const { return Modifier; } - /// \brief Set modifier location. + /// Set modifier location. void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } - /// \brief Return modifier location. + /// Return modifier location. SourceLocation getModifierLoc() const { return ModifierLoc; } - /// \brief Sets the location of ':'. + /// Sets the location of ':'. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - /// \brief Returns the location of ':'. + /// Returns the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Returns linear step. + /// Returns linear step. Expr *getStep() { return *(getFinals().end()); } - /// \brief Returns linear step. + /// Returns linear step. const Expr *getStep() const { return *(getFinals().end()); } - /// \brief Returns expression to calculate linear step. + /// Returns expression to calculate linear step. Expr *getCalcStep() { return *(getFinals().end() + 1); } - /// \brief Returns expression to calculate linear step. + /// Returns expression to calculate linear step. const Expr *getCalcStep() const { return *(getFinals().end() + 1); } - /// \brief Sets the list of update expressions for linear variables. + /// Sets the list of update expressions for linear variables. /// \param UL List of expressions. void setUpdates(ArrayRef<Expr *> UL); - /// \brief Sets the list of final update expressions for linear variables. + /// Sets the list of final update expressions for linear variables. /// \param FL List of expressions. void setFinals(ArrayRef<Expr *> FL); @@ -2596,7 +2596,7 @@ public: } }; -/// \brief This represents clause 'aligned' in the '#pragma omp ...' +/// This represents clause 'aligned' in the '#pragma omp ...' /// directives. /// /// \code @@ -2611,13 +2611,13 @@ class OMPAlignedClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Location of ':'. + /// Location of ':'. SourceLocation ColonLoc; - /// \brief Sets the alignment for clause. + /// Sets the alignment for clause. void setAlignment(Expr *A) { *varlist_end() = A; } - /// \brief Build 'aligned' clause with given number of variables \a NumVars. + /// Build 'aligned' clause with given number of variables \a NumVars. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -2631,7 +2631,7 @@ class OMPAlignedClause final EndLoc, NumVars), ColonLoc(ColonLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param NumVars Number of variables. explicit OMPAlignedClause(unsigned NumVars) @@ -2640,7 +2640,7 @@ class OMPAlignedClause final NumVars) {} public: - /// \brief Creates clause with a list of variables \a VL and alignment \a A. + /// Creates clause with a list of variables \a VL and alignment \a A. /// /// \param C AST Context. /// \param StartLoc Starting location of the clause. @@ -2655,22 +2655,22 @@ public: SourceLocation EndLoc, ArrayRef<Expr *> VL, Expr *A); - /// \brief Creates an empty clause with the place for \a NumVars variables. + /// Creates an empty clause with the place for \a NumVars variables. /// /// \param C AST context. /// \param NumVars Number of variables. static OMPAlignedClause *CreateEmpty(const ASTContext &C, unsigned NumVars); - /// \brief Sets the location of ':'. + /// Sets the location of ':'. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } - /// \brief Returns the location of ':'. + /// Returns the location of ':'. SourceLocation getColonLoc() const { return ColonLoc; } - /// \brief Returns alignment. + /// Returns alignment. Expr *getAlignment() { return *varlist_end(); } - /// \brief Returns alignment. + /// Returns alignment. const Expr *getAlignment() const { return *varlist_end(); } child_range children() { @@ -2683,7 +2683,7 @@ public: } }; -/// \brief This represents clause 'copyin' in the '#pragma omp ...' directives. +/// This represents clause 'copyin' in the '#pragma omp ...' directives. /// /// \code /// #pragma omp parallel copyin(a,b) @@ -2710,7 +2710,7 @@ class OMPCopyinClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -2721,7 +2721,7 @@ class OMPCopyinClause final : OMPVarListClause<OMPCopyinClause>(OMPC_copyin, StartLoc, LParenLoc, EndLoc, N) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPCopyinClause(unsigned N) @@ -2729,12 +2729,12 @@ class OMPCopyinClause final SourceLocation(), SourceLocation(), N) {} - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent source expression in the final /// assignment statement performed by the copyin clause. void setSourceExprs(ArrayRef<Expr *> SrcExprs); - /// \brief Get the list of helper source expressions. + /// Get the list of helper source expressions. MutableArrayRef<Expr *> getSourceExprs() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } @@ -2742,12 +2742,12 @@ class OMPCopyinClause final return llvm::makeArrayRef(varlist_end(), varlist_size()); } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent destination expression in the final /// assignment statement performed by the copyin clause. void setDestinationExprs(ArrayRef<Expr *> DstExprs); - /// \brief Get the list of helper destination expressions. + /// Get the list of helper destination expressions. MutableArrayRef<Expr *> getDestinationExprs() { return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); } @@ -2755,13 +2755,13 @@ class OMPCopyinClause final return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); } - /// \brief Set list of helper assignment expressions, required for proper + /// Set list of helper assignment expressions, required for proper /// codegen of the clause. These expressions are assignment expressions that /// assign source helper expressions to destination helper expressions /// correspondingly. void setAssignmentOps(ArrayRef<Expr *> AssignmentOps); - /// \brief Get the list of helper assignment expressions. + /// Get the list of helper assignment expressions. MutableArrayRef<Expr *> getAssignmentOps() { return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); } @@ -2770,7 +2770,7 @@ class OMPCopyinClause final } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -2796,7 +2796,7 @@ public: SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); - /// \brief Creates an empty clause with \a N variables. + /// Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -2847,7 +2847,7 @@ public: } }; -/// \brief This represents clause 'copyprivate' in the '#pragma omp ...' +/// This represents clause 'copyprivate' in the '#pragma omp ...' /// directives. /// /// \code @@ -2862,7 +2862,7 @@ class OMPCopyprivateClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -2873,7 +2873,7 @@ class OMPCopyprivateClause final : OMPVarListClause<OMPCopyprivateClause>(OMPC_copyprivate, StartLoc, LParenLoc, EndLoc, N) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPCopyprivateClause(unsigned N) @@ -2881,12 +2881,12 @@ class OMPCopyprivateClause final OMPC_copyprivate, SourceLocation(), SourceLocation(), SourceLocation(), N) {} - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent source expression in the final /// assignment statement performed by the copyprivate clause. void setSourceExprs(ArrayRef<Expr *> SrcExprs); - /// \brief Get the list of helper source expressions. + /// Get the list of helper source expressions. MutableArrayRef<Expr *> getSourceExprs() { return MutableArrayRef<Expr *>(varlist_end(), varlist_size()); } @@ -2894,12 +2894,12 @@ class OMPCopyprivateClause final return llvm::makeArrayRef(varlist_end(), varlist_size()); } - /// \brief Set list of helper expressions, required for proper codegen of the + /// Set list of helper expressions, required for proper codegen of the /// clause. These expressions represent destination expression in the final /// assignment statement performed by the copyprivate clause. void setDestinationExprs(ArrayRef<Expr *> DstExprs); - /// \brief Get the list of helper destination expressions. + /// Get the list of helper destination expressions. MutableArrayRef<Expr *> getDestinationExprs() { return MutableArrayRef<Expr *>(getSourceExprs().end(), varlist_size()); } @@ -2907,13 +2907,13 @@ class OMPCopyprivateClause final return llvm::makeArrayRef(getSourceExprs().end(), varlist_size()); } - /// \brief Set list of helper assignment expressions, required for proper + /// Set list of helper assignment expressions, required for proper /// codegen of the clause. These expressions are assignment expressions that /// assign source helper expressions to destination helper expressions /// correspondingly. void setAssignmentOps(ArrayRef<Expr *> AssignmentOps); - /// \brief Get the list of helper assignment expressions. + /// Get the list of helper assignment expressions. MutableArrayRef<Expr *> getAssignmentOps() { return MutableArrayRef<Expr *>(getDestinationExprs().end(), varlist_size()); } @@ -2922,7 +2922,7 @@ class OMPCopyprivateClause final } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -2947,7 +2947,7 @@ public: SourceLocation EndLoc, ArrayRef<Expr *> VL, ArrayRef<Expr *> SrcExprs, ArrayRef<Expr *> DstExprs, ArrayRef<Expr *> AssignmentOps); - /// \brief Creates an empty clause with \a N variables. + /// Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -2998,7 +2998,7 @@ public: } }; -/// \brief This represents implicit clause 'flush' for the '#pragma omp flush' +/// 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 @@ -3016,7 +3016,7 @@ class OMPFlushClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -3027,7 +3027,7 @@ class OMPFlushClause final : OMPVarListClause<OMPFlushClause>(OMPC_flush, StartLoc, LParenLoc, EndLoc, N) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPFlushClause(unsigned N) @@ -3036,7 +3036,7 @@ class OMPFlushClause final N) {} public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -3047,7 +3047,7 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc, ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. + /// Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. @@ -3063,7 +3063,7 @@ public: } }; -/// \brief This represents implicit clause 'depend' for the '#pragma omp task' +/// This represents implicit clause 'depend' for the '#pragma omp task' /// directive. /// /// \code @@ -3078,16 +3078,16 @@ class OMPDependClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Dependency type (one of in, out, inout). + /// Dependency type (one of in, out, inout). OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; - /// \brief Dependency type location. + /// Dependency type location. SourceLocation DepLoc; - /// \brief Colon location. + /// Colon location. SourceLocation ColonLoc; - /// \brief Build clause with number of variables \a N. + /// Build clause with number of variables \a N. /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -3098,7 +3098,7 @@ class OMPDependClause final : OMPVarListClause<OMPDependClause>(OMPC_depend, StartLoc, LParenLoc, EndLoc, N) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param N Number of variables. explicit OMPDependClause(unsigned N) @@ -3106,17 +3106,17 @@ class OMPDependClause final SourceLocation(), SourceLocation(), N) {} - /// \brief Set dependency kind. + /// Set dependency kind. void setDependencyKind(OpenMPDependClauseKind K) { DepKind = K; } - /// \brief Set dependency kind and its location. + /// Set dependency kind and its location. void setDependencyLoc(SourceLocation Loc) { DepLoc = Loc; } - /// \brief Set colon location. + /// Set colon location. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -3131,19 +3131,19 @@ public: SourceLocation EndLoc, OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VL); - /// \brief Creates an empty clause with \a N variables. + /// Creates an empty clause with \a N variables. /// /// \param C AST context. /// \param N The number of variables. static OMPDependClause *CreateEmpty(const ASTContext &C, unsigned N); - /// \brief Get dependency type. + /// Get dependency type. OpenMPDependClauseKind getDependencyKind() const { return DepKind; } - /// \brief Get dependency type location. + /// Get dependency type location. SourceLocation getDependencyLoc() const { return DepLoc; } - /// \brief Get colon location. + /// Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } /// Set the loop counter value for the depend clauses with 'sink|source' kind @@ -3166,7 +3166,7 @@ public: } }; -/// \brief This represents 'device' clause in the '#pragma omp ...' +/// This represents 'device' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -3177,46 +3177,49 @@ public: class OMPDeviceClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Device number. + /// Device number. Stmt *Device = nullptr; - /// \brief Set the device number. + /// Set the device number. /// /// \param E Device number. void setDevice(Expr *E) { Device = E; } public: - /// \brief Build 'device' clause. + /// Build 'device' clause. /// /// \param E Expression associated with this clause. + /// \param CaptureRegion Innermost OpenMP region where expressions in this + /// clause must be captured. /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. /// \param EndLoc Ending location of the clause. - OMPDeviceClause(Expr *E, Stmt *HelperE, SourceLocation StartLoc, - SourceLocation LParenLoc, SourceLocation EndLoc) + OMPDeviceClause(Expr *E, Stmt *HelperE, OpenMPDirectiveKind CaptureRegion, + SourceLocation StartLoc, SourceLocation LParenLoc, + SourceLocation EndLoc) : OMPClause(OMPC_device, StartLoc, EndLoc), OMPClauseWithPreInit(this), LParenLoc(LParenLoc), Device(E) { - setPreInitStmt(HelperE); + setPreInitStmt(HelperE, CaptureRegion); } - /// \brief Build an empty clause. + /// Build an empty clause. OMPDeviceClause() : OMPClause(OMPC_device, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return device number. + /// Return device number. Expr *getDevice() { return cast<Expr>(Device); } - /// \brief Return device number. + /// Return device number. Expr *getDevice() const { return cast<Expr>(Device); } child_range children() { return child_range(&Device, &Device + 1); } @@ -3226,7 +3229,7 @@ public: } }; -/// \brief This represents 'threads' clause in the '#pragma omp ...' directive. +/// This represents 'threads' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp ordered threads @@ -3234,14 +3237,14 @@ public: /// In this example directive '#pragma omp ordered' has simple 'threads' clause. class OMPThreadsClause : public OMPClause { public: - /// \brief Build 'threads' clause. + /// Build 'threads' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_threads, StartLoc, EndLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPThreadsClause() : OMPClause(OMPC_threads, SourceLocation(), SourceLocation()) {} @@ -3254,7 +3257,7 @@ public: } }; -/// \brief This represents 'simd' clause in the '#pragma omp ...' directive. +/// This represents 'simd' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp ordered simd @@ -3262,14 +3265,14 @@ public: /// In this example directive '#pragma omp ordered' has simple 'simd' clause. class OMPSIMDClause : public OMPClause { public: - /// \brief Build 'simd' clause. + /// Build 'simd' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_simd, StartLoc, EndLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPSIMDClause() : OMPClause(OMPC_simd, SourceLocation(), SourceLocation()) {} child_range children() { @@ -3281,23 +3284,23 @@ public: } }; -/// \brief Struct that defines common infrastructure to handle mappable +/// Struct that defines common infrastructure to handle mappable /// expressions used in OpenMP clauses. class OMPClauseMappableExprCommon { public: - // \brief Class that represents a component of a mappable expression. E.g. - // for an expression S.a, the first component is a declaration reference - // expression associated with 'S' and the second is a member expression - // associated with the field declaration 'a'. If the expression is an array - // subscript it may not have any associated declaration. In that case the - // associated declaration is set to nullptr. + /// Class that represents a component of a mappable expression. E.g. + /// for an expression S.a, the first component is a declaration reference + /// expression associated with 'S' and the second is a member expression + /// associated with the field declaration 'a'. If the expression is an array + /// subscript it may not have any associated declaration. In that case the + /// associated declaration is set to nullptr. class MappableComponent { - // \brief Expression associated with the component. + /// Expression associated with the component. Expr *AssociatedExpression = nullptr; - // \brief Declaration associated with the declaration. If the component does - // not have a declaration (e.g. array subscripts or section), this is set to - // nullptr. + /// Declaration associated with the declaration. If the component does + /// not have a declaration (e.g. array subscripts or section), this is set + /// to nullptr. ValueDecl *AssociatedDeclaration = nullptr; public: @@ -3317,29 +3320,29 @@ public: } }; - // \brief List of components of an expression. This first one is the whole + // List of components of an expression. This first one is the whole // expression and the last one is the base expression. using MappableExprComponentList = SmallVector<MappableComponent, 8>; using MappableExprComponentListRef = ArrayRef<MappableComponent>; - // \brief List of all component lists associated to the same base declaration. + // List of all component lists associated to the same base declaration. // E.g. if both 'S.a' and 'S.b' are a mappable expressions, each will have // their component list but the same base declaration 'S'. using MappableExprComponentLists = SmallVector<MappableExprComponentList, 8>; using MappableExprComponentListsRef = ArrayRef<MappableExprComponentList>; protected: - // \brief Return the total number of elements in a list of component lists. + // Return the total number of elements in a list of component lists. static unsigned getComponentsTotalNumber(MappableExprComponentListsRef ComponentLists); - // \brief Return the total number of elements in a list of declarations. All + // Return the total number of elements in a list of declarations. All // declarations are expected to be canonical. static unsigned - getUniqueDeclarationsTotalNumber(ArrayRef<ValueDecl *> Declarations); + getUniqueDeclarationsTotalNumber(ArrayRef<const ValueDecl *> Declarations); }; -/// \brief This represents clauses with a list of expressions that are mappable. +/// This represents clauses with a list of expressions that are mappable. /// Examples of these clauses are 'map' in /// '#pragma omp target [enter|exit] [data]...' directives, and 'to' and 'from /// in '#pragma omp target update...' directives. @@ -3348,17 +3351,17 @@ class OMPMappableExprListClause : public OMPVarListClause<T>, public OMPClauseMappableExprCommon { friend class OMPClauseReader; - /// \brief Number of unique declarations in this clause. + /// Number of unique declarations in this clause. unsigned NumUniqueDeclarations; - /// \brief Number of component lists in this clause. + /// Number of component lists in this clause. unsigned NumComponentLists; - /// \brief Total number of components in this clause. + /// Total number of components in this clause. unsigned NumComponents; protected: - /// \brief Build a clause for \a NumUniqueDeclarations declarations, \a + /// Build a clause for \a NumUniqueDeclarations declarations, \a /// NumComponentLists total component lists, and \a NumComponents total /// components. /// @@ -3380,7 +3383,7 @@ protected: NumUniqueDeclarations(NumUniqueDeclarations), NumComponentLists(NumComponentLists), NumComponents(NumComponents) {} - /// \brief Get the unique declarations that are in the trailing objects of the + /// Get the unique declarations that are in the trailing objects of the /// class. MutableArrayRef<ValueDecl *> getUniqueDeclsRef() { return MutableArrayRef<ValueDecl *>( @@ -3388,7 +3391,7 @@ protected: NumUniqueDeclarations); } - /// \brief Get the unique declarations that are in the trailing objects of the + /// Get the unique declarations that are in the trailing objects of the /// class. ArrayRef<ValueDecl *> getUniqueDeclsRef() const { return ArrayRef<ValueDecl *>( @@ -3397,7 +3400,7 @@ protected: NumUniqueDeclarations); } - /// \brief Set the unique declarations that are in the trailing objects of the + /// Set the unique declarations that are in the trailing objects of the /// class. void setUniqueDecls(ArrayRef<ValueDecl *> UDs) { assert(UDs.size() == NumUniqueDeclarations && @@ -3405,7 +3408,7 @@ protected: std::copy(UDs.begin(), UDs.end(), getUniqueDeclsRef().begin()); } - /// \brief Get the number of lists per declaration that are in the trailing + /// Get the number of lists per declaration that are in the trailing /// objects of the class. MutableArrayRef<unsigned> getDeclNumListsRef() { return MutableArrayRef<unsigned>( @@ -3413,7 +3416,7 @@ protected: NumUniqueDeclarations); } - /// \brief Get the number of lists per declaration that are in the trailing + /// Get the number of lists per declaration that are in the trailing /// objects of the class. ArrayRef<unsigned> getDeclNumListsRef() const { return ArrayRef<unsigned>( @@ -3421,7 +3424,7 @@ protected: NumUniqueDeclarations); } - /// \brief Set the number of lists per declaration that are in the trailing + /// Set the number of lists per declaration that are in the trailing /// objects of the class. void setDeclNumLists(ArrayRef<unsigned> DNLs) { assert(DNLs.size() == NumUniqueDeclarations && @@ -3429,7 +3432,7 @@ protected: std::copy(DNLs.begin(), DNLs.end(), getDeclNumListsRef().begin()); } - /// \brief Get the cumulative component lists sizes that are in the trailing + /// Get the cumulative component lists sizes that are in the trailing /// objects of the class. They are appended after the number of lists. MutableArrayRef<unsigned> getComponentListSizesRef() { return MutableArrayRef<unsigned>( @@ -3438,7 +3441,7 @@ protected: NumComponentLists); } - /// \brief Get the cumulative component lists sizes that are in the trailing + /// Get the cumulative component lists sizes that are in the trailing /// objects of the class. They are appended after the number of lists. ArrayRef<unsigned> getComponentListSizesRef() const { return ArrayRef<unsigned>( @@ -3447,7 +3450,7 @@ protected: NumComponentLists); } - /// \brief Set the cumulative component lists sizes that are in the trailing + /// Set the cumulative component lists sizes that are in the trailing /// objects of the class. void setComponentListSizes(ArrayRef<unsigned> CLSs) { assert(CLSs.size() == NumComponentLists && @@ -3455,7 +3458,7 @@ protected: std::copy(CLSs.begin(), CLSs.end(), getComponentListSizesRef().begin()); } - /// \brief Get the components that are in the trailing objects of the class. + /// Get the components that are in the trailing objects of the class. MutableArrayRef<MappableComponent> getComponentsRef() { return MutableArrayRef<MappableComponent>( static_cast<T *>(this) @@ -3463,7 +3466,7 @@ protected: NumComponents); } - /// \brief Get the components that are in the trailing objects of the class. + /// Get the components that are in the trailing objects of the class. ArrayRef<MappableComponent> getComponentsRef() const { return ArrayRef<MappableComponent>( static_cast<const T *>(this) @@ -3471,7 +3474,7 @@ protected: NumComponents); } - /// \brief Set the components that are in the trailing objects of the class. + /// Set the components that are in the trailing objects of the class. /// This requires the list sizes so that it can also fill the original /// expressions, which are the first component of each list. void setComponents(ArrayRef<MappableComponent> Components, @@ -3483,7 +3486,7 @@ protected: std::copy(Components.begin(), Components.end(), getComponentsRef().begin()); } - /// \brief Fill the clause information from the list of declarations and + /// Fill the clause information from the list of declarations and /// associated component lists. void setClauseInfo(ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists) { @@ -3560,17 +3563,17 @@ protected: } public: - /// \brief Return the number of unique base declarations in this clause. + /// Return the number of unique base declarations in this clause. unsigned getUniqueDeclarationsNum() const { return NumUniqueDeclarations; } - /// \brief Return the number of lists derived from the clause expressions. + /// Return the number of lists derived from the clause expressions. unsigned getTotalComponentListNum() const { return NumComponentLists; } - /// \brief Return the total number of components in all lists derived from the + /// Return the total number of components in all lists derived from the /// clause. unsigned getTotalComponentsNum() const { return NumComponents; } - /// \brief Iterator that browse the components by lists. It also allows + /// Iterator that browse the components by lists. It also allows /// browsing components of a single declaration. class const_component_lists_iterator : public llvm::iterator_adaptor_base< @@ -3600,7 +3603,7 @@ public: MappableExprComponentListRef::const_iterator End; public: - /// \brief Construct an iterator that scans all lists. + /// Construct an iterator that scans all lists. explicit const_component_lists_iterator( ArrayRef<ValueDecl *> UniqueDecls, ArrayRef<unsigned> DeclsListNum, ArrayRef<unsigned> CumulativeListSizes, @@ -3616,7 +3619,7 @@ public: RemainingLists = *NumListsCur; } - /// \brief Construct an iterator that scan lists for a given declaration \a + /// Construct an iterator that scan lists for a given declaration \a /// Declaration. explicit const_component_lists_iterator( const ValueDecl *Declaration, ArrayRef<ValueDecl *> UniqueDecls, @@ -3706,7 +3709,7 @@ public: using const_component_lists_range = llvm::iterator_range<const_component_lists_iterator>; - /// \brief Iterators for all component lists. + /// Iterators for all component lists. const_component_lists_iterator component_lists_begin() const { return const_component_lists_iterator( getUniqueDeclsRef(), getDeclNumListsRef(), getComponentListSizesRef(), @@ -3722,7 +3725,7 @@ public: return {component_lists_begin(), component_lists_end()}; } - /// \brief Iterators for component lists associated with the provided + /// Iterators for component lists associated with the provided /// declaration. const_component_lists_iterator decl_component_lists_begin(const ValueDecl *VD) const { @@ -3775,7 +3778,7 @@ public: } }; -/// \brief This represents clause 'map' in the '#pragma omp ...' +/// This represents clause 'map' in the '#pragma omp ...' /// directives. /// /// \code @@ -3804,22 +3807,22 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, return getUniqueDeclarationsNum() + getTotalComponentListNum(); } - /// \brief Map type modifier for the 'map' clause. + /// Map type modifier for the 'map' clause. OpenMPMapClauseKind MapTypeModifier = OMPC_MAP_unknown; - /// \brief Map type for the 'map' clause. + /// Map type for the 'map' clause. OpenMPMapClauseKind MapType = OMPC_MAP_unknown; - /// \brief Is this an implicit map type or not. + /// Is this an implicit map type or not. bool MapTypeIsImplicit = false; - /// \brief Location of the map type. + /// Location of the map type. SourceLocation MapLoc; - /// \brief Colon location. + /// Colon location. SourceLocation ColonLoc; - /// \brief Build a clause for \a NumVars listed expressions, \a + /// Build a clause for \a NumVars listed expressions, \a /// NumUniqueDeclarations declarations, \a NumComponentLists total component /// lists, and \a NumComponents total expression components. /// @@ -3846,7 +3849,7 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, MapTypeModifier(MapTypeModifier), MapType(MapType), MapTypeIsImplicit(MapTypeIsImplicit), MapLoc(MapLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param NumVars Number of expressions listed in this clause. /// \param NumUniqueDeclarations Number of unique base declarations in this @@ -3859,26 +3862,26 @@ class OMPMapClause final : public OMPMappableExprListClause<OMPMapClause>, OMPC_map, SourceLocation(), SourceLocation(), SourceLocation(), NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} - /// \brief Set type modifier for the clause. + /// Set type modifier for the clause. /// /// \param T Type Modifier for the clause. void setMapTypeModifier(OpenMPMapClauseKind T) { MapTypeModifier = T; } - /// \brief Set type for the clause. + /// Set type for the clause. /// /// \param T Type for the clause. void setMapType(OpenMPMapClauseKind T) { MapType = T; } - /// \brief Set type location. + /// Set type location. /// /// \param TLoc Type location. void setMapLoc(SourceLocation TLoc) { MapLoc = TLoc; } - /// \brief Set colon location. + /// Set colon location. void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } public: - /// \brief Creates clause with a list of variables \a VL. + /// Creates clause with a list of variables \a VL. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -3899,7 +3902,7 @@ public: OpenMPMapClauseKind Type, bool TypeIsImplicit, SourceLocation TypeLoc); - /// \brief Creates an empty clause with the place for for \a NumVars original + /// Creates an empty clause with the place for \a NumVars original /// expressions, \a NumUniqueDeclarations declarations, \NumComponentLists /// lists, and \a NumComponents expression components. /// @@ -3915,25 +3918,25 @@ public: unsigned NumComponentLists, unsigned NumComponents); - /// \brief Fetches mapping kind for the clause. + /// Fetches mapping kind for the clause. OpenMPMapClauseKind getMapType() const LLVM_READONLY { return MapType; } - /// \brief Is this an implicit map type? + /// Is this an implicit map type? /// We have to capture 'IsMapTypeImplicit' from the parser for more /// informative error messages. It helps distinguish map(r) from /// map(tofrom: r), which is important to print more helpful error /// messages for some target directives. bool isImplicitMapType() const LLVM_READONLY { return MapTypeIsImplicit; } - /// \brief Fetches the map type modifier for the clause. + /// Fetches the map type modifier for the clause. OpenMPMapClauseKind getMapTypeModifier() const LLVM_READONLY { return MapTypeModifier; } - /// \brief Fetches location of clause mapping kind. + /// Fetches location of clause mapping kind. SourceLocation getMapLoc() const LLVM_READONLY { return MapLoc; } - /// \brief Get colon location. + /// Get colon location. SourceLocation getColonLoc() const { return ColonLoc; } child_range children() { @@ -3947,7 +3950,7 @@ public: } }; -/// \brief This represents 'num_teams' clause in the '#pragma omp ...' +/// This represents 'num_teams' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -3958,19 +3961,19 @@ public: class OMPNumTeamsClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief NumTeams number. + /// NumTeams number. Stmt *NumTeams = nullptr; - /// \brief Set the NumTeams number. + /// Set the NumTeams number. /// /// \param E NumTeams number. void setNumTeams(Expr *E) { NumTeams = E; } public: - /// \brief Build 'num_teams' clause. + /// Build 'num_teams' clause. /// /// \param E Expression associated with this clause. /// \param HelperE Helper Expression associated with this clause. @@ -3987,21 +3990,21 @@ public: setPreInitStmt(HelperE, CaptureRegion); } - /// \brief Build an empty clause. + /// Build an empty clause. OMPNumTeamsClause() : OMPClause(OMPC_num_teams, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return NumTeams number. + /// Return NumTeams number. Expr *getNumTeams() { return cast<Expr>(NumTeams); } - /// \brief Return NumTeams number. + /// Return NumTeams number. Expr *getNumTeams() const { return cast<Expr>(NumTeams); } child_range children() { return child_range(&NumTeams, &NumTeams + 1); } @@ -4011,7 +4014,7 @@ public: } }; -/// \brief This represents 'thread_limit' clause in the '#pragma omp ...' +/// This represents 'thread_limit' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -4022,19 +4025,19 @@ public: class OMPThreadLimitClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief ThreadLimit number. + /// ThreadLimit number. Stmt *ThreadLimit = nullptr; - /// \brief Set the ThreadLimit number. + /// Set the ThreadLimit number. /// /// \param E ThreadLimit number. void setThreadLimit(Expr *E) { ThreadLimit = E; } public: - /// \brief Build 'thread_limit' clause. + /// Build 'thread_limit' clause. /// /// \param E Expression associated with this clause. /// \param HelperE Helper Expression associated with this clause. @@ -4052,21 +4055,21 @@ public: setPreInitStmt(HelperE, CaptureRegion); } - /// \brief Build an empty clause. + /// Build an empty clause. OMPThreadLimitClause() : OMPClause(OMPC_thread_limit, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return ThreadLimit number. + /// Return ThreadLimit number. Expr *getThreadLimit() { return cast<Expr>(ThreadLimit); } - /// \brief Return ThreadLimit number. + /// Return ThreadLimit number. Expr *getThreadLimit() const { return cast<Expr>(ThreadLimit); } child_range children() { return child_range(&ThreadLimit, &ThreadLimit + 1); } @@ -4076,7 +4079,7 @@ public: } }; -/// \brief This represents 'priority' clause in the '#pragma omp ...' +/// This represents 'priority' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -4087,19 +4090,19 @@ public: class OMPPriorityClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Priority number. + /// Priority number. Stmt *Priority = nullptr; - /// \brief Set the Priority number. + /// Set the Priority number. /// /// \param E Priority number. void setPriority(Expr *E) { Priority = E; } public: - /// \brief Build 'priority' clause. + /// Build 'priority' clause. /// /// \param E Expression associated with this clause. /// \param StartLoc Starting location of the clause. @@ -4110,20 +4113,20 @@ public: : OMPClause(OMPC_priority, StartLoc, EndLoc), LParenLoc(LParenLoc), Priority(E) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPPriorityClause() : OMPClause(OMPC_priority, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return Priority number. + /// Return Priority number. Expr *getPriority() { return cast<Expr>(Priority); } - /// \brief Return Priority number. + /// Return Priority number. Expr *getPriority() const { return cast<Expr>(Priority); } child_range children() { return child_range(&Priority, &Priority + 1); } @@ -4133,7 +4136,7 @@ public: } }; -/// \brief This represents 'grainsize' clause in the '#pragma omp ...' +/// This represents 'grainsize' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -4144,17 +4147,17 @@ public: class OMPGrainsizeClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Safe iteration space distance. + /// Safe iteration space distance. Stmt *Grainsize = nullptr; - /// \brief Set safelen. + /// Set safelen. void setGrainsize(Expr *Size) { Grainsize = Size; } public: - /// \brief Build 'grainsize' clause. + /// Build 'grainsize' clause. /// /// \param Size Expression associated with this clause. /// \param StartLoc Starting location of the clause. @@ -4164,17 +4167,17 @@ public: : OMPClause(OMPC_grainsize, StartLoc, EndLoc), LParenLoc(LParenLoc), Grainsize(Size) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPGrainsizeClause() : OMPClause(OMPC_grainsize, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return safe iteration space distance. + /// Return safe iteration space distance. Expr *getGrainsize() const { return cast_or_null<Expr>(Grainsize); } child_range children() { return child_range(&Grainsize, &Grainsize + 1); } @@ -4184,7 +4187,7 @@ public: } }; -/// \brief This represents 'nogroup' clause in the '#pragma omp ...' directive. +/// This represents 'nogroup' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp taskloop nogroup @@ -4192,14 +4195,14 @@ public: /// In this example directive '#pragma omp taskloop' has 'nogroup' clause. class OMPNogroupClause : public OMPClause { public: - /// \brief Build 'nogroup' clause. + /// Build 'nogroup' clause. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. OMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc) : OMPClause(OMPC_nogroup, StartLoc, EndLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPNogroupClause() : OMPClause(OMPC_nogroup, SourceLocation(), SourceLocation()) {} @@ -4212,7 +4215,7 @@ public: } }; -/// \brief This represents 'num_tasks' clause in the '#pragma omp ...' +/// This represents 'num_tasks' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -4223,17 +4226,17 @@ public: class OMPNumTasksClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Safe iteration space distance. + /// Safe iteration space distance. Stmt *NumTasks = nullptr; - /// \brief Set safelen. + /// Set safelen. void setNumTasks(Expr *Size) { NumTasks = Size; } public: - /// \brief Build 'num_tasks' clause. + /// Build 'num_tasks' clause. /// /// \param Size Expression associated with this clause. /// \param StartLoc Starting location of the clause. @@ -4243,17 +4246,17 @@ public: : OMPClause(OMPC_num_tasks, StartLoc, EndLoc), LParenLoc(LParenLoc), NumTasks(Size) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPNumTasksClause() : OMPClause(OMPC_num_tasks, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Return safe iteration space distance. + /// Return safe iteration space distance. Expr *getNumTasks() const { return cast_or_null<Expr>(NumTasks); } child_range children() { return child_range(&NumTasks, &NumTasks + 1); } @@ -4263,7 +4266,7 @@ public: } }; -/// \brief This represents 'hint' clause in the '#pragma omp ...' directive. +/// This represents 'hint' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp critical (name) hint(6) @@ -4273,17 +4276,17 @@ public: class OMPHintClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Hint expression of the 'hint' clause. + /// Hint expression of the 'hint' clause. Stmt *Hint = nullptr; - /// \brief Set hint expression. + /// Set hint expression. void setHint(Expr *H) { Hint = H; } public: - /// \brief Build 'hint' clause with expression \a Hint. + /// Build 'hint' clause with expression \a Hint. /// /// \param Hint Hint expression. /// \param StartLoc Starting location of the clause. @@ -4294,16 +4297,16 @@ public: : OMPClause(OMPC_hint, StartLoc, EndLoc), LParenLoc(LParenLoc), Hint(Hint) {} - /// \brief Build an empty clause. + /// Build an empty clause. OMPHintClause() : OMPClause(OMPC_hint, SourceLocation(), SourceLocation()) {} - /// \brief Sets the location of '('. + /// Sets the location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Returns the location of '('. + /// Returns the location of '('. SourceLocation getLParenLoc() const { return LParenLoc; } - /// \brief Returns number of threads. + /// Returns number of threads. Expr *getHint() const { return cast_or_null<Expr>(Hint); } child_range children() { return child_range(&Hint, &Hint + 1); } @@ -4313,7 +4316,7 @@ public: } }; -/// \brief This represents 'dist_schedule' clause in the '#pragma omp ...' +/// This represents 'dist_schedule' clause in the '#pragma omp ...' /// directive. /// /// \code @@ -4324,48 +4327,48 @@ public: class OMPDistScheduleClause : public OMPClause, public OMPClauseWithPreInit { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief A kind of the 'schedule' clause. + /// A kind of the 'schedule' clause. OpenMPDistScheduleClauseKind Kind = OMPC_DIST_SCHEDULE_unknown; - /// \brief Start location of the schedule kind in source code. + /// Start location of the schedule kind in source code. SourceLocation KindLoc; - /// \brief Location of ',' (if any). + /// Location of ',' (if any). SourceLocation CommaLoc; - /// \brief Chunk size. + /// Chunk size. Expr *ChunkSize = nullptr; - /// \brief Set schedule kind. + /// Set schedule kind. /// /// \param K Schedule kind. void setDistScheduleKind(OpenMPDistScheduleClauseKind K) { Kind = K; } - /// \brief Sets the location of '('. + /// Sets the location of '('. /// /// \param Loc Location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Set schedule kind start location. + /// Set schedule kind start location. /// /// \param KLoc Schedule kind location. void setDistScheduleKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } - /// \brief Set location of ','. + /// Set location of ','. /// /// \param Loc Location of ','. void setCommaLoc(SourceLocation Loc) { CommaLoc = Loc; } - /// \brief Set chunk size. + /// Set chunk size. /// /// \param E Chunk size. void setChunkSize(Expr *E) { ChunkSize = E; } public: - /// \brief Build 'dist_schedule' clause with schedule kind \a Kind and chunk + /// Build 'dist_schedule' clause with schedule kind \a Kind and chunk /// size expression \a ChunkSize. /// /// \param StartLoc Starting location of the clause. @@ -4387,27 +4390,27 @@ public: setPreInitStmt(HelperChunkSize); } - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPDistScheduleClause() : OMPClause(OMPC_dist_schedule, SourceLocation(), SourceLocation()), OMPClauseWithPreInit(this) {} - /// \brief Get kind of the clause. + /// Get kind of the clause. OpenMPDistScheduleClauseKind getDistScheduleKind() const { return Kind; } - /// \brief Get location of '('. + /// Get location of '('. SourceLocation getLParenLoc() { return LParenLoc; } - /// \brief Get kind location. + /// Get kind location. SourceLocation getDistScheduleKindLoc() { return KindLoc; } - /// \brief Get location of ','. + /// Get location of ','. SourceLocation getCommaLoc() { return CommaLoc; } - /// \brief Get chunk size. + /// Get chunk size. Expr *getChunkSize() { return ChunkSize; } - /// \brief Get chunk size. + /// Get chunk size. const Expr *getChunkSize() const { return ChunkSize; } child_range children() { @@ -4420,7 +4423,7 @@ public: } }; -/// \brief This represents 'defaultmap' clause in the '#pragma omp ...' directive. +/// This represents 'defaultmap' clause in the '#pragma omp ...' directive. /// /// \code /// #pragma omp target defaultmap(tofrom: scalar) @@ -4430,50 +4433,50 @@ public: class OMPDefaultmapClause : public OMPClause { friend class OMPClauseReader; - /// \brief Location of '('. + /// Location of '('. SourceLocation LParenLoc; - /// \brief Modifiers for 'defaultmap' clause. + /// Modifiers for 'defaultmap' clause. OpenMPDefaultmapClauseModifier Modifier = OMPC_DEFAULTMAP_MODIFIER_unknown; - /// \brief Locations of modifiers. + /// Locations of modifiers. SourceLocation ModifierLoc; - /// \brief A kind of the 'defaultmap' clause. + /// A kind of the 'defaultmap' clause. OpenMPDefaultmapClauseKind Kind = OMPC_DEFAULTMAP_unknown; - /// \brief Start location of the defaultmap kind in source code. + /// Start location of the defaultmap kind in source code. SourceLocation KindLoc; - /// \brief Set defaultmap kind. + /// Set defaultmap kind. /// /// \param K Defaultmap kind. void setDefaultmapKind(OpenMPDefaultmapClauseKind K) { Kind = K; } - /// \brief Set the defaultmap modifier. + /// Set the defaultmap modifier. /// /// \param M Defaultmap modifier. void setDefaultmapModifier(OpenMPDefaultmapClauseModifier M) { Modifier = M; } - /// \brief Set location of the defaultmap modifier. + /// Set location of the defaultmap modifier. void setDefaultmapModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; } - /// \brief Sets the location of '('. + /// Sets the location of '('. /// /// \param Loc Location of '('. void setLParenLoc(SourceLocation Loc) { LParenLoc = Loc; } - /// \brief Set defaultmap kind start location. + /// Set defaultmap kind start location. /// /// \param KLoc Defaultmap kind location. void setDefaultmapKindLoc(SourceLocation KLoc) { KindLoc = KLoc; } public: - /// \brief Build 'defaultmap' clause with defaultmap kind \a Kind + /// Build 'defaultmap' clause with defaultmap kind \a Kind /// /// \param StartLoc Starting location of the clause. /// \param LParenLoc Location of '('. @@ -4489,25 +4492,25 @@ public: : OMPClause(OMPC_defaultmap, StartLoc, EndLoc), LParenLoc(LParenLoc), Modifier(M), ModifierLoc(MLoc), Kind(Kind), KindLoc(KLoc) {} - /// \brief Build an empty clause. + /// Build an empty clause. explicit OMPDefaultmapClause() : OMPClause(OMPC_defaultmap, SourceLocation(), SourceLocation()) {} - /// \brief Get kind of the clause. + /// Get kind of the clause. OpenMPDefaultmapClauseKind getDefaultmapKind() const { return Kind; } - /// \brief Get the modifier of the clause. + /// Get the modifier of the clause. OpenMPDefaultmapClauseModifier getDefaultmapModifier() const { return Modifier; } - /// \brief Get location of '('. + /// Get location of '('. SourceLocation getLParenLoc() { return LParenLoc; } - /// \brief Get kind location. + /// Get kind location. SourceLocation getDefaultmapKindLoc() { return KindLoc; } - /// \brief Get the modifier location. + /// Get the modifier location. SourceLocation getDefaultmapModifierLoc() const { return ModifierLoc; } @@ -4521,7 +4524,7 @@ public: } }; -/// \brief This represents clause 'to' in the '#pragma omp ...' +/// This represents clause 'to' in the '#pragma omp ...' /// directives. /// /// \code @@ -4538,7 +4541,7 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a NumVars. + /// Build clause with number of variables \a NumVars. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. @@ -4555,7 +4558,7 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, NumUniqueDeclarations, NumComponentLists, NumComponents) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param NumVars Number of expressions listed in this clause. /// \param NumUniqueDeclarations Number of unique base declarations in this @@ -4581,7 +4584,7 @@ class OMPToClause final : public OMPMappableExprListClause<OMPToClause>, } public: - /// \brief Creates clause with a list of variables \a Vars. + /// Creates clause with a list of variables \a Vars. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -4595,7 +4598,7 @@ public: ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists); - /// \brief Creates an empty clause with the place for \a NumVars variables. + /// Creates an empty clause with the place for \a NumVars variables. /// /// \param C AST context. /// \param NumVars Number of expressions listed in the clause. @@ -4619,7 +4622,7 @@ public: } }; -/// \brief This represents clause 'from' in the '#pragma omp ...' +/// This represents clause 'from' in the '#pragma omp ...' /// directives. /// /// \code @@ -4637,7 +4640,7 @@ class OMPFromClause final friend OMPVarListClause; friend TrailingObjects; - /// \brief Build clause with number of variables \a NumVars. + /// Build clause with number of variables \a NumVars. /// /// \param StartLoc Starting location of the clause. /// \param EndLoc Ending location of the clause. @@ -4654,7 +4657,7 @@ class OMPFromClause final NumVars, NumUniqueDeclarations, NumComponentLists, NumComponents) {} - /// \brief Build an empty clause. + /// Build an empty clause. /// /// \param NumVars Number of expressions listed in this clause. /// \param NumUniqueDeclarations Number of unique base declarations in this @@ -4680,7 +4683,7 @@ class OMPFromClause final } public: - /// \brief Creates clause with a list of variables \a Vars. + /// Creates clause with a list of variables \a Vars. /// /// \param C AST context. /// \param StartLoc Starting location of the clause. @@ -4694,7 +4697,7 @@ public: ArrayRef<ValueDecl *> Declarations, MappableExprComponentListsRef ComponentLists); - /// \brief Creates an empty clause with the place for \a NumVars variables. + /// Creates an empty clause with the place for \a NumVars variables. /// /// \param C AST context. /// \param NumVars Number of expressions listed in the clause. diff --git a/include/clang/AST/OperationKinds.def b/include/clang/AST/OperationKinds.def index b13cf3b63276f..823e32424f1ee 100644 --- a/include/clang/AST/OperationKinds.def +++ b/include/clang/AST/OperationKinds.def @@ -227,87 +227,87 @@ CAST_OPERATION(BlockPointerToObjCPointerCast) /// to a block pointer. Block-to-block casts are bitcasts. CAST_OPERATION(AnyPointerToBlockPointerCast) -/// \brief Converting between two Objective-C object types, which +/// Converting between two Objective-C object types, which /// can occur when performing reference binding to an Objective-C /// object. CAST_OPERATION(ObjCObjectLValueCast) -/// \brief A conversion of a floating point real to a floating point +/// A conversion of a floating point real to a floating point /// complex of the original type. Injects the value as the real /// component with a zero imaginary component. /// float -> _Complex float CAST_OPERATION(FloatingRealToComplex) -/// \brief Converts a floating point complex to floating point real +/// Converts a floating point complex to floating point real /// of the source's element type. Just discards the imaginary /// component. /// _Complex long double -> long double CAST_OPERATION(FloatingComplexToReal) -/// \brief Converts a floating point complex to bool by comparing +/// Converts a floating point complex to bool by comparing /// against 0+0i. CAST_OPERATION(FloatingComplexToBoolean) -/// \brief Converts between different floating point complex types. +/// Converts between different floating point complex types. /// _Complex float -> _Complex double CAST_OPERATION(FloatingComplexCast) -/// \brief Converts from a floating complex to an integral complex. +/// Converts from a floating complex to an integral complex. /// _Complex float -> _Complex int CAST_OPERATION(FloatingComplexToIntegralComplex) -/// \brief Converts from an integral real to an integral complex +/// Converts from an integral real to an integral complex /// whose element type matches the source. Injects the value as /// the real component with a zero imaginary component. /// long -> _Complex long CAST_OPERATION(IntegralRealToComplex) -/// \brief Converts an integral complex to an integral real of the +/// Converts an integral complex to an integral real of the /// source's element type by discarding the imaginary component. /// _Complex short -> short CAST_OPERATION(IntegralComplexToReal) -/// \brief Converts an integral complex to bool by comparing against +/// Converts an integral complex to bool by comparing against /// 0+0i. CAST_OPERATION(IntegralComplexToBoolean) -/// \brief Converts between different integral complex types. +/// Converts between different integral complex types. /// _Complex char -> _Complex long long /// _Complex unsigned int -> _Complex signed int CAST_OPERATION(IntegralComplexCast) -/// \brief Converts from an integral complex to a floating complex. +/// Converts from an integral complex to a floating complex. /// _Complex unsigned -> _Complex float CAST_OPERATION(IntegralComplexToFloatingComplex) -/// \brief [ARC] Produces a retainable object pointer so that it may +/// [ARC] Produces a retainable object pointer so that it may /// be consumed, e.g. by being passed to a consuming parameter. /// Calls objc_retain. CAST_OPERATION(ARCProduceObject) -/// \brief [ARC] Consumes a retainable object pointer that has just +/// [ARC] Consumes a retainable object pointer that has just /// been produced, e.g. as the return value of a retaining call. /// Enters a cleanup to call objc_release at some indefinite time. CAST_OPERATION(ARCConsumeObject) -/// \brief [ARC] Reclaim a retainable object pointer object that may +/// [ARC] Reclaim a retainable object pointer object that may /// have been produced and autoreleased as part of a function return /// sequence. CAST_OPERATION(ARCReclaimReturnedObject) -/// \brief [ARC] Causes a value of block type to be copied to the +/// [ARC] Causes a value of block type to be copied to the /// heap, if it is not already there. A number of other operations /// in ARC cause blocks to be copied; this is for cases where that /// would not otherwise be guaranteed, such as when casting to a /// non-block pointer type. CAST_OPERATION(ARCExtendBlockObject) -/// \brief Converts from _Atomic(T) to T. +/// Converts from _Atomic(T) to T. CAST_OPERATION(AtomicToNonAtomic) -/// \brief Converts from T to _Atomic(T). +/// Converts from T to _Atomic(T). CAST_OPERATION(NonAtomicToAtomic) -/// \brief Causes a block literal to by copied to the heap and then +/// Causes a block literal to by copied to the heap and then /// autoreleased. /// /// This particular cast kind is used for the conversion from a C++11 diff --git a/include/clang/AST/OperationKinds.h b/include/clang/AST/OperationKinds.h index e3832689d64b8..c7e01fa1834e8 100644 --- a/include/clang/AST/OperationKinds.h +++ b/include/clang/AST/OperationKinds.h @@ -33,15 +33,15 @@ enum UnaryOperatorKind { #include "clang/AST/OperationKinds.def" }; -/// \brief The kind of bridging performed by the Objective-C bridge cast. +/// The kind of bridging performed by the Objective-C bridge cast. enum ObjCBridgeCastKind { - /// \brief Bridging via __bridge, which does nothing but reinterpret + /// Bridging via __bridge, which does nothing but reinterpret /// the bits. OBC_Bridge, - /// \brief Bridging via __bridge_transfer, which transfers ownership of an + /// Bridging via __bridge_transfer, which transfers ownership of an /// Objective-C pointer into ARC. OBC_BridgeTransfer, - /// \brief Bridging via __bridge_retain, which makes an ARC object available + /// Bridging via __bridge_retain, which makes an ARC object available /// as a +1 C pointer. OBC_BridgeRetained }; diff --git a/include/clang/AST/ParentMap.h b/include/clang/AST/ParentMap.h index 8945c413d2685..c1c76ceaaf692 100644 --- a/include/clang/AST/ParentMap.h +++ b/include/clang/AST/ParentMap.h @@ -24,7 +24,7 @@ public: ParentMap(Stmt* ASTRoot); ~ParentMap(); - /// \brief Adds and/or updates the parent/child-relations of the complete + /// Adds and/or updates the parent/child-relations of the complete /// stmt tree of S. All children of S including indirect descendants are /// visited and updated or inserted but not the parents of S. void addStmt(Stmt* S); diff --git a/include/clang/Sema/PrettyDeclStackTrace.h b/include/clang/AST/PrettyDeclStackTrace.h index ca22e640deb49..8eb519eae26da 100644 --- a/include/clang/Sema/PrettyDeclStackTrace.h +++ b/include/clang/AST/PrettyDeclStackTrace.h @@ -13,31 +13,31 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H -#define LLVM_CLANG_SEMA_PRETTYDECLSTACKTRACE_H +#ifndef LLVM_CLANG_AST_PRETTYDECLSTACKTRACE_H +#define LLVM_CLANG_AST_PRETTYDECLSTACKTRACE_H #include "clang/Basic/SourceLocation.h" #include "llvm/Support/PrettyStackTrace.h" namespace clang { +class ASTContext; class Decl; -class Sema; class SourceManager; /// PrettyDeclStackTraceEntry - If a crash occurs in the parser while /// parsing something related to a declaration, include that /// declaration in the stack trace. class PrettyDeclStackTraceEntry : public llvm::PrettyStackTraceEntry { - Sema &S; + ASTContext &Context; Decl *TheDecl; SourceLocation Loc; const char *Message; public: - PrettyDeclStackTraceEntry(Sema &S, Decl *D, SourceLocation Loc, + PrettyDeclStackTraceEntry(ASTContext &Ctx, Decl *D, SourceLocation Loc, const char *Msg) - : S(S), TheDecl(D), Loc(Loc), Message(Msg) {} + : Context(Ctx), TheDecl(D), Loc(Loc), Message(Msg) {} void print(raw_ostream &OS) const override; }; diff --git a/include/clang/AST/PrettyPrinter.h b/include/clang/AST/PrettyPrinter.h index e831b903cbae6..41c804486c358 100644 --- a/include/clang/AST/PrettyPrinter.h +++ b/include/clang/AST/PrettyPrinter.h @@ -36,7 +36,7 @@ public: /// This type is intended to be small and suitable for passing by value. /// It is very frequently copied. struct PrintingPolicy { - /// \brief Create a default printing policy for the specified language. + /// Create a default printing policy for the specified language. PrintingPolicy(const LangOptions &LO) : Indentation(2), SuppressSpecifiers(false), SuppressTagKeyword(LO.CPlusPlus), diff --git a/include/clang/AST/QualTypeNames.h b/include/clang/AST/QualTypeNames.h index 86d805feeed76..422ed9e4c8fc4 100644 --- a/include/clang/AST/QualTypeNames.h +++ b/include/clang/AST/QualTypeNames.h @@ -63,7 +63,7 @@ namespace clang { namespace TypeName { -/// \brief Get the fully qualified name for a type. This includes full +/// Get the fully qualified name for a type. This includes full /// qualification of all template parameters etc. /// /// \param[in] QT - the type for which the fully qualified name will be @@ -72,9 +72,10 @@ namespace TypeName { /// \param[in] WithGlobalNsPrefix - If true, then the global namespace /// specifier "::" will be prepended to the fully qualified name. std::string getFullyQualifiedName(QualType QT, const ASTContext &Ctx, + const PrintingPolicy &Policy, bool WithGlobalNsPrefix = false); -/// \brief Generates a QualType that can be used to name the same type +/// Generates a QualType that can be used to name the same type /// if used at the end of the current translation unit. This ignores /// issues such as type shadowing. /// diff --git a/include/clang/AST/RawCommentList.h b/include/clang/AST/RawCommentList.h index 2e005ddbd027d..8327efc750fd3 100644 --- a/include/clang/AST/RawCommentList.h +++ b/include/clang/AST/RawCommentList.h @@ -41,7 +41,7 @@ public: RawComment() : Kind(RCK_Invalid), IsAlmostTrailingComment(false) { } RawComment(const SourceManager &SourceMgr, SourceRange SR, - bool Merged, bool ParseAllComments); + const CommentOptions &CommentOpts, bool Merged); CommentKind getKind() const LLVM_READONLY { return (CommentKind) Kind; @@ -70,7 +70,6 @@ public: /// \code /**< stuff */ \endcode /// \code /*!< stuff */ \endcode bool isTrailingComment() const LLVM_READONLY { - assert(isDocumentation()); return IsTrailingComment; } @@ -83,8 +82,7 @@ public: /// Returns true if this comment is not a documentation comment. bool isOrdinary() const LLVM_READONLY { - return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)) && - !ParseAllComments; + return ((Kind == RCK_OrdinaryBCPL) || (Kind == RCK_OrdinaryC)); } /// Returns true if this comment any kind of a documentation comment. @@ -92,11 +90,6 @@ public: return !isInvalid() && !isOrdinary(); } - /// Returns whether we are parsing all comments. - bool isParseAllComments() const LLVM_READONLY { - return ParseAllComments; - } - /// Returns raw comment text with comment markers. StringRef getRawText(const SourceManager &SourceMgr) const { if (RawTextValid) @@ -118,6 +111,30 @@ public: return extractBriefText(Context); } + /// Returns sanitized comment text, suitable for presentation in editor UIs. + /// E.g. will transform: + /// // This is a long multiline comment. + /// // Parts of it might be indented. + /// /* The comments styles might be mixed. */ + /// into + /// "This is a long multiline comment.\n" + /// " Parts of it might be indented.\n" + /// "The comments styles might be mixed." + /// Also removes leading indentation and sanitizes some common cases: + /// /* This is a first line. + /// * This is a second line. It is indented. + /// * This is a third line. */ + /// and + /// /* This is a first line. + /// This is a second line. It is indented. + /// This is a third line. */ + /// will both turn into: + /// "This is a first line.\n" + /// " This is a second line. It is indented.\n" + /// "This is a third line." + std::string getFormattedText(const SourceManager &SourceMgr, + DiagnosticsEngine &Diags) const; + /// Parse the comment, assuming it is attached to decl \c D. comments::FullComment *parse(const ASTContext &Context, const Preprocessor *PP, const Decl *D) const; @@ -139,18 +156,12 @@ private: bool IsTrailingComment : 1; bool IsAlmostTrailingComment : 1; - /// When true, ordinary comments starting with "//" and "/*" will be - /// considered as documentation comments. - bool ParseAllComments : 1; - - /// \brief Constructor for AST deserialization. + /// Constructor for AST deserialization. RawComment(SourceRange SR, CommentKind K, bool IsTrailingComment, - bool IsAlmostTrailingComment, - bool ParseAllComments) : + bool IsAlmostTrailingComment) : Range(SR), RawTextValid(false), BriefTextValid(false), Kind(K), IsAttached(false), IsTrailingComment(IsTrailingComment), - IsAlmostTrailingComment(IsAlmostTrailingComment), - ParseAllComments(ParseAllComments) + IsAlmostTrailingComment(IsAlmostTrailingComment) { } StringRef getRawTextSlow(const SourceManager &SourceMgr) const; @@ -160,7 +171,7 @@ private: friend class ASTReader; }; -/// \brief Compare comments' source locations. +/// Compare comments' source locations. template<> class BeforeThanCompare<RawComment> { const SourceManager &SM; @@ -177,13 +188,14 @@ public: } }; -/// \brief This class represents all comments included in the translation unit, +/// This class represents all comments included in the translation unit, /// sorted in order of appearance in the translation unit. class RawCommentList { public: RawCommentList(SourceManager &SourceMgr) : SourceMgr(SourceMgr) {} - void addComment(const RawComment &RC, llvm::BumpPtrAllocator &Allocator); + void addComment(const RawComment &RC, const CommentOptions &CommentOpts, + llvm::BumpPtrAllocator &Allocator); ArrayRef<RawComment *> getComments() const { return Comments; diff --git a/include/clang/AST/RecordLayout.h b/include/clang/AST/RecordLayout.h index 696d44efa0d9d..dc60ef892b073 100644 --- a/include/clang/AST/RecordLayout.h +++ b/include/clang/AST/RecordLayout.h @@ -111,7 +111,7 @@ private: /// Only used for MS-ABI. bool EndsWithZeroSizedObject : 1; - /// \brief True if this class is zero sized or first base is zero sized or + /// True if this class is zero sized or first base is zero sized or /// has this property. Only used for MS-ABI. bool LeadsWithZeroSizedBase : 1; diff --git a/include/clang/AST/RecursiveASTVisitor.h b/include/clang/AST/RecursiveASTVisitor.h index ba76ea0a0df55..0d2b670507c12 100644 --- a/include/clang/AST/RecursiveASTVisitor.h +++ b/include/clang/AST/RecursiveASTVisitor.h @@ -83,7 +83,7 @@ namespace clang { return false; \ } while (false) -/// \brief A class that does preorder or postorder +/// A class that does preorder or postorder /// depth-first traversal on the entire Clang AST and visits each node. /// /// This class performs three distinct tasks: @@ -146,7 +146,7 @@ namespace clang { /// from which they were produced. /// /// By default, this visitor preorder traverses the AST. If postorder traversal -/// is needed, the \c shouldTraversePostOrder method needs to be overriden +/// is needed, the \c shouldTraversePostOrder method needs to be overridden /// to return \c true. template <typename Derived> class RecursiveASTVisitor { public: @@ -158,25 +158,25 @@ public: typedef SmallVectorImpl<llvm::PointerIntPair<Stmt *, 1, bool>> DataRecursionQueue; - /// \brief Return a reference to the derived class. + /// Return a reference to the derived class. Derived &getDerived() { return *static_cast<Derived *>(this); } - /// \brief Return whether this visitor should recurse into + /// Return whether this visitor should recurse into /// template instantiations. bool shouldVisitTemplateInstantiations() const { return false; } - /// \brief Return whether this visitor should recurse into the types of + /// Return whether this visitor should recurse into the types of /// TypeLocs. bool shouldWalkTypesOfTypeLocs() const { return true; } - /// \brief Return whether this visitor should recurse into implicit + /// Return whether this visitor should recurse into implicit /// code, e.g., implicit constructors and destructors. bool shouldVisitImplicitCode() const { return false; } - /// \brief Return whether this visitor should traverse post-order. + /// Return whether this visitor should traverse post-order. bool shouldTraversePostOrder() const { return false; } - /// \brief Recursively visit a statement or expression, by + /// Recursively visit a statement or expression, by /// dispatching to Traverse*() based on the argument's dynamic type. /// /// \returns false if the visitation was terminated early, true @@ -195,70 +195,70 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool dataTraverseStmtPost(Stmt *S) { return true; } - /// \brief Recursively visit a type, by dispatching to + /// Recursively visit a type, by dispatching to /// Traverse*Type() based on the argument's getTypeClass() property. /// /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is a Null type). bool TraverseType(QualType T); - /// \brief Recursively visit a type with location, by dispatching to + /// Recursively visit a type with location, by dispatching to /// Traverse*TypeLoc() based on the argument type's getTypeClass() property. /// /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is a Null type location). bool TraverseTypeLoc(TypeLoc TL); - /// \brief Recursively visit an attribute, by dispatching to + /// Recursively visit an attribute, by dispatching to /// Traverse*Attr() based on the argument's dynamic type. /// /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is a Null type location). bool TraverseAttr(Attr *At); - /// \brief Recursively visit a declaration, by dispatching to + /// Recursively visit a declaration, by dispatching to /// Traverse*Decl() based on the argument's dynamic type. /// /// \returns false if the visitation was terminated early, true /// otherwise (including when the argument is NULL). bool TraverseDecl(Decl *D); - /// \brief Recursively visit a C++ nested-name-specifier. + /// Recursively visit a C++ nested-name-specifier. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS); - /// \brief Recursively visit a C++ nested-name-specifier with location + /// Recursively visit a C++ nested-name-specifier with location /// information. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); - /// \brief Recursively visit a name with its location information. + /// Recursively visit a name with its location information. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo); - /// \brief Recursively visit a template name and dispatch to the + /// Recursively visit a template name and dispatch to the /// appropriate method. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseTemplateName(TemplateName Template); - /// \brief Recursively visit a template argument and dispatch to the + /// Recursively visit a template argument and dispatch to the /// appropriate method for the argument type. /// /// \returns false if the visitation was terminated early, true otherwise. // FIXME: migrate callers to TemplateArgumentLoc instead. bool TraverseTemplateArgument(const TemplateArgument &Arg); - /// \brief Recursively visit a template argument location and dispatch to the + /// Recursively visit a template argument location and dispatch to the /// appropriate method for the argument type. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc); - /// \brief Recursively visit a set of template arguments. + /// Recursively visit a set of template arguments. /// This can be overridden by a subclass, but it's not expected that /// will be needed -- this visitor always dispatches to another. /// @@ -267,13 +267,13 @@ public: bool TraverseTemplateArguments(const TemplateArgument *Args, unsigned NumArgs); - /// \brief Recursively visit a base specifier. This can be overridden by a + /// Recursively visit a base specifier. This can be overridden by a /// subclass. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseCXXBaseSpecifier(const CXXBaseSpecifier &Base); - /// \brief Recursively visit a constructor initializer. This + /// Recursively visit a constructor initializer. This /// automatically dispatches to another visitor for the initializer /// expression, but not for the name of the initializer, so may /// be overridden for clients that need access to the name. @@ -281,14 +281,14 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseConstructorInitializer(CXXCtorInitializer *Init); - /// \brief Recursively visit a lambda capture. \c Init is the expression that + /// Recursively visit a lambda capture. \c Init is the expression that /// will be used to initialize the capture. /// /// \returns false if the visitation was terminated early, true otherwise. bool TraverseLambdaCapture(LambdaExpr *LE, const LambdaCapture *C, Expr *Init); - /// \brief Recursively visit the body of a lambda expression. + /// Recursively visit the body of a lambda expression. /// /// This provides a hook for visitors that need more context when visiting /// \c LE->getBody(). @@ -296,7 +296,7 @@ public: /// \returns false if the visitation was terminated early, true otherwise. bool TraverseLambdaBody(LambdaExpr *LE, DataRecursionQueue *Queue = nullptr); - /// \brief Recursively visit the syntactic or semantic form of an + /// Recursively visit the syntactic or semantic form of an /// initialization list. /// /// \returns false if the visitation was terminated early, true otherwise. @@ -305,7 +305,7 @@ public: // ---- Methods on Attrs ---- - // \brief Visit an attribute. + // Visit an attribute. bool VisitAttr(Attr *A) { return true; } // Declare Traverse* and empty Visit* for all Attr classes. @@ -529,7 +529,7 @@ private: bool TraverseOMPClause(OMPClause *C); #define OPENMP_CLAUSE(Name, Class) bool Visit##Class(Class *C); #include "clang/Basic/OpenMPKinds.def" - /// \brief Process clauses with list of variables. + /// Process clauses with list of variables. template <typename T> bool VisitOMPClauseList(T *Node); /// Process clauses with pre-initis. bool VisitOMPClauseWithPreInit(OMPClauseWithPreInit *Node); @@ -993,6 +993,12 @@ DEF_TRAVERSE_TYPE(DependentAddressSpaceType, { TRY_TO(TraverseType(T->getPointeeType())); }) +DEF_TRAVERSE_TYPE(DependentVectorType, { + if (T->getSizeExpr()) + TRY_TO(TraverseStmt(T->getSizeExpr())); + TRY_TO(TraverseType(T->getElementType())); +}) + DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, { if (T->getSizeExpr()) TRY_TO(TraverseStmt(T->getSizeExpr())); @@ -1221,6 +1227,12 @@ DEF_TRAVERSE_TYPELOC(VectorType, { TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); }) +DEF_TRAVERSE_TYPELOC(DependentVectorType, { + if (TL.getTypePtr()->getSizeExpr()) + TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr())); + TRY_TO(TraverseType(TL.getTypePtr()->getElementType())); +}) + // FIXME: size and attributes // FIXME: base VectorTypeLoc is unfinished DEF_TRAVERSE_TYPELOC(ExtVectorType, { @@ -2585,6 +2597,7 @@ DEF_TRAVERSE_STMT(CoyieldExpr, { // These literals (all of them) do not need any action. DEF_TRAVERSE_STMT(IntegerLiteral, {}) +DEF_TRAVERSE_STMT(FixedPointLiteral, {}) DEF_TRAVERSE_STMT(CharacterLiteral, {}) DEF_TRAVERSE_STMT(FloatingLiteral, {}) DEF_TRAVERSE_STMT(ImaginaryLiteral, {}) diff --git a/include/clang/AST/Redeclarable.h b/include/clang/AST/Redeclarable.h index 86b0f356e7b53..c2bd6e6fd1361 100644 --- a/include/clang/AST/Redeclarable.h +++ b/include/clang/AST/Redeclarable.h @@ -36,7 +36,7 @@ class Decl; // DeclLink that may point to one of 3 possible states: // - the "previous" (temporal) element in the chain // - the "latest" (temporal) element in the chain -// - the an "uninitialized-latest" value (when newly-constructed) +// - the "uninitialized-latest" value (when newly-constructed) // // - The first element is also often called the canonical element. Every // element has a pointer to it so that "getCanonical" can be fast. @@ -48,10 +48,8 @@ class Decl; // "most-recent" when referring to temporal order: order of addition // to the chain. // -// - To make matters confusing, the DeclLink type uses the term "next" -// for its pointer-storage internally (thus functions like -// NextIsPrevious). It's easiest to just ignore the implementation of -// DeclLink when making sense of the redeclaration chain. +// - It's easiest to just ignore the implementation of DeclLink when making +// sense of the redeclaration chain. // // - There's also a "definition" link for several types of // redeclarable, where only one definition should exist at any given @@ -82,7 +80,7 @@ class Decl; // | link +-----+ | // +-->-------------------------------------------+ -/// \brief Provides common interface for the Decls that can be redeclared. +/// Provides common interface for the Decls that can be redeclared. template<typename decl_type> class Redeclarable { protected: @@ -105,66 +103,64 @@ protected: /// previous declaration. using NotKnownLatest = llvm::PointerUnion<Previous, UninitializedLatest>; - mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Next; + mutable llvm::PointerUnion<NotKnownLatest, KnownLatest> Link; public: enum PreviousTag { PreviousLink }; enum LatestTag { LatestLink }; DeclLink(LatestTag, const ASTContext &Ctx) - : Next(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {} - DeclLink(PreviousTag, decl_type *D) : Next(NotKnownLatest(Previous(D))) {} + : Link(NotKnownLatest(reinterpret_cast<UninitializedLatest>(&Ctx))) {} + DeclLink(PreviousTag, decl_type *D) : Link(NotKnownLatest(Previous(D))) {} - bool NextIsPrevious() const { - return Next.is<NotKnownLatest>() && + bool isFirst() const { + return Link.is<KnownLatest>() || // FIXME: 'template' is required on the next line due to an // apparent clang bug. - Next.get<NotKnownLatest>().template is<Previous>(); + Link.get<NotKnownLatest>().template is<UninitializedLatest>(); } - bool NextIsLatest() const { return !NextIsPrevious(); } - - decl_type *getNext(const decl_type *D) const { - if (Next.is<NotKnownLatest>()) { - NotKnownLatest NKL = Next.get<NotKnownLatest>(); + decl_type *getPrevious(const decl_type *D) const { + if (Link.is<NotKnownLatest>()) { + NotKnownLatest NKL = Link.get<NotKnownLatest>(); if (NKL.is<Previous>()) return static_cast<decl_type*>(NKL.get<Previous>()); // Allocate the generational 'most recent' cache now, if needed. - Next = KnownLatest(*reinterpret_cast<const ASTContext *>( + Link = KnownLatest(*reinterpret_cast<const ASTContext *>( NKL.get<UninitializedLatest>()), const_cast<decl_type *>(D)); } - return static_cast<decl_type*>(Next.get<KnownLatest>().get(D)); + return static_cast<decl_type*>(Link.get<KnownLatest>().get(D)); } void setPrevious(decl_type *D) { - assert(NextIsPrevious() && "decl became non-canonical unexpectedly"); - Next = Previous(D); + assert(!isFirst() && "decl became non-canonical unexpectedly"); + Link = Previous(D); } void setLatest(decl_type *D) { - assert(NextIsLatest() && "decl became canonical unexpectedly"); - if (Next.is<NotKnownLatest>()) { - NotKnownLatest NKL = Next.get<NotKnownLatest>(); - Next = KnownLatest(*reinterpret_cast<const ASTContext *>( + assert(isFirst() && "decl became canonical unexpectedly"); + if (Link.is<NotKnownLatest>()) { + NotKnownLatest NKL = Link.get<NotKnownLatest>(); + Link = KnownLatest(*reinterpret_cast<const ASTContext *>( NKL.get<UninitializedLatest>()), D); } else { - auto Latest = Next.get<KnownLatest>(); + auto Latest = Link.get<KnownLatest>(); Latest.set(D); - Next = Latest; + Link = Latest; } } - void markIncomplete() { Next.get<KnownLatest>().markIncomplete(); } + void markIncomplete() { Link.get<KnownLatest>().markIncomplete(); } Decl *getLatestNotUpdated() const { - assert(NextIsLatest() && "expected a canonical decl"); - if (Next.is<NotKnownLatest>()) + assert(isFirst() && "expected a canonical decl"); + if (Link.is<NotKnownLatest>()) return nullptr; - return Next.get<KnownLatest>().getNotUpdated(); + return Link.get<KnownLatest>().getNotUpdated(); } }; @@ -176,10 +172,10 @@ protected: return DeclLink(DeclLink::LatestLink, Ctx); } - /// \brief Points to the next redeclaration in the chain. + /// Points to the next redeclaration in the chain. /// - /// If NextIsPrevious() is true, this is a link to the previous declaration - /// of this same Decl. If NextIsLatest() is true, this is the first + /// If isFirst() is false, this is a link to the previous declaration + /// of this same Decl. If isFirst() is true, this is the first /// declaration and Link points to the latest declaration. For example: /// /// #1 int f(int x, int y = 1); // <pointer to #3, true> @@ -192,7 +188,7 @@ protected: decl_type *First; decl_type *getNextRedeclaration() const { - return RedeclLink.getNext(static_cast<const decl_type *>(this)); + return RedeclLink.getPrevious(static_cast<const decl_type *>(this)); } public: @@ -203,10 +199,10 @@ public: : RedeclLink(LatestDeclLink(Ctx)), First(static_cast<decl_type *>(this)) {} - /// \brief Return the previous declaration of this declaration or NULL if this + /// Return the previous declaration of this declaration or NULL if this /// is the first declaration. decl_type *getPreviousDecl() { - if (RedeclLink.NextIsPrevious()) + if (!RedeclLink.isFirst()) return getNextRedeclaration(); return nullptr; } @@ -215,32 +211,32 @@ public: static_cast<const decl_type*>(this))->getPreviousDecl(); } - /// \brief Return the first declaration of this declaration or itself if this + /// Return the first declaration of this declaration or itself if this /// is the only declaration. decl_type *getFirstDecl() { return First; } - /// \brief Return the first declaration of this declaration or itself if this + /// Return the first declaration of this declaration or itself if this /// is the only declaration. const decl_type *getFirstDecl() const { return First; } - /// \brief True if this is the first declaration in its redeclaration chain. - bool isFirstDecl() const { return RedeclLink.NextIsLatest(); } + /// True if this is the first declaration in its redeclaration chain. + bool isFirstDecl() const { return RedeclLink.isFirst(); } - /// \brief Returns the most recent (re)declaration of this declaration. + /// Returns the most recent (re)declaration of this declaration. decl_type *getMostRecentDecl() { return getFirstDecl()->getNextRedeclaration(); } - /// \brief Returns the most recent (re)declaration of this declaration. + /// Returns the most recent (re)declaration of this declaration. const decl_type *getMostRecentDecl() const { return getFirstDecl()->getNextRedeclaration(); } - /// \brief Set the previous declaration. If PrevDecl is NULL, set this as the + /// Set the previous declaration. If PrevDecl is NULL, set this as the /// first and only declaration. void setPreviousDecl(decl_type *PrevDecl); - /// \brief Iterates through all the redeclarations of the same decl. + /// Iterates through all the redeclarations of the same decl. class redecl_iterator { /// Current - The current declaration. decl_type *Current = nullptr; @@ -294,7 +290,7 @@ public: using redecl_range = llvm::iterator_range<redecl_iterator>; - /// \brief Returns an iterator range for all the redeclarations of the same + /// Returns an iterator range for all the redeclarations of the same /// decl. It will iterate at least once (when this decl is the only one). redecl_range redecls() const { return redecl_range(redecl_iterator(const_cast<decl_type *>( @@ -306,11 +302,11 @@ public: redecl_iterator redecls_end() const { return redecls().end(); } }; -/// \brief Get the primary declaration for a declaration from an AST file. That +/// Get the primary declaration for a declaration from an AST file. That /// will be the first-loaded declaration. Decl *getPrimaryMergedDecl(Decl *D); -/// \brief Provides common interface for the Decls that cannot be redeclared, +/// Provides common interface for the Decls that cannot be redeclared, /// but can be merged if the same declaration is brought in from multiple /// modules. template<typename decl_type> @@ -318,25 +314,25 @@ class Mergeable { public: Mergeable() = default; - /// \brief Return the first declaration of this declaration or itself if this + /// Return the first declaration of this declaration or itself if this /// is the only declaration. decl_type *getFirstDecl() { - decl_type *D = static_cast<decl_type*>(this); + auto *D = static_cast<decl_type *>(this); if (!D->isFromASTFile()) return D; return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D))); } - /// \brief Return the first declaration of this declaration or itself if this + /// Return the first declaration of this declaration or itself if this /// is the only declaration. const decl_type *getFirstDecl() const { - const decl_type *D = static_cast<const decl_type*>(this); + const auto *D = static_cast<const decl_type *>(this); if (!D->isFromASTFile()) return D; return cast<decl_type>(getPrimaryMergedDecl(const_cast<decl_type*>(D))); } - /// \brief Returns true if this is the first declaration. + /// Returns true if this is the first declaration. bool isFirstDecl() const { return getFirstDecl() == this; } }; diff --git a/include/clang/AST/SelectorLocationsKind.h b/include/clang/AST/SelectorLocationsKind.h index 6d903f820cd49..6ca2dba47558f 100644 --- a/include/clang/AST/SelectorLocationsKind.h +++ b/include/clang/AST/SelectorLocationsKind.h @@ -23,32 +23,32 @@ namespace clang { class Expr; class ParmVarDecl; -/// \brief Whether all locations of the selector identifiers are in a +/// Whether all locations of the selector identifiers are in a /// "standard" position. enum SelectorLocationsKind { - /// \brief Non-standard. + /// Non-standard. SelLoc_NonStandard = 0, - /// \brief For nullary selectors, immediately before the end: + /// For nullary selectors, immediately before the end: /// "[foo release]" / "-(void)release;" /// Or immediately before the arguments: /// "[foo first:1 second:2]" / "-(id)first:(int)x second:(int)y; SelLoc_StandardNoSpace = 1, - /// \brief For nullary selectors, immediately before the end: + /// For nullary selectors, immediately before the end: /// "[foo release]" / "-(void)release;" /// Or with a space between the arguments: /// "[foo first: 1 second: 2]" / "-(id)first: (int)x second: (int)y; SelLoc_StandardWithSpace = 2 }; -/// \brief Returns true if all \p SelLocs are in a "standard" location. +/// Returns true if all \p SelLocs are in a "standard" location. SelectorLocationsKind hasStandardSelectorLocs(Selector Sel, ArrayRef<SourceLocation> SelLocs, ArrayRef<Expr *> Args, SourceLocation EndLoc); -/// \brief Get the "standard" location of a selector identifier, e.g: +/// Get the "standard" location of a selector identifier, e.g: /// For nullary selectors, immediately before ']': "[foo release]" /// /// \param WithArgSpace if true the standard location is with a space apart @@ -60,13 +60,13 @@ SourceLocation getStandardSelectorLoc(unsigned Index, ArrayRef<Expr *> Args, SourceLocation EndLoc); -/// \brief Returns true if all \p SelLocs are in a "standard" location. +/// Returns true if all \p SelLocs are in a "standard" location. SelectorLocationsKind hasStandardSelectorLocs(Selector Sel, ArrayRef<SourceLocation> SelLocs, ArrayRef<ParmVarDecl *> Args, SourceLocation EndLoc); -/// \brief Get the "standard" location of a selector identifier, e.g: +/// Get the "standard" location of a selector identifier, e.g: /// For nullary selectors, immediately before ']': "[foo release]" /// /// \param WithArgSpace if true the standard location is with a space apart diff --git a/include/clang/AST/Stmt.h b/include/clang/AST/Stmt.h index b27dbfacf6a64..91dbcb71a600c 100644 --- a/include/clang/AST/Stmt.h +++ b/include/clang/AST/Stmt.h @@ -92,7 +92,7 @@ protected: class StmtBitfields { friend class Stmt; - /// \brief The statement class. + /// The statement class. unsigned sClass : 8; }; enum { NumStmtBits = 8 }; @@ -198,11 +198,13 @@ protected: class CastExprBitfields { friend class CastExpr; + friend class ImplicitCastExpr; unsigned : NumExprBits; unsigned Kind : 6; - unsigned BasePathSize : 32 - 6 - NumExprBits; + unsigned PartOfExplicitCast : 1; // Only set for ImplicitCastExpr. + unsigned BasePathSize : 32 - 6 - 1 - NumExprBits; }; class CallExprBitfields { @@ -237,6 +239,16 @@ protected: unsigned ResultIndex : 32 - 8 - NumExprBits; }; + class OpaqueValueExprBitfields { + friend class OpaqueValueExpr; + + unsigned : NumExprBits; + + /// The OVE is a unique semantic reference to its source expressio if this + /// bit is set to true. + unsigned IsUnique : 1; + }; + class ObjCIndirectCopyRestoreExprBitfields { friend class ObjCIndirectCopyRestoreExpr; @@ -262,14 +274,14 @@ protected: unsigned : NumExprBits; - /// \brief The kind of type trait, which is a value of a TypeTrait enumerator. + /// The kind of type trait, which is a value of a TypeTrait enumerator. unsigned Kind : 8; - /// \brief If this expression is not value-dependent, this indicates whether + /// If this expression is not value-dependent, this indicates whether /// the trait evaluated true or false. unsigned Value : 1; - /// \brief The number of arguments to this type trait. + /// The number of arguments to this type trait. unsigned NumArgs : 32 - 8 - 1 - NumExprBits; }; @@ -294,6 +306,7 @@ protected: CallExprBitfields CallExprBits; ExprWithCleanupsBitfields ExprWithCleanupsBits; PseudoObjectExprBitfields PseudoObjectExprBits; + OpaqueValueExprBitfields OpaqueValueExprBits; ObjCIndirectCopyRestoreExprBitfields ObjCIndirectCopyRestoreExprBits; InitListExprBitfields InitListExprBits; TypeTraitExprBitfields TypeTraitExprBits; @@ -319,7 +332,7 @@ public: void operator delete(void *, void *) noexcept {} public: - /// \brief A placeholder type used to construct an empty shell of a + /// A placeholder type used to construct an empty shell of a /// type, that will be filled in later (e.g., by some /// de-serialization). struct EmptyShell {}; @@ -358,11 +371,11 @@ protected: }; private: - /// \brief Whether statistic collection is enabled. + /// Whether statistic collection is enabled. static bool StatisticsEnabled; protected: - /// \brief Construct an empty statement. + /// Construct an empty statement. explicit Stmt(StmtClass SC, EmptyShell) : Stmt(SC) {} public: @@ -393,7 +406,7 @@ public: static void EnableStatistics(); static void PrintStats(); - /// \brief Dumps the specified AST fragment and all subtrees to + /// Dumps the specified AST fragment and all subtrees to /// \c llvm::errs(). void dump() const; void dump(SourceManager &SM) const; @@ -421,7 +434,7 @@ public: return const_cast<Stmt *>(this)->IgnoreImplicit(); } - /// \brief Skip no-op (attributed, compound) container stmts and skip captured + /// 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 *IgnoreContainers(bool IgnoreCaptured = false) const { @@ -444,6 +457,7 @@ public: using const_child_range = llvm::iterator_range<const_child_iterator>; child_range children(); + const_child_range children() const { auto Children = const_cast<Stmt *>(this)->children(); return const_child_range(Children.begin(), Children.end()); @@ -455,7 +469,7 @@ public: const_child_iterator child_begin() const { return children().begin(); } const_child_iterator child_end() const { return children().end(); } - /// \brief Produce a unique representation of the given statement. + /// Produce a unique representation of the given statement. /// /// \param ID once the profiling operation is complete, will contain /// the unique representation of the given statement. @@ -470,7 +484,7 @@ public: void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, bool Canonical) const; - /// \brief Calculate a unique representation for a statement that is + /// Calculate a unique representation for a statement that is /// stable across compiler invocations. /// /// \param ID profile information will be stored in ID. @@ -492,7 +506,7 @@ public: DeclStmt(DeclGroupRef dg, SourceLocation startLoc, SourceLocation endLoc) : Stmt(DeclStmtClass), DG(dg), StartLoc(startLoc), EndLoc(endLoc) {} - /// \brief Build an empty declaration statement. + /// Build an empty declaration statement. explicit DeclStmt(EmptyShell Empty) : Stmt(DeclStmtClass, Empty) {} /// isSingleDecl - This method returns true if this DeclStmt refers @@ -532,9 +546,11 @@ public: using decl_const_range = llvm::iterator_range<const_decl_iterator>; decl_range decls() { return decl_range(decl_begin(), decl_end()); } + decl_const_range decls() const { return decl_const_range(decl_begin(), decl_end()); } + decl_iterator decl_begin() { return DG.begin(); } decl_iterator decl_end() { return DG.end(); } const_decl_iterator decl_begin() const { return DG.begin(); } @@ -556,7 +572,7 @@ public: class NullStmt : public Stmt { SourceLocation SemiLoc; - /// \brief True if the null statement was preceded by an empty macro, e.g: + /// True if the null statement was preceded by an empty macro, e.g: /// @code /// #define CALL(x) /// CALL(0); @@ -571,7 +587,7 @@ public: : Stmt(NullStmtClass), SemiLoc(L), HasLeadingEmptyMacro(hasLeadingEmptyMacro) {} - /// \brief Build an empty null statement. + /// Build an empty null statement. explicit NullStmt(EmptyShell Empty) : Stmt(NullStmtClass, Empty) {} SourceLocation getSemiLoc() const { return SemiLoc; } @@ -608,13 +624,13 @@ public: static CompoundStmt *Create(const ASTContext &C, ArrayRef<Stmt *> Stmts, SourceLocation LB, SourceLocation RB); - // \brief Build an empty compound statement with a location. + // Build an empty compound statement with a location. explicit CompoundStmt(SourceLocation Loc) : Stmt(CompoundStmtClass), LBraceLoc(Loc), RBraceLoc(Loc) { CompoundStmtBits.NumStmts = 0; } - // \brief Build an empty compound statement. + // Build an empty compound statement. static CompoundStmt *CreateEmpty(const ASTContext &C, unsigned NumStmts); bool body_empty() const { return CompoundStmtBits.NumStmts == 0; } @@ -627,6 +643,7 @@ public: body_iterator body_begin() { return getTrailingObjects<Stmt *>(); } body_iterator body_end() { return body_begin() + size(); } Stmt *body_front() { return !body_empty() ? body_begin()[0] : nullptr; } + Stmt *body_back() { return !body_empty() ? body_begin()[size() - 1] : nullptr; } @@ -646,6 +663,7 @@ public: const_body_iterator body_begin() const { return getTrailingObjects<Stmt *>(); } + const_body_iterator body_end() const { return body_begin() + size(); } const Stmt *body_front() const { @@ -751,7 +769,7 @@ public: EllipsisLoc = ellipsisLoc; } - /// \brief Build an empty switch case statement. + /// Build an empty switch case statement. explicit CaseStmt(EmptyShell Empty) : SwitchCase(CaseStmtClass, Empty) {} SourceLocation getCaseLoc() const { return KeywordLoc; } @@ -784,7 +802,7 @@ public: SourceLocation getLocEnd() const LLVM_READONLY { // Handle deeply nested case statements with iteration instead of recursion. const CaseStmt *CS = this; - while (const CaseStmt *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) + while (const auto *CS2 = dyn_cast<CaseStmt>(CS->getSubStmt())) CS = CS2; return CS->getSubStmt()->getLocEnd(); @@ -807,7 +825,7 @@ public: DefaultStmt(SourceLocation DL, SourceLocation CL, Stmt *substmt) : SwitchCase(DefaultStmtClass, DL, CL), SubStmt(substmt) {} - /// \brief Build an empty default statement. + /// Build an empty default statement. explicit DefaultStmt(EmptyShell Empty) : SwitchCase(DefaultStmtClass, Empty) {} @@ -832,7 +850,7 @@ public: }; inline SourceLocation SwitchCase::getLocEnd() const { - if (const CaseStmt *CS = dyn_cast<CaseStmt>(this)) + if (const auto *CS = dyn_cast<CaseStmt>(this)) return CS->getLocEnd(); return cast<DefaultStmt>(this)->getLocEnd(); } @@ -852,7 +870,7 @@ public: "LabelStmt too big"); } - // \brief Build an empty label statement. + // Build an empty label statement. explicit LabelStmt(EmptyShell Empty) : Stmt(LabelStmtClass, Empty) {} SourceLocation getIdentLoc() const { return IdentLoc; } @@ -874,7 +892,7 @@ public: } }; -/// \brief Represents an attribute applied to a statement. +/// Represents an attribute applied to a statement. /// /// Represents an attribute applied to a statement. For example: /// [[omp::for(...)]] for (...) { ... } @@ -895,7 +913,7 @@ class AttributedStmt final } explicit AttributedStmt(EmptyShell Empty, unsigned NumAttrs) - : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { + : Stmt(AttributedStmtClass, Empty), NumAttrs(NumAttrs) { std::fill_n(getAttrArrayPtr(), NumAttrs, nullptr); } @@ -908,7 +926,7 @@ public: static AttributedStmt *Create(const ASTContext &C, SourceLocation Loc, ArrayRef<const Attr*> Attrs, Stmt *SubStmt); - // \brief Build an empty attributed statement. + // Build an empty attributed statement. static AttributedStmt *CreateEmpty(const ASTContext &C, unsigned NumAttrs); SourceLocation getAttrLoc() const { return AttrLoc; } @@ -943,10 +961,10 @@ public: Stmt *then, SourceLocation EL = SourceLocation(), Stmt *elsev = nullptr); - /// \brief Build an empty if/then/else statement + /// Build an empty if/then/else statement explicit IfStmt(EmptyShell Empty) : Stmt(IfStmtClass, Empty) {} - /// \brief Retrieve the variable declared in this "if" statement, if any. + /// Retrieve the variable declared in this "if" statement, if any. /// /// In the following example, "x" is the condition variable. /// \code @@ -1022,10 +1040,10 @@ class SwitchStmt : public Stmt { public: SwitchStmt(const ASTContext &C, Stmt *Init, VarDecl *Var, Expr *cond); - /// \brief Build a empty switch statement. + /// Build a empty switch statement. explicit SwitchStmt(EmptyShell Empty) : Stmt(SwitchStmtClass, Empty) {} - /// \brief Retrieve the variable declared in this "switch" statement, if any. + /// Retrieve the variable declared in this "switch" statement, if any. /// /// In the following example, "x" is the condition variable. /// \code @@ -1056,7 +1074,7 @@ public: void setBody(Stmt *S) { SubExprs[BODY] = S; } SwitchCase *getSwitchCaseList() { return FirstCase.getPointer(); } - /// \brief Set the case list for this switch statement. + /// Set the case list for this switch statement. void setSwitchCaseList(SwitchCase *SC) { FirstCase.setPointer(SC); } SourceLocation getSwitchLoc() const { return SwitchLoc; } @@ -1108,10 +1126,10 @@ public: WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL); - /// \brief Build an empty while statement. + /// Build an empty while statement. explicit WhileStmt(EmptyShell Empty) : Stmt(WhileStmtClass, Empty) {} - /// \brief Retrieve the variable declared in this "while" statement, if any. + /// Retrieve the variable declared in this "while" statement, if any. /// /// In the following example, "x" is the condition variable. /// \code @@ -1170,7 +1188,7 @@ public: SubExprs[BODY] = body; } - /// \brief Build an empty do-while statement. + /// Build an empty do-while statement. explicit DoStmt(EmptyShell Empty) : Stmt(DoStmtClass, Empty) {} Expr *getCond() { return reinterpret_cast<Expr*>(SubExprs[COND]); } @@ -1215,12 +1233,12 @@ public: Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, SourceLocation RP); - /// \brief Build an empty for statement. + /// Build an empty for statement. explicit ForStmt(EmptyShell Empty) : Stmt(ForStmtClass, Empty) {} Stmt *getInit() { return SubExprs[INIT]; } - /// \brief Retrieve the variable declared in this "for" statement, if any. + /// Retrieve the variable declared in this "for" statement, if any. /// /// In the following example, "y" is the condition variable. /// \code @@ -1284,7 +1302,7 @@ public: GotoStmt(LabelDecl *label, SourceLocation GL, SourceLocation LL) : Stmt(GotoStmtClass), Label(label), GotoLoc(GL), LabelLoc(LL) {} - /// \brief Build an empty goto statement. + /// Build an empty goto statement. explicit GotoStmt(EmptyShell Empty) : Stmt(GotoStmtClass, Empty) {} LabelDecl *getLabel() const { return Label; } @@ -1320,7 +1338,7 @@ public: : Stmt(IndirectGotoStmtClass), GotoLoc(gotoLoc), StarLoc(starLoc), Target((Stmt*)target) {} - /// \brief Build an empty indirect goto statement. + /// Build an empty indirect goto statement. explicit IndirectGotoStmt(EmptyShell Empty) : Stmt(IndirectGotoStmtClass, Empty) {} @@ -1358,7 +1376,7 @@ class ContinueStmt : public Stmt { public: ContinueStmt(SourceLocation CL) : Stmt(ContinueStmtClass), ContinueLoc(CL) {} - /// \brief Build an empty continue statement. + /// Build an empty continue statement. explicit ContinueStmt(EmptyShell Empty) : Stmt(ContinueStmtClass, Empty) {} SourceLocation getContinueLoc() const { return ContinueLoc; } @@ -1387,7 +1405,7 @@ public: "BreakStmt too large"); } - /// \brief Build an empty break statement. + /// Build an empty break statement. explicit BreakStmt(EmptyShell Empty) : Stmt(BreakStmtClass, Empty) {} SourceLocation getBreakLoc() const { return BreakLoc; } @@ -1426,7 +1444,7 @@ public: : Stmt(ReturnStmtClass), RetLoc(RL), RetExpr((Stmt *)E), NRVOCandidate(NRVOCandidate) {} - /// \brief Build an empty return expression. + /// Build an empty return expression. explicit ReturnStmt(EmptyShell Empty) : Stmt(ReturnStmtClass, Empty) {} const Expr *getRetValue() const; @@ -1436,7 +1454,7 @@ public: SourceLocation getReturnLoc() const { return RetLoc; } void setReturnLoc(SourceLocation L) { RetLoc = L; } - /// \brief Retrieve the variable that might be used for the named return + /// Retrieve the variable that might be used for the named return /// value optimization. /// /// The optimization itself can only be performed if the variable is @@ -1468,11 +1486,11 @@ protected: SourceLocation AsmLoc; - /// \brief True if the assembly statement does not have any input or output + /// True if the assembly statement does not have any input or output /// operands. bool IsSimple; - /// \brief If true, treat this inline assembly as having side effects. + /// If true, treat this inline assembly as having side effects. /// This assembly statement should not be optimized, deleted or moved. bool IsVolatile; @@ -1489,7 +1507,7 @@ protected: NumClobbers(numclobbers) {} public: - /// \brief Build an empty inline-assembly statement. + /// Build an empty inline-assembly statement. explicit AsmStmt(StmtClass SC, EmptyShell Empty) : Stmt(SC, Empty) {} SourceLocation getAsmLoc() const { return AsmLoc; } @@ -1501,8 +1519,8 @@ public: bool isVolatile() const { return IsVolatile; } void setVolatile(bool V) { IsVolatile = V; } - SourceLocation getLocStart() const LLVM_READONLY { return SourceLocation(); } - SourceLocation getLocEnd() const LLVM_READONLY { return SourceLocation(); } + SourceLocation getLocStart() const LLVM_READONLY { return {}; } + SourceLocation getLocEnd() const LLVM_READONLY { return {}; } //===--- Asm String Analysis ---===// @@ -1635,7 +1653,7 @@ public: StringLiteral *asmstr, unsigned numclobbers, StringLiteral **clobbers, SourceLocation rparenloc); - /// \brief Build an empty inline-assembly statement. + /// Build an empty inline-assembly statement. explicit GCCAsmStmt(EmptyShell Empty) : AsmStmt(GCCAsmStmtClass, Empty) {} SourceLocation getRParenLoc() const { return RParenLoc; } @@ -1675,9 +1693,7 @@ public: bool isString() const { return MyKind == String; } bool isOperand() const { return MyKind == Operand; } - const std::string &getString() const { - return Str; - } + const std::string &getString() const { return Str; } unsigned getOperandNo() const { assert(isOperand()); @@ -1707,15 +1723,13 @@ public: //===--- Output operands ---===// - IdentifierInfo *getOutputIdentifier(unsigned i) const { - return Names[i]; - } + IdentifierInfo *getOutputIdentifier(unsigned i) const { return Names[i]; } StringRef getOutputName(unsigned i) const { if (IdentifierInfo *II = getOutputIdentifier(i)) return II->getName(); - return StringRef(); + return {}; } StringRef getOutputConstraint(unsigned i) const; @@ -1743,7 +1757,7 @@ public: if (IdentifierInfo *II = getInputIdentifier(i)) return II->getName(); - return StringRef(); + return {}; } StringRef getInputConstraint(unsigned i) const; @@ -1816,7 +1830,7 @@ public: ArrayRef<Expr*> exprs, StringRef asmstr, ArrayRef<StringRef> clobbers, SourceLocation endloc); - /// \brief Build an empty MS-style inline-assembly statement. + /// Build an empty MS-style inline-assembly statement. explicit MSAsmStmt(EmptyShell Empty) : AsmStmt(MSAsmStmtClass, Empty) {} SourceLocation getLBraceLoc() const { return LBraceLoc; } @@ -1930,7 +1944,7 @@ public: } child_range children() { - return child_range(Children,Children+2); + return child_range(Children, Children+2); } static bool classof(const Stmt *T) { @@ -2011,7 +2025,7 @@ public: SEHFinallyStmt *getFinallyHandler() const; child_range children() { - return child_range(Children,Children+2); + return child_range(Children, Children+2); } static bool classof(const Stmt *T) { @@ -2027,7 +2041,7 @@ public: explicit SEHLeaveStmt(SourceLocation LL) : Stmt(SEHLeaveStmtClass), LeaveLoc(LL) {} - /// \brief Build an empty __leave statement. + /// Build an empty __leave statement. explicit SEHLeaveStmt(EmptyShell Empty) : Stmt(SEHLeaveStmtClass, Empty) {} SourceLocation getLeaveLoc() const { return LeaveLoc; } @@ -2046,7 +2060,7 @@ public: } }; -/// \brief This captures a statement into a function. For example, the following +/// This captures a statement into a function. For example, the following /// pragma annotated compound statement can be represented as a CapturedStmt, /// and this compound statement is the body of an anonymous outlined function. /// @code @@ -2057,7 +2071,7 @@ public: /// @endcode class CapturedStmt : public Stmt { public: - /// \brief The different capture forms: by 'this', by reference, capture for + /// The different capture forms: by 'this', by reference, capture for /// variable-length array type etc. enum VariableCaptureKind { VCK_This, @@ -2066,7 +2080,7 @@ public: VCK_VLAType, }; - /// \brief Describes the capture of either a variable, or 'this', or + /// Describes the capture of either a variable, or 'this', or /// variable-length array type. class Capture { llvm::PointerIntPair<VarDecl *, 2, VariableCaptureKind> VarAndKind; @@ -2075,7 +2089,7 @@ public: public: friend class ASTStmtReader; - /// \brief Create a new capture. + /// Create a new capture. /// /// \param Loc The source location associated with this capture. /// @@ -2085,52 +2099,52 @@ public: Capture(SourceLocation Loc, VariableCaptureKind Kind, VarDecl *Var = nullptr); - /// \brief Determine the kind of capture. + /// Determine the kind of capture. VariableCaptureKind getCaptureKind() const; - /// \brief Retrieve the source location at which the variable or 'this' was + /// Retrieve the source location at which the variable or 'this' was /// first used. SourceLocation getLocation() const { return Loc; } - /// \brief Determine whether this capture handles the C++ 'this' pointer. + /// Determine whether this capture handles the C++ 'this' pointer. bool capturesThis() const { return getCaptureKind() == VCK_This; } - /// \brief Determine whether this capture handles a variable (by reference). + /// Determine whether this capture handles a variable (by reference). bool capturesVariable() const { return getCaptureKind() == VCK_ByRef; } - /// \brief Determine whether this capture handles a variable by copy. + /// Determine whether this capture handles a variable by copy. bool capturesVariableByCopy() const { return getCaptureKind() == VCK_ByCopy; } - /// \brief Determine whether this capture handles a variable-length array + /// 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. + /// Retrieve the declaration of the variable being captured. /// /// This operation is only valid if this capture captures a variable. VarDecl *getCapturedVar() const; }; private: - /// \brief The number of variable captured, including 'this'. + /// The number of variable captured, including 'this'. unsigned NumCaptures; - /// \brief The pointer part is the implicit the outlined function and the + /// The pointer part is the implicit the outlined function and the /// int part is the captured region kind, 'CR_Default' etc. - llvm::PointerIntPair<CapturedDecl *, 1, CapturedRegionKind> CapDeclAndKind; + llvm::PointerIntPair<CapturedDecl *, 2, CapturedRegionKind> CapDeclAndKind; - /// \brief The record for captured variables, a RecordDecl or CXXRecordDecl. + /// The record for captured variables, a RecordDecl or CXXRecordDecl. RecordDecl *TheRecordDecl = nullptr; - /// \brief Construct a captured statement. + /// Construct a captured statement. CapturedStmt(Stmt *S, CapturedRegionKind Kind, ArrayRef<Capture> Captures, ArrayRef<Expr *> CaptureInits, CapturedDecl *CD, RecordDecl *RD); - /// \brief Construct an empty captured statement. + /// Construct an empty captured statement. CapturedStmt(EmptyShell Empty, unsigned NumCaptures); Stmt **getStoredStmts() { return reinterpret_cast<Stmt **>(this + 1); } @@ -2155,36 +2169,36 @@ public: static CapturedStmt *CreateDeserialized(const ASTContext &Context, unsigned NumCaptures); - /// \brief Retrieve the statement being captured. + /// Retrieve the statement being captured. Stmt *getCapturedStmt() { return getStoredStmts()[NumCaptures]; } const Stmt *getCapturedStmt() const { return getStoredStmts()[NumCaptures]; } - /// \brief Retrieve the outlined function declaration. + /// Retrieve the outlined function declaration. CapturedDecl *getCapturedDecl(); const CapturedDecl *getCapturedDecl() const; - /// \brief Set the outlined function declaration. + /// Set the outlined function declaration. void setCapturedDecl(CapturedDecl *D); - /// \brief Retrieve the captured region kind. + /// Retrieve the captured region kind. CapturedRegionKind getCapturedRegionKind() const; - /// \brief Set the captured region kind. + /// Set the captured region kind. void setCapturedRegionKind(CapturedRegionKind Kind); - /// \brief Retrieve the record declaration for captured variables. + /// Retrieve the record declaration for captured variables. const RecordDecl *getCapturedRecordDecl() const { return TheRecordDecl; } - /// \brief Set the record declaration for captured variables. + /// Set the record declaration for captured variables. void setCapturedRecordDecl(RecordDecl *D) { assert(D && "null RecordDecl"); TheRecordDecl = D; } - /// \brief True if this variable has been captured. + /// True if this variable has been captured. bool capturesVariable(const VarDecl *Var) const; - /// \brief An iterator that walks over the captures. + /// An iterator that walks over the captures. using capture_iterator = Capture *; using const_capture_iterator = const Capture *; using capture_range = llvm::iterator_range<capture_iterator>; @@ -2197,24 +2211,24 @@ public: return capture_const_range(capture_begin(), capture_end()); } - /// \brief Retrieve an iterator pointing to the first capture. + /// Retrieve an iterator pointing to the first capture. capture_iterator capture_begin() { return getStoredCaptures(); } const_capture_iterator capture_begin() const { return getStoredCaptures(); } - /// \brief Retrieve an iterator pointing past the end of the sequence of + /// Retrieve an iterator pointing past the end of the sequence of /// captures. capture_iterator capture_end() const { return getStoredCaptures() + NumCaptures; } - /// \brief Retrieve the number of captures, including 'this'. + /// Retrieve the number of captures, including 'this'. unsigned capture_size() const { return NumCaptures; } - /// \brief Iterator that walks over the capture initialization arguments. + /// Iterator that walks over the capture initialization arguments. using capture_init_iterator = Expr **; using capture_init_range = llvm::iterator_range<capture_init_iterator>; - /// \brief Const iterator that walks over the capture initialization + /// Const iterator that walks over the capture initialization /// arguments. using const_capture_init_iterator = Expr *const *; using const_capture_init_range = @@ -2228,7 +2242,7 @@ public: return const_capture_init_range(capture_init_begin(), capture_init_end()); } - /// \brief Retrieve the first initialization argument. + /// Retrieve the first initialization argument. capture_init_iterator capture_init_begin() { return reinterpret_cast<Expr **>(getStoredStmts()); } @@ -2237,7 +2251,7 @@ public: return reinterpret_cast<Expr *const *>(getStoredStmts()); } - /// \brief Retrieve the iterator pointing one past the last initialization + /// Retrieve the iterator pointing one past the last initialization /// argument. capture_init_iterator capture_init_end() { return capture_init_begin() + NumCaptures; diff --git a/include/clang/AST/StmtCXX.h b/include/clang/AST/StmtCXX.h index 77f81838e5eb6..34553741eb38e 100644 --- a/include/clang/AST/StmtCXX.h +++ b/include/clang/AST/StmtCXX.h @@ -62,21 +62,22 @@ public: /// CXXTryStmt - A C++ try block, including all handlers. /// -class CXXTryStmt : public Stmt { +class CXXTryStmt final : public Stmt, + private llvm::TrailingObjects<CXXTryStmt, Stmt *> { + + friend TrailingObjects; + friend class ASTStmtReader; + SourceLocation TryLoc; unsigned NumHandlers; + size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; } CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); - CXXTryStmt(EmptyShell Empty, unsigned numHandlers) : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } - Stmt const * const *getStmts() const { - return reinterpret_cast<Stmt const * const*>(this + 1); - } - Stmt **getStmts() { - return reinterpret_cast<Stmt **>(this + 1); - } + Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); } + Stmt **getStmts() { return getTrailingObjects<Stmt *>(); } public: static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, @@ -115,8 +116,6 @@ public: child_range children() { return child_range(getStmts(), getStmts() + getNumHandlers() + 1); } - - friend class ASTStmtReader; }; /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for @@ -210,7 +209,7 @@ public: } }; -/// \brief Representation of a Microsoft __if_exists or __if_not_exists +/// Representation of a Microsoft __if_exists or __if_not_exists /// statement with a dependent name. /// /// The __if_exists statement can be used to include a sequence of statements @@ -257,25 +256,25 @@ public: QualifierLoc(QualifierLoc), NameInfo(NameInfo), SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } - /// \brief Retrieve the location of the __if_exists or __if_not_exists + /// Retrieve the location of the __if_exists or __if_not_exists /// keyword. SourceLocation getKeywordLoc() const { return KeywordLoc; } - /// \brief Determine whether this is an __if_exists statement. + /// Determine whether this is an __if_exists statement. bool isIfExists() const { return IsIfExists; } - /// \brief Determine whether this is an __if_exists statement. + /// Determine whether this is an __if_exists statement. bool isIfNotExists() const { return !IsIfExists; } - /// \brief Retrieve the nested-name-specifier that qualifies this name, if + /// Retrieve the nested-name-specifier that qualifies this name, if /// any. NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } - /// \brief Retrieve the name of the entity we're testing for, along with + /// Retrieve the name of the entity we're testing for, along with /// location information DeclarationNameInfo getNameInfo() const { return NameInfo; } - /// \brief Retrieve the compound statement that will be included in the + /// Retrieve the compound statement that will be included in the /// program only if the existence of the symbol matches the initial keyword. CompoundStmt *getSubStmt() const { return reinterpret_cast<CompoundStmt *>(SubStmt); @@ -293,7 +292,7 @@ public: } }; -/// \brief Represents the body of a coroutine. This wraps the normal function +/// Represents the body of a coroutine. This wraps the normal function /// body and holds the additional semantic context required to set up and tear /// down the coroutine frame. class CoroutineBodyStmt final @@ -355,7 +354,7 @@ public: return getPromiseDecl()->getType()->isDependentType(); } - /// \brief Retrieve the body of the coroutine as written. This will be either + /// Retrieve the body of the coroutine as written. This will be either /// a CompoundStmt or a TryStmt. Stmt *getBody() const { return getStoredStmts()[SubStmt::Body]; @@ -418,7 +417,7 @@ public: } }; -/// \brief Represents a 'co_return' statement in the C++ Coroutines TS. +/// Represents a 'co_return' statement in the C++ Coroutines TS. /// /// This statament models the initialization of the coroutine promise /// (encapsulating the eventual notional return value) from an expression @@ -451,11 +450,11 @@ public: SourceLocation getKeywordLoc() const { return CoreturnLoc; } - /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr + /// Retrieve the operand of the 'co_return' statement. Will be nullptr /// if none was specified. Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } - /// \brief Retrieve the promise call that results from this 'co_return' + /// Retrieve the promise call that results from this 'co_return' /// statement. Will be nullptr if either the coroutine has not yet been /// finalized or the coroutine has no eventual return type. Expr *getPromiseCall() const { diff --git a/include/clang/AST/StmtObjC.h b/include/clang/AST/StmtObjC.h index 5260b6985bf58..571ad76be8a9d 100644 --- a/include/clang/AST/StmtObjC.h +++ b/include/clang/AST/StmtObjC.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// \file -/// \brief Defines the Objective-C statement AST node classes. +/// Defines the Objective-C statement AST node classes. #ifndef LLVM_CLANG_AST_STMTOBJC_H #define LLVM_CLANG_AST_STMTOBJC_H @@ -18,7 +18,7 @@ namespace clang { -/// \brief Represents Objective-C's collection statement. +/// Represents Objective-C's collection statement. /// /// This is represented as 'for (element 'in' collection-expression)' stmt. class ObjCForCollectionStmt : public Stmt { @@ -70,7 +70,7 @@ public: } }; -/// \brief Represents Objective-C's \@catch statement. +/// Represents Objective-C's \@catch statement. class ObjCAtCatchStmt : public Stmt { private: VarDecl *ExceptionDecl; @@ -116,7 +116,7 @@ public: child_range children() { return child_range(&Body, &Body + 1); } }; -/// \brief Represents Objective-C's \@finally statement +/// Represents Objective-C's \@finally statement class ObjCAtFinallyStmt : public Stmt { SourceLocation AtFinallyLoc; Stmt *AtFinallyStmt; @@ -150,7 +150,7 @@ public: } }; -/// \brief Represents Objective-C's \@try ... \@catch ... \@finally statement. +/// Represents Objective-C's \@try ... \@catch ... \@finally statement. class ObjCAtTryStmt : public Stmt { private: // The location of the @ in the \@try. @@ -162,7 +162,7 @@ private: // Whether this statement has a \@finally statement. bool HasFinally : 1; - /// \brief Retrieve the statements that are stored after this \@try statement. + /// Retrieve the statements that are stored after this \@try statement. /// /// The order of the statements in memory follows the order in the source, /// with the \@try body first, followed by the \@catch statements (if any) @@ -189,38 +189,38 @@ public: static ObjCAtTryStmt *CreateEmpty(const ASTContext &Context, unsigned NumCatchStmts, bool HasFinally); - /// \brief Retrieve the location of the @ in the \@try. + /// Retrieve the location of the @ in the \@try. SourceLocation getAtTryLoc() const { return AtTryLoc; } void setAtTryLoc(SourceLocation Loc) { AtTryLoc = Loc; } - /// \brief Retrieve the \@try body. + /// Retrieve the \@try body. const Stmt *getTryBody() const { return getStmts()[0]; } Stmt *getTryBody() { return getStmts()[0]; } void setTryBody(Stmt *S) { getStmts()[0] = S; } - /// \brief Retrieve the number of \@catch statements in this try-catch-finally + /// Retrieve the number of \@catch statements in this try-catch-finally /// block. unsigned getNumCatchStmts() const { return NumCatchStmts; } - /// \brief Retrieve a \@catch statement. + /// Retrieve a \@catch statement. const ObjCAtCatchStmt *getCatchStmt(unsigned I) const { assert(I < NumCatchStmts && "Out-of-bounds @catch index"); return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - /// \brief Retrieve a \@catch statement. + /// Retrieve a \@catch statement. ObjCAtCatchStmt *getCatchStmt(unsigned I) { assert(I < NumCatchStmts && "Out-of-bounds @catch index"); return cast_or_null<ObjCAtCatchStmt>(getStmts()[I + 1]); } - /// \brief Set a particular catch statement. + /// Set a particular catch statement. void setCatchStmt(unsigned I, ObjCAtCatchStmt *S) { assert(I < NumCatchStmts && "Out-of-bounds @catch index"); getStmts()[I + 1] = S; } - /// \brief Retrieve the \@finally statement, if any. + /// Retrieve the \@finally statement, if any. const ObjCAtFinallyStmt *getFinallyStmt() const { if (!HasFinally) return nullptr; @@ -251,7 +251,7 @@ public: } }; -/// \brief Represents Objective-C's \@synchronized statement. +/// Represents Objective-C's \@synchronized statement. /// /// Example: /// \code @@ -309,7 +309,7 @@ public: } }; -/// \brief Represents Objective-C's \@throw statement. +/// Represents Objective-C's \@throw statement. class ObjCAtThrowStmt : public Stmt { SourceLocation AtThrowLoc; Stmt *Throw; @@ -341,7 +341,7 @@ public: child_range children() { return child_range(&Throw, &Throw+1); } }; -/// \brief Represents Objective-C's \@autoreleasepool Statement +/// Represents Objective-C's \@autoreleasepool Statement class ObjCAutoreleasePoolStmt : public Stmt { SourceLocation AtLoc; Stmt *SubStmt; diff --git a/include/clang/AST/StmtOpenMP.h b/include/clang/AST/StmtOpenMP.h index 66fb037fc33cb..84a35db938b06 100644 --- a/include/clang/AST/StmtOpenMP.h +++ b/include/clang/AST/StmtOpenMP.h @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief This file defines OpenMP AST classes for executable directives and +/// This file defines OpenMP AST classes for executable directives and /// clauses. /// //===----------------------------------------------------------------------===// @@ -27,28 +27,28 @@ namespace clang { // AST classes for directives. //===----------------------------------------------------------------------===// -/// \brief This is a basic class for representing single OpenMP executable +/// This is a basic class for representing single OpenMP executable /// directive. /// class OMPExecutableDirective : public Stmt { friend class ASTStmtReader; - /// \brief Kind of the directive. + /// Kind of the directive. OpenMPDirectiveKind Kind; - /// \brief Starting location of the directive (directive keyword). + /// Starting location of the directive (directive keyword). SourceLocation StartLoc; - /// \brief Ending location of the directive. + /// Ending location of the directive. SourceLocation EndLoc; - /// \brief Numbers of clauses. + /// Numbers of clauses. const unsigned NumClauses; - /// \brief Number of child expressions/stmts. + /// Number of child expressions/stmts. const unsigned NumChildren; - /// \brief Offset from this to the start of clauses. + /// Offset from this to the start of clauses. /// There are NumClauses pointers to clauses, they are followed by /// NumChildren pointers to child stmts/exprs (if the directive type /// requires an associated stmt, then it has to be the first of them). const unsigned ClausesOffset; - /// \brief Get the clauses storage. + /// Get the clauses storage. MutableArrayRef<OMPClause *> getClauses() { OMPClause **ClauseStorage = reinterpret_cast<OMPClause **>( reinterpret_cast<char *>(this) + ClausesOffset); @@ -56,7 +56,7 @@ class OMPExecutableDirective : public Stmt { } protected: - /// \brief Build instance of directive of class \a K. + /// Build instance of directive of class \a K. /// /// \param SC Statement class. /// \param K Kind of OpenMP directive. @@ -72,13 +72,13 @@ protected: NumChildren(NumChildren), ClausesOffset(llvm::alignTo(sizeof(T), alignof(OMPClause *))) {} - /// \brief Sets the list of variables for this clause. + /// Sets the list of variables for this clause. /// /// \param Clauses The list of clauses for the directive. /// void setClauses(ArrayRef<OMPClause *> Clauses); - /// \brief Set the associated statement for the directive. + /// Set the associated statement for the directive. /// /// /param S Associated statement. /// @@ -88,7 +88,7 @@ protected: } public: - /// \brief Iterates over a filtered subrange of clauses applied to a + /// Iterates over a filtered subrange of clauses applied to a /// directive. /// /// This iterator visits only clauses of type SpecificClause. @@ -164,45 +164,49 @@ public: return Clauses.begin() != Clauses.end(); } - /// \brief Returns starting location of directive kind. + /// Returns starting location of directive kind. SourceLocation getLocStart() const { return StartLoc; } - /// \brief Returns ending location of directive. + /// Returns ending location of directive. SourceLocation getLocEnd() const { return EndLoc; } - /// \brief Set starting location of directive kind. + /// Set starting location of directive kind. /// /// \param Loc New starting location of directive. /// void setLocStart(SourceLocation Loc) { StartLoc = Loc; } - /// \brief Set ending location of directive. + /// Set ending location of directive. /// /// \param Loc New ending location of directive. /// void setLocEnd(SourceLocation Loc) { EndLoc = Loc; } - /// \brief Get number of clauses. + /// Get number of clauses. unsigned getNumClauses() const { return NumClauses; } - /// \brief Returns specified clause. + /// Returns specified clause. /// /// \param i Number of clause. /// OMPClause *getClause(unsigned i) const { return clauses()[i]; } - /// \brief Returns true if directive has associated statement. + /// Returns true if directive has associated statement. bool hasAssociatedStmt() const { return NumChildren > 0; } - /// \brief Returns statement associated with the directive. - Stmt *getAssociatedStmt() const { + /// Returns statement associated with the directive. + const Stmt *getAssociatedStmt() const { assert(hasAssociatedStmt() && "no associated statement."); - return const_cast<Stmt *>(*child_begin()); + return *child_begin(); + } + Stmt *getAssociatedStmt() { + assert(hasAssociatedStmt() && "no associated statement."); + return *child_begin(); } - /// \brief Returns the captured statement associated with the + /// Returns the captured statement associated with the /// component region within the (combined) directive. // // \param RegionKind Component region kind. - CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const { + const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const { SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind()); assert(std::any_of( @@ -218,6 +222,25 @@ public: llvm_unreachable("Incorrect RegionKind specified for directive."); } + /// Get innermost captured statement for the construct. + CapturedStmt *getInnermostCapturedStmt() { + assert(hasAssociatedStmt() && getAssociatedStmt() && + "Must have associated statement."); + SmallVector<OpenMPDirectiveKind, 4> CaptureRegions; + getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind()); + assert(!CaptureRegions.empty() && + "At least one captured statement must be provided."); + auto *CS = cast<CapturedStmt>(getAssociatedStmt()); + for (unsigned Level = CaptureRegions.size(); Level > 1; --Level) + CS = cast<CapturedStmt>(CS->getCapturedStmt()); + return CS; + } + + const CapturedStmt *getInnermostCapturedStmt() const { + return const_cast<OMPExecutableDirective *>(this) + ->getInnermostCapturedStmt(); + } + OpenMPDirectiveKind getDirectiveKind() const { return Kind; } static bool classof(const Stmt *S) { @@ -229,7 +252,9 @@ public: if (!hasAssociatedStmt()) return child_range(child_iterator(), child_iterator()); Stmt **ChildStorage = reinterpret_cast<Stmt **>(getClauses().end()); - return child_range(ChildStorage, ChildStorage + NumChildren); + /// Do not mark all the special expression/statements as children, except + /// for the associated statement. + return child_range(ChildStorage, ChildStorage + 1); } ArrayRef<OMPClause *> clauses() { return getClauses(); } @@ -239,7 +264,7 @@ public: } }; -/// \brief This represents '#pragma omp parallel' directive. +/// This represents '#pragma omp parallel' directive. /// /// \code /// #pragma omp parallel private(a,b) reduction(+: c,d) @@ -250,10 +275,10 @@ public: /// class OMPParallelDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief true if the construct has inner cancel directive. + /// true if the construct has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive (directive keyword). /// \param EndLoc Ending Location of the directive. @@ -264,7 +289,7 @@ class OMPParallelDirective : public OMPExecutableDirective { StartLoc, EndLoc, NumClauses, 1), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -274,11 +299,11 @@ class OMPParallelDirective : public OMPExecutableDirective { 1), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -291,7 +316,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - /// \brief Creates an empty directive with the place for \a N clauses. + /// Creates an empty directive with the place for \a N clauses. /// /// \param C AST context. /// \param NumClauses Number of clauses. @@ -299,7 +324,7 @@ public: static OMPParallelDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -307,15 +332,15 @@ public: } }; -/// \brief This is a common base class for loop directives ('omp simd', 'omp +/// 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. + /// Number of collapsed loops as specified by 'collapse' clause. unsigned CollapsedNum; - /// \brief Offsets to the stored exprs. + /// Offsets to the stored exprs. /// This enumeration contains offsets to all the pointers to children /// expressions stored in OMPLoopDirective. /// The first 9 children are necessary for all the loop directives, @@ -372,21 +397,21 @@ class OMPLoopDirective : public OMPExecutableDirective { CombinedDistributeEnd = 28, }; - /// \brief Get the counters storage. + /// 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 private counters storage. + /// Get the private counters storage. MutableArrayRef<Expr *> getPrivateCounters() { Expr **Storage = reinterpret_cast<Expr **>(&*std::next( child_begin(), getArraysOffset(getDirectiveKind()) + CollapsedNum)); return MutableArrayRef<Expr *>(Storage, CollapsedNum); } - /// \brief Get the updates storage. + /// Get the updates storage. MutableArrayRef<Expr *> getInits() { Expr **Storage = reinterpret_cast<Expr **>( &*std::next(child_begin(), @@ -394,7 +419,7 @@ class OMPLoopDirective : public OMPExecutableDirective { return MutableArrayRef<Expr *>(Storage, CollapsedNum); } - /// \brief Get the updates storage. + /// Get the updates storage. MutableArrayRef<Expr *> getUpdates() { Expr **Storage = reinterpret_cast<Expr **>( &*std::next(child_begin(), @@ -402,7 +427,7 @@ class OMPLoopDirective : public OMPExecutableDirective { return MutableArrayRef<Expr *>(Storage, CollapsedNum); } - /// \brief Get the final counter updates storage. + /// Get the final counter updates storage. MutableArrayRef<Expr *> getFinals() { Expr **Storage = reinterpret_cast<Expr **>( &*std::next(child_begin(), @@ -411,7 +436,7 @@ class OMPLoopDirective : public OMPExecutableDirective { } protected: - /// \brief Build instance of loop directive of class \a Kind. + /// Build instance of loop directive of class \a Kind. /// /// \param SC Statement class. /// \param Kind Kind of OpenMP directive. @@ -431,7 +456,7 @@ protected: NumSpecialChildren), CollapsedNum(CollapsedNum) {} - /// \brief Offset to the start of children expression arrays. + /// Offset to the start of children expression arrays. static unsigned getArraysOffset(OpenMPDirectiveKind Kind) { if (isOpenMPLoopBoundSharingDirective(Kind)) return CombinedDistributeEnd; @@ -441,7 +466,7 @@ protected: return DefaultEnd; } - /// \brief Children number. + /// Children number. static unsigned numLoopChildren(unsigned CollapsedNum, OpenMPDirectiveKind Kind) { return getArraysOffset(Kind) + 5 * CollapsedNum; // Counters, @@ -606,72 +631,72 @@ public: /// Distribute Loop condition used when composing 'omp distribute' /// with 'omp for' in a same construct Expr *Cond; - /// Update of LowerBound for statically sheduled omp loops for + /// Update of LowerBound for statically scheduled omp loops for /// outer loop in combined constructs (e.g. 'distribute parallel for') Expr *NLB; - /// Update of UpperBound for statically sheduled omp loops for + /// Update of UpperBound for statically scheduled omp loops for /// outer loop in combined constructs (e.g. 'distribute parallel for') Expr *NUB; }; - /// \brief The expressions built for the OpenMP loop CodeGen for the + /// The expressions built for the OpenMP loop CodeGen for the /// whole collapsed loop nest. struct HelperExprs { - /// \brief Loop iteration variable. + /// Loop iteration variable. Expr *IterationVarRef; - /// \brief Loop last iteration number. + /// Loop last iteration number. Expr *LastIteration; - /// \brief Loop number of iterations. + /// Loop number of iterations. Expr *NumIterations; - /// \brief Calculation of last iteration. + /// Calculation of last iteration. Expr *CalcLastIteration; - /// \brief Loop pre-condition. + /// Loop pre-condition. Expr *PreCond; - /// \brief Loop condition. + /// Loop condition. Expr *Cond; - /// \brief Loop iteration variable init. + /// Loop iteration variable init. Expr *Init; - /// \brief Loop increment. + /// Loop increment. Expr *Inc; - /// \brief IsLastIteration - local flag variable passed to runtime. + /// IsLastIteration - local flag variable passed to runtime. Expr *IL; - /// \brief LowerBound - local variable passed to runtime. + /// LowerBound - local variable passed to runtime. Expr *LB; - /// \brief UpperBound - local variable passed to runtime. + /// UpperBound - local variable passed to runtime. Expr *UB; - /// \brief Stride - local variable passed to runtime. + /// Stride - local variable passed to runtime. Expr *ST; - /// \brief EnsureUpperBound -- expression UB = min(UB, NumIterations). + /// EnsureUpperBound -- expression UB = min(UB, NumIterations). Expr *EUB; - /// \brief Update of LowerBound for statically sheduled 'omp for' loops. + /// Update of LowerBound for statically scheduled 'omp for' loops. Expr *NLB; - /// \brief Update of UpperBound for statically sheduled 'omp for' loops. + /// Update of UpperBound for statically scheduled 'omp for' loops. Expr *NUB; - /// \brief PreviousLowerBound - local variable passed to runtime in the + /// PreviousLowerBound - local variable passed to runtime in the /// enclosing schedule or null if that does not apply. Expr *PrevLB; - /// \brief PreviousUpperBound - local variable passed to runtime in the + /// PreviousUpperBound - local variable passed to runtime in the /// enclosing schedule or null if that does not apply. Expr *PrevUB; - /// \brief DistInc - increment expression for distribute loop when found + /// DistInc - increment expression for distribute loop when found /// combined with a further loop level (e.g. in 'distribute parallel for') /// expression IV = IV + ST Expr *DistInc; - /// \brief PrevEUB - expression similar to EUB but to be used when loop + /// PrevEUB - expression similar to EUB but to be used when loop /// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for' /// when ensuring that the UB is either the calculated UB by the runtime or /// the end of the assigned distribute chunk) /// expression UB = min (UB, PrevUB) Expr *PrevEUB; - /// \brief Counters Loop counters. + /// Counters Loop counters. SmallVector<Expr *, 4> Counters; - /// \brief PrivateCounters Loop counters. + /// PrivateCounters Loop counters. SmallVector<Expr *, 4> PrivateCounters; - /// \brief Expressions for loop counters inits for CodeGen. + /// Expressions for loop counters inits for CodeGen. SmallVector<Expr *, 4> Inits; - /// \brief Expressions for loop counters update for CodeGen. + /// Expressions for loop counters update for CodeGen. SmallVector<Expr *, 4> Updates; - /// \brief Final loop counter values for GodeGen. + /// Final loop counter values for GodeGen. SmallVector<Expr *, 4> Finals; /// Init statement for all captured expressions. Stmt *PreInits; @@ -679,7 +704,7 @@ public: /// Expressions used when combining OpenMP loop pragmas DistCombinedHelperExprs DistCombinedFields; - /// \brief Check if all the expressions are built (does not check the + /// Check if all the expressions are built (does not check the /// worksharing ones). bool builtAll() { return IterationVarRef != nullptr && LastIteration != nullptr && @@ -687,7 +712,7 @@ public: Cond != nullptr && Init != nullptr && Inc != nullptr; } - /// \brief Initialize all the fields to null. + /// Initialize all the fields to null. /// \param Size Number of elements in the counters/finals/updates arrays. void clear(unsigned Size) { IterationVarRef = nullptr; @@ -732,7 +757,7 @@ public: } }; - /// \brief Get number of collapsed loops. + /// Get number of collapsed loops. unsigned getCollapsedNumber() const { return CollapsedNum; } Expr *getIterationVariable() const { @@ -899,9 +924,8 @@ public: } const Stmt *getBody() const { // This relies on the loop form is already checked by Sema. - const Stmt *Body = getAssociatedStmt()->IgnoreContainers(true); - while(const auto *CS = dyn_cast<CapturedStmt>(Body)) - Body = CS->getCapturedStmt(); + const Stmt *Body = + getInnermostCapturedStmt()->getCapturedStmt()->IgnoreContainers(); Body = cast<ForStmt>(Body)->getBody(); for (unsigned Cnt = 1; Cnt < CollapsedNum; ++Cnt) { Body = Body->IgnoreContainers(); @@ -969,7 +993,7 @@ public: } }; -/// \brief This represents '#pragma omp simd' directive. +/// This represents '#pragma omp simd' directive. /// /// \code /// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d) @@ -980,7 +1004,7 @@ public: /// class OMPSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -992,7 +1016,7 @@ class OMPSimdDirective : public OMPLoopDirective { : OMPLoopDirective(this, OMPSimdDirectiveClass, OMPD_simd, StartLoc, EndLoc, CollapsedNum, NumClauses) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -1003,7 +1027,7 @@ class OMPSimdDirective : public OMPLoopDirective { NumClauses) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1019,7 +1043,7 @@ public: Stmt *AssociatedStmt, const HelperExprs &Exprs); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -1034,7 +1058,7 @@ public: } }; -/// \brief This represents '#pragma omp for' directive. +/// This represents '#pragma omp for' directive. /// /// \code /// #pragma omp for private(a,b) reduction(+:c,d) @@ -1046,10 +1070,10 @@ public: class OMPForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief true if current directive has inner cancel directive. + /// true if current directive has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1062,7 +1086,7 @@ class OMPForDirective : public OMPLoopDirective { CollapsedNum, NumClauses), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -1072,11 +1096,11 @@ class OMPForDirective : public OMPLoopDirective { SourceLocation(), CollapsedNum, NumClauses), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1093,7 +1117,7 @@ public: Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -1103,7 +1127,7 @@ public: static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -1111,7 +1135,7 @@ public: } }; -/// \brief This represents '#pragma omp for simd' directive. +/// This represents '#pragma omp for simd' directive. /// /// \code /// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d) @@ -1122,7 +1146,7 @@ public: /// class OMPForSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1134,7 +1158,7 @@ class OMPForSimdDirective : public OMPLoopDirective { : OMPLoopDirective(this, OMPForSimdDirectiveClass, OMPD_for_simd, StartLoc, EndLoc, CollapsedNum, NumClauses) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -1145,7 +1169,7 @@ class OMPForSimdDirective : public OMPLoopDirective { NumClauses) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1160,7 +1184,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -1176,7 +1200,7 @@ public: } }; -/// \brief This represents '#pragma omp sections' directive. +/// This represents '#pragma omp sections' directive. /// /// \code /// #pragma omp sections private(a,b) reduction(+:c,d) @@ -1188,10 +1212,10 @@ public: class OMPSectionsDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief true if current directive has inner cancel directive. + /// true if current directive has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1203,7 +1227,7 @@ class OMPSectionsDirective : public OMPExecutableDirective { StartLoc, EndLoc, NumClauses, 1), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -1213,11 +1237,11 @@ class OMPSectionsDirective : public OMPExecutableDirective { 1), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1230,7 +1254,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -1239,7 +1263,7 @@ public: static OMPSectionsDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -1247,7 +1271,7 @@ public: } }; -/// \brief This represents '#pragma omp section' directive. +/// This represents '#pragma omp section' directive. /// /// \code /// #pragma omp section @@ -1256,10 +1280,10 @@ public: class OMPSectionDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief true if current directive has inner cancel directive. + /// true if current directive has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1269,7 +1293,7 @@ class OMPSectionDirective : public OMPExecutableDirective { StartLoc, EndLoc, 0, 1), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// explicit OMPSectionDirective() : OMPExecutableDirective(this, OMPSectionDirectiveClass, OMPD_section, @@ -1277,7 +1301,7 @@ class OMPSectionDirective : public OMPExecutableDirective { HasCancel(false) {} public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1290,16 +1314,16 @@ public: SourceLocation EndLoc, Stmt *AssociatedStmt, bool HasCancel); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell); - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -1307,7 +1331,7 @@ public: } }; -/// \brief This represents '#pragma omp single' directive. +/// This represents '#pragma omp single' directive. /// /// \code /// #pragma omp single private(a,b) copyprivate(c,d) @@ -1317,7 +1341,7 @@ public: /// class OMPSingleDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1328,7 +1352,7 @@ class OMPSingleDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPSingleDirectiveClass, OMPD_single, StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -1338,7 +1362,7 @@ class OMPSingleDirective : public OMPExecutableDirective { 1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1350,7 +1374,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -1364,7 +1388,7 @@ public: } }; -/// \brief This represents '#pragma omp master' directive. +/// This represents '#pragma omp master' directive. /// /// \code /// #pragma omp master @@ -1372,7 +1396,7 @@ public: /// class OMPMasterDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1381,14 +1405,14 @@ class OMPMasterDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, StartLoc, EndLoc, 0, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// explicit OMPMasterDirective() : OMPExecutableDirective(this, OMPMasterDirectiveClass, OMPD_master, SourceLocation(), SourceLocation(), 0, 1) {} public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1400,7 +1424,7 @@ public: SourceLocation EndLoc, Stmt *AssociatedStmt); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// @@ -1411,7 +1435,7 @@ public: } }; -/// \brief This represents '#pragma omp critical' directive. +/// This represents '#pragma omp critical' directive. /// /// \code /// #pragma omp critical @@ -1419,9 +1443,9 @@ public: /// class OMPCriticalDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Name of the directive. + /// Name of the directive. DeclarationNameInfo DirName; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param Name Name of the directive. /// \param StartLoc Starting location of the directive kind. @@ -1434,7 +1458,7 @@ class OMPCriticalDirective : public OMPExecutableDirective { StartLoc, EndLoc, NumClauses, 1), DirName(Name) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -1444,14 +1468,14 @@ class OMPCriticalDirective : public OMPExecutableDirective { 1), DirName() {} - /// \brief Set name of the directive. + /// Set name of the directive. /// /// \param Name Name of the directive. /// void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; } public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param Name Name of the directive. @@ -1465,7 +1489,7 @@ public: SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// \param NumClauses Number of clauses. @@ -1473,7 +1497,7 @@ public: static OMPCriticalDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Return name of the directive. + /// Return name of the directive. /// DeclarationNameInfo getDirectiveName() const { return DirName; } @@ -1482,7 +1506,7 @@ public: } }; -/// \brief This represents '#pragma omp parallel for' directive. +/// This represents '#pragma omp parallel for' directive. /// /// \code /// #pragma omp parallel for private(a,b) reduction(+:c,d) @@ -1494,10 +1518,10 @@ public: class OMPParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief true if current region has inner cancel directive. + /// true if current region has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1510,7 +1534,7 @@ class OMPParallelForDirective : public OMPLoopDirective { StartLoc, EndLoc, CollapsedNum, NumClauses), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -1521,11 +1545,11 @@ class OMPParallelForDirective : public OMPLoopDirective { NumClauses), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1541,7 +1565,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -1553,7 +1577,7 @@ public: unsigned CollapsedNum, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -1561,7 +1585,7 @@ public: } }; -/// \brief This represents '#pragma omp parallel for simd' directive. +/// This represents '#pragma omp parallel for simd' directive. /// /// \code /// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d) @@ -1573,7 +1597,7 @@ public: /// class OMPParallelForSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1586,7 +1610,7 @@ class OMPParallelForSimdDirective : public OMPLoopDirective { OMPD_parallel_for_simd, StartLoc, EndLoc, CollapsedNum, NumClauses) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -1598,7 +1622,7 @@ class OMPParallelForSimdDirective : public OMPLoopDirective { SourceLocation(), CollapsedNum, NumClauses) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1613,7 +1637,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -1630,7 +1654,7 @@ public: } }; -/// \brief This represents '#pragma omp parallel sections' directive. +/// This represents '#pragma omp parallel sections' directive. /// /// \code /// #pragma omp parallel sections private(a,b) reduction(+:c,d) @@ -1642,10 +1666,10 @@ public: class OMPParallelSectionsDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief true if current directive has inner cancel directive. + /// true if current directive has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1658,7 +1682,7 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective { NumClauses, 1), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -1668,11 +1692,11 @@ class OMPParallelSectionsDirective : public OMPExecutableDirective { SourceLocation(), NumClauses, 1), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1685,7 +1709,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -1694,7 +1718,7 @@ public: static OMPParallelSectionsDirective * CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -1702,7 +1726,7 @@ public: } }; -/// \brief This represents '#pragma omp task' directive. +/// This represents '#pragma omp task' directive. /// /// \code /// #pragma omp task private(a,b) final(d) @@ -1712,10 +1736,10 @@ public: /// class OMPTaskDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief true if this directive has inner cancel directive. + /// true if this directive has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1727,7 +1751,7 @@ class OMPTaskDirective : public OMPExecutableDirective { EndLoc, NumClauses, 1), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -1737,11 +1761,11 @@ class OMPTaskDirective : public OMPExecutableDirective { 1), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1755,7 +1779,7 @@ public: ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, bool HasCancel); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -1764,7 +1788,7 @@ public: static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -1772,7 +1796,7 @@ public: } }; -/// \brief This represents '#pragma omp taskyield' directive. +/// This represents '#pragma omp taskyield' directive. /// /// \code /// #pragma omp taskyield @@ -1780,7 +1804,7 @@ public: /// class OMPTaskyieldDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1789,14 +1813,14 @@ class OMPTaskyieldDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, StartLoc, EndLoc, 0, 0) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// explicit OMPTaskyieldDirective() : OMPExecutableDirective(this, OMPTaskyieldDirectiveClass, OMPD_taskyield, SourceLocation(), SourceLocation(), 0, 0) {} public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1805,7 +1829,7 @@ public: static OMPTaskyieldDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// @@ -1816,7 +1840,7 @@ public: } }; -/// \brief This represents '#pragma omp barrier' directive. +/// This represents '#pragma omp barrier' directive. /// /// \code /// #pragma omp barrier @@ -1824,7 +1848,7 @@ public: /// class OMPBarrierDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1833,14 +1857,14 @@ class OMPBarrierDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, StartLoc, EndLoc, 0, 0) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// explicit OMPBarrierDirective() : OMPExecutableDirective(this, OMPBarrierDirectiveClass, OMPD_barrier, SourceLocation(), SourceLocation(), 0, 0) {} public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1849,7 +1873,7 @@ public: static OMPBarrierDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// @@ -1860,7 +1884,7 @@ public: } }; -/// \brief This represents '#pragma omp taskwait' directive. +/// This represents '#pragma omp taskwait' directive. /// /// \code /// #pragma omp taskwait @@ -1868,7 +1892,7 @@ public: /// class OMPTaskwaitDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1877,14 +1901,14 @@ class OMPTaskwaitDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, StartLoc, EndLoc, 0, 0) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// explicit OMPTaskwaitDirective() : OMPExecutableDirective(this, OMPTaskwaitDirectiveClass, OMPD_taskwait, SourceLocation(), SourceLocation(), 0, 0) {} public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -1893,7 +1917,7 @@ public: static OMPTaskwaitDirective * Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// @@ -1973,7 +1997,7 @@ public: } }; -/// \brief This represents '#pragma omp flush' directive. +/// This represents '#pragma omp flush' directive. /// /// \code /// #pragma omp flush(a,b) @@ -1985,7 +2009,7 @@ public: /// FlushClause. class OMPFlushDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -1996,7 +2020,7 @@ class OMPFlushDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPFlushDirectiveClass, OMPD_flush, StartLoc, EndLoc, NumClauses, 0) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2006,7 +2030,7 @@ class OMPFlushDirective : public OMPExecutableDirective { 0) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2018,7 +2042,7 @@ public: SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -2032,7 +2056,7 @@ public: } }; -/// \brief This represents '#pragma omp ordered' directive. +/// This represents '#pragma omp ordered' directive. /// /// \code /// #pragma omp ordered @@ -2040,7 +2064,7 @@ public: /// class OMPOrderedDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2051,7 +2075,7 @@ class OMPOrderedDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPOrderedDirectiveClass, OMPD_ordered, StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2061,7 +2085,7 @@ class OMPOrderedDirective : public OMPExecutableDirective { 1) {} public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2073,7 +2097,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// \param NumClauses Number of clauses. @@ -2086,7 +2110,7 @@ public: } }; -/// \brief This represents '#pragma omp atomic' directive. +/// This represents '#pragma omp atomic' directive. /// /// \code /// #pragma omp atomic capture @@ -2095,7 +2119,7 @@ public: /// class OMPAtomicDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may + /// Used for 'atomic update' or 'atomic capture' constructs. They may /// have atomic expressions of forms /// \code /// x = x binop expr; @@ -2105,7 +2129,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// second. Required for correct codegen of non-associative operations (like /// << or >>). bool IsXLHSInRHSPart; - /// \brief Used for 'atomic update' or 'atomic capture' constructs. They may + /// Used for 'atomic update' or 'atomic capture' constructs. They may /// have atomic expressions of forms /// \code /// v = x; <update x>; @@ -2115,7 +2139,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { /// otherwise. bool IsPostfixUpdate; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2127,7 +2151,7 @@ class OMPAtomicDirective : public OMPExecutableDirective { StartLoc, EndLoc, NumClauses, 5), IsXLHSInRHSPart(false), IsPostfixUpdate(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2137,19 +2161,19 @@ class OMPAtomicDirective : public OMPExecutableDirective { 5), IsXLHSInRHSPart(false), IsPostfixUpdate(false) {} - /// \brief Set 'x' part of the associated expression/statement. + /// Set 'x' part of the associated expression/statement. void setX(Expr *X) { *std::next(child_begin()) = X; } - /// \brief Set helper expression of the form + /// Set helper expression of the form /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. void setUpdateExpr(Expr *UE) { *std::next(child_begin(), 2) = UE; } - /// \brief Set 'v' part of the associated expression/statement. + /// Set 'v' part of the associated expression/statement. void setV(Expr *V) { *std::next(child_begin(), 3) = V; } - /// \brief Set 'expr' part of the associated expression/statement. + /// Set 'expr' part of the associated expression/statement. void setExpr(Expr *E) { *std::next(child_begin(), 4) = E; } public: - /// \brief Creates directive with a list of \a Clauses and 'x', 'v' and 'expr' + /// 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'). /// @@ -2173,7 +2197,7 @@ public: ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V, Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -2182,12 +2206,12 @@ public: static OMPAtomicDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Get 'x' part of the associated expression/statement. + /// 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 helper expression of the form + /// Get helper expression of the form /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. Expr *getUpdateExpr() { @@ -2196,19 +2220,19 @@ public: const Expr *getUpdateExpr() const { return cast_or_null<Expr>(*std::next(child_begin(), 2)); } - /// \brief Return true if helper update expression has form + /// Return true if helper update expression has form /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'. bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; } - /// \brief Return true if 'v' expression must be updated to original value of + /// Return true if 'v' expression must be updated to original value of /// 'x', false if 'v' must be updated to the new value of 'x'. bool isPostfixUpdate() const { return IsPostfixUpdate; } - /// \brief Get 'v' part of the associated expression/statement. + /// Get 'v' part of the associated expression/statement. Expr *getV() { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } const Expr *getV() const { return cast_or_null<Expr>(*std::next(child_begin(), 3)); } - /// \brief Get 'expr' part of the associated expression/statement. + /// Get 'expr' part of the associated expression/statement. Expr *getExpr() { return cast_or_null<Expr>(*std::next(child_begin(), 4)); } const Expr *getExpr() const { return cast_or_null<Expr>(*std::next(child_begin(), 4)); @@ -2219,7 +2243,7 @@ public: } }; -/// \brief This represents '#pragma omp target' directive. +/// This represents '#pragma omp target' directive. /// /// \code /// #pragma omp target if(a) @@ -2229,7 +2253,7 @@ public: /// class OMPTargetDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2240,7 +2264,7 @@ class OMPTargetDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPTargetDirectiveClass, OMPD_target, StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2250,7 +2274,7 @@ class OMPTargetDirective : public OMPExecutableDirective { 1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2262,7 +2286,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -2276,7 +2300,7 @@ public: } }; -/// \brief This represents '#pragma omp target data' directive. +/// This represents '#pragma omp target data' directive. /// /// \code /// #pragma omp target data device(0) if(a) map(b[:]) @@ -2287,7 +2311,7 @@ public: /// class OMPTargetDataDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. @@ -2299,7 +2323,7 @@ class OMPTargetDataDirective : public OMPExecutableDirective { OMPD_target_data, StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2309,7 +2333,7 @@ class OMPTargetDataDirective : public OMPExecutableDirective { SourceLocation(), NumClauses, 1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2321,7 +2345,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a N clauses. + /// Creates an empty directive with the place for \a N clauses. /// /// \param C AST context. /// \param N The number of clauses. @@ -2334,7 +2358,7 @@ public: } }; -/// \brief This represents '#pragma omp target enter data' directive. +/// This represents '#pragma omp target enter data' directive. /// /// \code /// #pragma omp target enter data device(0) if(a) map(b[:]) @@ -2345,7 +2369,7 @@ public: /// class OMPTargetEnterDataDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. @@ -2357,7 +2381,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective { OMPD_target_enter_data, StartLoc, EndLoc, NumClauses, /*NumChildren=*/1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2368,7 +2392,7 @@ class OMPTargetEnterDataDirective : public OMPExecutableDirective { /*NumChildren=*/1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2380,7 +2404,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a N clauses. + /// Creates an empty directive with the place for \a N clauses. /// /// \param C AST context. /// \param N The number of clauses. @@ -2393,7 +2417,7 @@ public: } }; -/// \brief This represents '#pragma omp target exit data' directive. +/// This represents '#pragma omp target exit data' directive. /// /// \code /// #pragma omp target exit data device(0) if(a) map(b[:]) @@ -2404,7 +2428,7 @@ public: /// class OMPTargetExitDataDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. @@ -2416,7 +2440,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective { OMPD_target_exit_data, StartLoc, EndLoc, NumClauses, /*NumChildren=*/1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2427,7 +2451,7 @@ class OMPTargetExitDataDirective : public OMPExecutableDirective { /*NumChildren=*/1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2439,7 +2463,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a N clauses. + /// Creates an empty directive with the place for \a N clauses. /// /// \param C AST context. /// \param N The number of clauses. @@ -2452,7 +2476,7 @@ public: } }; -/// \brief This represents '#pragma omp target parallel' directive. +/// This represents '#pragma omp target parallel' directive. /// /// \code /// #pragma omp target parallel if(a) @@ -2462,7 +2486,7 @@ public: /// class OMPTargetParallelDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2474,7 +2498,7 @@ class OMPTargetParallelDirective : public OMPExecutableDirective { OMPD_target_parallel, StartLoc, EndLoc, NumClauses, /*NumChildren=*/1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2485,7 +2509,7 @@ class OMPTargetParallelDirective : public OMPExecutableDirective { /*NumChildren=*/1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2497,7 +2521,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -2511,7 +2535,7 @@ public: } }; -/// \brief This represents '#pragma omp target parallel for' directive. +/// This represents '#pragma omp target parallel for' directive. /// /// \code /// #pragma omp target parallel for private(a,b) reduction(+:c,d) @@ -2523,10 +2547,10 @@ public: class OMPTargetParallelForDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief true if current region has inner cancel directive. + /// true if current region has inner cancel directive. bool HasCancel; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2540,7 +2564,7 @@ class OMPTargetParallelForDirective : public OMPLoopDirective { CollapsedNum, NumClauses), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -2552,11 +2576,11 @@ class OMPTargetParallelForDirective : public OMPLoopDirective { SourceLocation(), CollapsedNum, NumClauses), HasCancel(false) {} - /// \brief Set cancel state. + /// Set cancel state. void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2572,7 +2596,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -2584,7 +2608,7 @@ public: unsigned CollapsedNum, EmptyShell); - /// \brief Return true if current directive has inner cancel directive. + /// Return true if current directive has inner cancel directive. bool hasCancel() const { return HasCancel; } static bool classof(const Stmt *T) { @@ -2592,7 +2616,7 @@ public: } }; -/// \brief This represents '#pragma omp teams' directive. +/// This represents '#pragma omp teams' directive. /// /// \code /// #pragma omp teams if(a) @@ -2602,7 +2626,7 @@ public: /// class OMPTeamsDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2613,7 +2637,7 @@ class OMPTeamsDirective : public OMPExecutableDirective { : OMPExecutableDirective(this, OMPTeamsDirectiveClass, OMPD_teams, StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -2623,7 +2647,7 @@ class OMPTeamsDirective : public OMPExecutableDirective { 1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2636,7 +2660,7 @@ public: ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -2650,7 +2674,7 @@ public: } }; -/// \brief This represents '#pragma omp cancellation point' directive. +/// This represents '#pragma omp cancellation point' directive. /// /// \code /// #pragma omp cancellation point for @@ -2660,7 +2684,7 @@ public: class OMPCancellationPointDirective : public OMPExecutableDirective { friend class ASTStmtReader; OpenMPDirectiveKind CancelRegion; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2670,7 +2694,7 @@ class OMPCancellationPointDirective : public OMPExecutableDirective { OMPD_cancellation_point, StartLoc, EndLoc, 0, 0), CancelRegion(OMPD_unknown) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// explicit OMPCancellationPointDirective() : OMPExecutableDirective(this, OMPCancellationPointDirectiveClass, @@ -2678,12 +2702,12 @@ class OMPCancellationPointDirective : public OMPExecutableDirective { SourceLocation(), 0, 0), CancelRegion(OMPD_unknown) {} - /// \brief Set cancel region for current cancellation point. + /// Set cancel region for current cancellation point. /// \param CR Cancellation region. void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; } public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2693,14 +2717,14 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C, EmptyShell); - /// \brief Get cancellation region for the current cancellation point. + /// Get cancellation region for the current cancellation point. OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; } static bool classof(const Stmt *T) { @@ -2708,7 +2732,7 @@ public: } }; -/// \brief This represents '#pragma omp cancel' directive. +/// This represents '#pragma omp cancel' directive. /// /// \code /// #pragma omp cancel for @@ -2718,7 +2742,7 @@ public: class OMPCancelDirective : public OMPExecutableDirective { friend class ASTStmtReader; OpenMPDirectiveKind CancelRegion; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2730,7 +2754,7 @@ class OMPCancelDirective : public OMPExecutableDirective { StartLoc, EndLoc, NumClauses, 0), CancelRegion(OMPD_unknown) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. explicit OMPCancelDirective(unsigned NumClauses) @@ -2739,12 +2763,12 @@ class OMPCancelDirective : public OMPExecutableDirective { 0), CancelRegion(OMPD_unknown) {} - /// \brief Set cancel region for current cancellation point. + /// Set cancel region for current cancellation point. /// \param CR Cancellation region. void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; } public: - /// \brief Creates directive. + /// Creates directive. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2755,7 +2779,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion); - /// \brief Creates an empty directive. + /// Creates an empty directive. /// /// \param C AST context. /// \param NumClauses Number of clauses. @@ -2763,7 +2787,7 @@ public: static OMPCancelDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell); - /// \brief Get cancellation region for the current cancellation point. + /// Get cancellation region for the current cancellation point. OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; } static bool classof(const Stmt *T) { @@ -2771,7 +2795,7 @@ public: } }; -/// \brief This represents '#pragma omp taskloop' directive. +/// This represents '#pragma omp taskloop' directive. /// /// \code /// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num) @@ -2782,7 +2806,7 @@ public: /// class OMPTaskLoopDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2794,7 +2818,7 @@ class OMPTaskLoopDirective : public OMPLoopDirective { : OMPLoopDirective(this, OMPTaskLoopDirectiveClass, OMPD_taskloop, StartLoc, EndLoc, CollapsedNum, NumClauses) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -2805,7 +2829,7 @@ class OMPTaskLoopDirective : public OMPLoopDirective { NumClauses) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2820,7 +2844,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -2836,7 +2860,7 @@ public: } }; -/// \brief This represents '#pragma omp taskloop simd' directive. +/// This represents '#pragma omp taskloop simd' directive. /// /// \code /// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num) @@ -2847,7 +2871,7 @@ public: /// class OMPTaskLoopSimdDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2860,7 +2884,7 @@ class OMPTaskLoopSimdDirective : public OMPLoopDirective { OMPD_taskloop_simd, StartLoc, EndLoc, CollapsedNum, NumClauses) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -2871,7 +2895,7 @@ class OMPTaskLoopSimdDirective : public OMPLoopDirective { CollapsedNum, NumClauses) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2886,7 +2910,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -2903,7 +2927,7 @@ public: } }; -/// \brief This represents '#pragma omp distribute' directive. +/// This represents '#pragma omp distribute' directive. /// /// \code /// #pragma omp distribute private(a,b) @@ -2914,7 +2938,7 @@ public: class OMPDistributeDirective : public OMPLoopDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -2927,7 +2951,7 @@ class OMPDistributeDirective : public OMPLoopDirective { StartLoc, EndLoc, CollapsedNum, NumClauses) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -2939,7 +2963,7 @@ class OMPDistributeDirective : public OMPLoopDirective { {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -2954,7 +2978,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. @@ -2970,7 +2994,7 @@ public: } }; -/// \brief This represents '#pragma omp target update' directive. +/// This represents '#pragma omp target update' directive. /// /// \code /// #pragma omp target update to(a) from(b) device(1) @@ -2981,7 +3005,7 @@ public: /// class OMPTargetUpdateDirective : public OMPExecutableDirective { friend class ASTStmtReader; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending Location of the directive. @@ -2993,7 +3017,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective { OMPD_target_update, StartLoc, EndLoc, NumClauses, 1) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param NumClauses Number of clauses. /// @@ -3003,7 +3027,7 @@ class OMPTargetUpdateDirective : public OMPExecutableDirective { SourceLocation(), NumClauses, 1) {} public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -3015,7 +3039,7 @@ public: Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt); - /// \brief Creates an empty directive with the place for \a NumClauses + /// Creates an empty directive with the place for \a NumClauses /// clauses. /// /// \param C AST context. @@ -3029,7 +3053,7 @@ public: } }; -/// \brief This represents '#pragma omp distribute parallel for' composite +/// This represents '#pragma omp distribute parallel for' composite /// directive. /// /// \code @@ -3043,7 +3067,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective { /// true if the construct has inner cancel directive. bool HasCancel = false; - /// \brief Build directive with the given start and end location. + /// Build directive with the given start and end location. /// /// \param StartLoc Starting location of the directive kind. /// \param EndLoc Ending location of the directive. @@ -3057,7 +3081,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective { OMPD_distribute_parallel_for, StartLoc, EndLoc, CollapsedNum, NumClauses), HasCancel(false) {} - /// \brief Build an empty directive. + /// Build an empty directive. /// /// \param CollapsedNum Number of collapsed nested loops. /// \param NumClauses Number of clauses. @@ -3073,7 +3097,7 @@ class OMPDistributeParallelForDirective : public OMPLoopDirective { void setHasCancel(bool Has) { HasCancel = Has; } public: - /// \brief Creates directive with a list of \a Clauses. + /// Creates directive with a list of \a Clauses. /// /// \param C AST context. /// \param StartLoc Starting location of the directive kind. @@ -3089,7 +3113,7 @@ public: unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel); - /// \brief Creates an empty directive with the place + /// Creates an empty directive with the place /// for \a NumClauses clauses. /// /// \param C AST context. diff --git a/include/clang/AST/StmtVisitor.h b/include/clang/AST/StmtVisitor.h index 98fa113274069..30bc257c7e795 100644 --- a/include/clang/AST/StmtVisitor.h +++ b/include/clang/AST/StmtVisitor.h @@ -195,7 +195,7 @@ template<typename ImplClass, typename RetTy=void, typename... ParamTys> class ConstStmtVisitor : public StmtVisitorBase<make_const_ptr, ImplClass, RetTy, ParamTys...> {}; -/// \brief This class implements a simple visitor for OMPClause +/// This class implements a simple visitor for OMPClause /// subclasses. template<class ImplClass, template <typename> class Ptr, typename RetTy> class OMPClauseVisitorBase { diff --git a/include/clang/AST/TemplateBase.h b/include/clang/AST/TemplateBase.h index 850250b9c0a21..a1920253de78a 100644 --- a/include/clang/AST/TemplateBase.h +++ b/include/clang/AST/TemplateBase.h @@ -47,12 +47,12 @@ struct PrintingPolicy; class TypeSourceInfo; class ValueDecl; -/// \brief Represents a template argument. +/// Represents a template argument. class TemplateArgument { public: - /// \brief The kind of template argument we're storing. + /// The kind of template argument we're storing. enum ArgKind { - /// \brief Represents an empty template argument, e.g., one that has not + /// Represents an empty template argument, e.g., one that has not /// been deduced. Null = 0, @@ -92,7 +92,7 @@ public: }; private: - /// \brief The kind of template argument we're storing. + /// The kind of template argument we're storing. struct DA { unsigned Kind; @@ -138,16 +138,16 @@ private: }; public: - /// \brief Construct an empty, invalid template argument. + /// Construct an empty, invalid template argument. constexpr TemplateArgument() : TypeOrValue({Null, 0}) {} - /// \brief Construct a template type argument. + /// Construct a template type argument. TemplateArgument(QualType T, bool isNullPtr = false) { TypeOrValue.Kind = isNullPtr ? NullPtr : Type; TypeOrValue.V = reinterpret_cast<uintptr_t>(T.getAsOpaquePtr()); } - /// \brief Construct a template argument that refers to a + /// Construct a template argument that refers to a /// declaration, which is either an external declaration or a /// template declaration. TemplateArgument(ValueDecl *D, QualType QT) { @@ -157,18 +157,18 @@ public: DeclArg.D = D; } - /// \brief Construct an integral constant template argument. The memory to + /// Construct an integral constant template argument. The memory to /// store the value is allocated with Ctx. TemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType Type); - /// \brief Construct an integral constant template argument with the same + /// Construct an integral constant template argument with the same /// value as Other but a different type. TemplateArgument(const TemplateArgument &Other, QualType Type) { Integer = Other.Integer; Integer.Type = Type.getAsOpaquePtr(); } - /// \brief Construct a template argument that is a template. + /// Construct a template argument that is a template. /// /// This form of template argument is generally used for template template /// parameters. However, the template name could be a dependent template @@ -182,7 +182,7 @@ public: TemplateArg.NumExpansions = 0; } - /// \brief Construct a template argument that is a template pack expansion. + /// Construct a template argument that is a template pack expansion. /// /// This form of template argument is generally used for template template /// parameters. However, the template name could be a dependent template @@ -202,7 +202,7 @@ public: TemplateArg.NumExpansions = 0; } - /// \brief Construct a template argument that is an expression. + /// Construct a template argument that is an expression. /// /// This form of template argument only occurs in template argument /// lists used for dependent types and for expression; it will not @@ -212,7 +212,7 @@ public: TypeOrValue.V = reinterpret_cast<uintptr_t>(E); } - /// \brief Construct a template argument that is a template argument pack. + /// Construct a template argument that is a template argument pack. /// /// We assume that storage for the template arguments provided /// outlives the TemplateArgument itself. @@ -226,40 +226,40 @@ public: static TemplateArgument getEmptyPack() { return TemplateArgument(None); } - /// \brief Create a new template argument pack by copying the given set of + /// Create a new template argument pack by copying the given set of /// template arguments. static TemplateArgument CreatePackCopy(ASTContext &Context, ArrayRef<TemplateArgument> Args); - /// \brief Return the kind of stored template argument. + /// Return the kind of stored template argument. ArgKind getKind() const { return (ArgKind)TypeOrValue.Kind; } - /// \brief Determine whether this template argument has no value. + /// Determine whether this template argument has no value. bool isNull() const { return getKind() == Null; } - /// \brief Whether this template argument is dependent on a template + /// Whether this template argument is dependent on a template /// parameter such that its result can change from one instantiation to /// another. bool isDependent() const; - /// \brief Whether this template argument is dependent on a template + /// Whether this template argument is dependent on a template /// parameter. bool isInstantiationDependent() const; - /// \brief Whether this template argument contains an unexpanded + /// Whether this template argument contains an unexpanded /// parameter pack. bool containsUnexpandedParameterPack() const; - /// \brief Determine whether this template argument is a pack expansion. + /// Determine whether this template argument is a pack expansion. bool isPackExpansion() const; - /// \brief Retrieve the type for a type template argument. + /// Retrieve the type for a type template argument. QualType getAsType() const { assert(getKind() == Type && "Unexpected kind"); return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); } - /// \brief Retrieve the declaration for a declaration non-type + /// Retrieve the declaration for a declaration non-type /// template argument. ValueDecl *getAsDecl() const { assert(getKind() == Declaration && "Unexpected kind"); @@ -271,19 +271,19 @@ public: return QualType::getFromOpaquePtr(DeclArg.QT); } - /// \brief Retrieve the type for null non-type template argument. + /// Retrieve the type for null non-type template argument. QualType getNullPtrType() const { assert(getKind() == NullPtr && "Unexpected kind"); return QualType::getFromOpaquePtr(reinterpret_cast<void*>(TypeOrValue.V)); } - /// \brief Retrieve the template name for a template name argument. + /// Retrieve the template name for a template name argument. TemplateName getAsTemplate() const { assert(getKind() == Template && "Unexpected kind"); return TemplateName::getFromVoidPointer(TemplateArg.Name); } - /// \brief Retrieve the template argument as a template name; if the argument + /// Retrieve the template argument as a template name; if the argument /// is a pack expansion, return the pattern as a template name. TemplateName getAsTemplateOrTemplatePattern() const { assert((getKind() == Template || getKind() == TemplateExpansion) && @@ -292,11 +292,11 @@ public: return TemplateName::getFromVoidPointer(TemplateArg.Name); } - /// \brief Retrieve the number of expansions that a template template argument + /// Retrieve the number of expansions that a template template argument /// expansion will produce, if known. Optional<unsigned> getNumTemplateExpansions() const; - /// \brief Retrieve the template argument as an integral value. + /// Retrieve the template argument as an integral value. // FIXME: Provide a way to read the integral data without copying the value. llvm::APSInt getAsIntegral() const { assert(getKind() == Integral && "Unexpected kind"); @@ -311,7 +311,7 @@ public: Integer.IsUnsigned); } - /// \brief Retrieve the type of the integral value. + /// Retrieve the type of the integral value. QualType getIntegralType() const { assert(getKind() == Integral && "Unexpected kind"); return QualType::getFromOpaquePtr(Integer.Type); @@ -322,70 +322,70 @@ public: Integer.Type = T.getAsOpaquePtr(); } - /// \brief If this is a non-type template argument, get its type. Otherwise, + /// If this is a non-type template argument, get its type. Otherwise, /// returns a null QualType. QualType getNonTypeTemplateArgumentType() const; - /// \brief Retrieve the template argument as an expression. + /// Retrieve the template argument as an expression. Expr *getAsExpr() const { assert(getKind() == Expression && "Unexpected kind"); return reinterpret_cast<Expr *>(TypeOrValue.V); } - /// \brief Iterator that traverses the elements of a template argument pack. + /// Iterator that traverses the elements of a template argument pack. using pack_iterator = const TemplateArgument *; - /// \brief Iterator referencing the first argument of a template argument + /// Iterator referencing the first argument of a template argument /// pack. pack_iterator pack_begin() const { assert(getKind() == Pack); return Args.Args; } - /// \brief Iterator referencing one past the last argument of a template + /// Iterator referencing one past the last argument of a template /// argument pack. pack_iterator pack_end() const { assert(getKind() == Pack); return Args.Args + Args.NumArgs; } - /// \brief Iterator range referencing all of the elements of a template + /// Iterator range referencing all of the elements of a template /// argument pack. ArrayRef<TemplateArgument> pack_elements() const { return llvm::makeArrayRef(pack_begin(), pack_end()); } - /// \brief The number of template arguments in the given template argument + /// The number of template arguments in the given template argument /// pack. unsigned pack_size() const { assert(getKind() == Pack); return Args.NumArgs; } - /// \brief Return the array of arguments in this template argument pack. + /// Return the array of arguments in this template argument pack. ArrayRef<TemplateArgument> getPackAsArray() const { assert(getKind() == Pack); return llvm::makeArrayRef(Args.Args, Args.NumArgs); } - /// \brief Determines whether two template arguments are superficially the + /// Determines whether two template arguments are superficially the /// same. bool structurallyEquals(const TemplateArgument &Other) const; - /// \brief When the template argument is a pack expansion, returns + /// When the template argument is a pack expansion, returns /// the pattern of the pack expansion. TemplateArgument getPackExpansionPattern() const; - /// \brief Print this template argument to the given output stream. + /// Print this template argument to the given output stream. void print(const PrintingPolicy &Policy, raw_ostream &Out) const; - /// \brief Debugging aid that dumps the template argument. + /// Debugging aid that dumps the template argument. void dump(raw_ostream &Out) const; - /// \brief Debugging aid that dumps the template argument to standard error. + /// Debugging aid that dumps the template argument to standard error. void dump() const; - /// \brief Used to insert TemplateArguments into FoldingSets. + /// Used to insert TemplateArguments into FoldingSets. void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context) const; }; @@ -478,7 +478,7 @@ public: Argument.getKind() == TemplateArgument::TemplateExpansion); } - /// \brief - Fetches the primary location of the argument. + /// - Fetches the primary location of the argument. SourceLocation getLocation() const { if (Argument.getKind() == TemplateArgument::Template || Argument.getKind() == TemplateArgument::TemplateExpansion) @@ -487,7 +487,7 @@ public: return getSourceRange().getBegin(); } - /// \brief - Fetches the full source range of the argument. + /// - Fetches the full source range of the argument. SourceRange getSourceRange() const LLVM_READONLY; const TemplateArgument &getArgument() const { @@ -588,7 +588,7 @@ public: } }; -/// \brief Represents an explicit template argument list in C++, e.g., +/// Represents an explicit template argument list in C++, e.g., /// the "<int>" in "sort<int>". /// This is safe to be used inside an AST node, in contrast with /// TemplateArgumentListInfo. @@ -602,16 +602,16 @@ private: ASTTemplateArgumentListInfo(const TemplateArgumentListInfo &List); public: - /// \brief The source location of the left angle bracket ('<'). + /// The source location of the left angle bracket ('<'). SourceLocation LAngleLoc; - /// \brief The source location of the right angle bracket ('>'). + /// The source location of the right angle bracket ('>'). SourceLocation RAngleLoc; - /// \brief The number of template arguments in TemplateArgs. + /// The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; - /// \brief Retrieve the template arguments + /// Retrieve the template arguments const TemplateArgumentLoc *getTemplateArgs() const { return getTrailingObjects<TemplateArgumentLoc>(); } @@ -628,7 +628,7 @@ public: Create(ASTContext &C, const TemplateArgumentListInfo &List); }; -/// \brief Represents an explicit template argument list in C++, e.g., +/// Represents an explicit template argument list in C++, e.g., /// the "<int>" in "sort<int>". /// /// It is intended to be used as a trailing object on AST nodes, and @@ -636,19 +636,19 @@ public: /// but expects the containing object to also provide storage for /// that. struct alignas(void *) ASTTemplateKWAndArgsInfo { - /// \brief The source location of the left angle bracket ('<'). + /// The source location of the left angle bracket ('<'). SourceLocation LAngleLoc; - /// \brief The source location of the right angle bracket ('>'). + /// The source location of the right angle bracket ('>'). SourceLocation RAngleLoc; - /// \brief The source location of the template keyword; this is used + /// The source location of the template keyword; this is used /// as part of the representation of qualified identifiers, such as /// S<T>::template apply<T>. Will be empty if this expression does /// not have a template keyword. SourceLocation TemplateKWLoc; - /// \brief The number of template arguments in TemplateArgs. + /// The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; void initializeFrom(SourceLocation TemplateKWLoc, diff --git a/include/clang/AST/TemplateName.h b/include/clang/AST/TemplateName.h index fb33cf58d7960..50549e1a0a6a3 100644 --- a/include/clang/AST/TemplateName.h +++ b/include/clang/AST/TemplateName.h @@ -39,7 +39,7 @@ class TemplateArgument; class TemplateDecl; class TemplateTemplateParmDecl; -/// \brief Implementation class used to describe either a set of overloaded +/// Implementation class used to describe either a set of overloaded /// template names or an already-substituted template template parameter pack. class UncommonTemplateNameStorage { protected: @@ -50,10 +50,10 @@ protected: }; struct BitsTag { - /// \brief A Kind. + /// A Kind. unsigned Kind : 2; - /// \brief The number of stored templates or template arguments, + /// The number of stored templates or template arguments, /// depending on which subclass we have. unsigned Size : 30; }; @@ -90,7 +90,7 @@ public: } }; -/// \brief A structure for storing the information associated with an +/// A structure for storing the information associated with an /// overloaded template name. class OverloadedTemplateStorage : public UncommonTemplateNameStorage { friend class ASTContext; @@ -112,7 +112,7 @@ public: iterator end() const { return getStorage() + size(); } }; -/// \brief A structure for storing an already-substituted template template +/// A structure for storing an already-substituted template template /// parameter pack. /// /// This kind of template names occurs when the parameter pack has been @@ -131,12 +131,12 @@ public: : UncommonTemplateNameStorage(SubstTemplateTemplateParmPack, Size), Parameter(Parameter), Arguments(Arguments) {} - /// \brief Retrieve the template template parameter pack being substituted. + /// Retrieve the template template parameter pack being substituted. TemplateTemplateParmDecl *getParameterPack() const { return Parameter; } - /// \brief Retrieve the template template argument pack with which this + /// Retrieve the template template argument pack with which this /// parameter was substituted. TemplateArgument getArgumentPack() const; @@ -148,7 +148,7 @@ public: const TemplateArgument &ArgPack); }; -/// \brief Represents a C++ template name within the type system. +/// Represents a C++ template name within the type system. /// /// A C++ template name refers to a template within the C++ type /// system. In most cases, a template name is simply a reference to a @@ -185,27 +185,27 @@ class TemplateName { explicit TemplateName(void *Ptr); public: - // \brief Kind of name that is actually stored. + // Kind of name that is actually stored. enum NameKind { - /// \brief A single template declaration. + /// A single template declaration. Template, - /// \brief A set of overloaded template declarations. + /// A set of overloaded template declarations. OverloadedTemplate, - /// \brief A qualified template name, where the qualification is kept + /// A qualified template name, where the qualification is kept /// to describe the source code as written. QualifiedTemplate, - /// \brief A dependent template name that has not been resolved to a + /// A dependent template name that has not been resolved to a /// template (or set of templates). DependentTemplate, - /// \brief A template template parameter that has been substituted + /// A template template parameter that has been substituted /// for some other template name. SubstTemplateTemplateParm, - /// \brief A template template parameter pack that has been substituted for + /// A template template parameter pack that has been substituted for /// a template template argument pack, but has not yet been expanded into /// individual arguments. SubstTemplateTemplateParmPack @@ -219,13 +219,13 @@ public: explicit TemplateName(QualifiedTemplateName *Qual); explicit TemplateName(DependentTemplateName *Dep); - /// \brief Determine whether this template name is NULL. + /// Determine whether this template name is NULL. bool isNull() const; - // \brief Get the kind of name that is actually stored. + // Get the kind of name that is actually stored. NameKind getKind() const; - /// \brief Retrieve the underlying template declaration that + /// Retrieve the underlying template declaration that /// this template name refers to, if known. /// /// \returns The template declaration that this template name refers @@ -234,7 +234,7 @@ public: /// set of function templates, returns NULL. TemplateDecl *getAsTemplateDecl() const; - /// \brief Retrieve the underlying, overloaded function template + /// Retrieve the underlying, overloaded function template // declarations that this template name refers to, if known. /// /// \returns The set of overloaded function templates that this template @@ -243,14 +243,14 @@ public: /// refers to a single template, returns NULL. OverloadedTemplateStorage *getAsOverloadedTemplate() const; - /// \brief Retrieve the substituted template template parameter, if + /// Retrieve the substituted template template parameter, if /// known. /// /// \returns The storage for the substituted template template parameter, /// if known. Otherwise, returns NULL. SubstTemplateTemplateParmStorage *getAsSubstTemplateTemplateParm() const; - /// \brief Retrieve the substituted template template parameter pack, if + /// Retrieve the substituted template template parameter pack, if /// known. /// /// \returns The storage for the substituted template template parameter pack, @@ -258,11 +258,11 @@ public: SubstTemplateTemplateParmPackStorage * getAsSubstTemplateTemplateParmPack() const; - /// \brief Retrieve the underlying qualified template name + /// Retrieve the underlying qualified template name /// structure, if any. QualifiedTemplateName *getAsQualifiedTemplateName() const; - /// \brief Retrieve the underlying dependent template name + /// Retrieve the underlying dependent template name /// structure, if any. DependentTemplateName *getAsDependentTemplateName() const; @@ -273,18 +273,18 @@ public: /// the template, including any default template arguments. TemplateName getNameToSubstitute() const; - /// \brief Determines whether this is a dependent template name. + /// Determines whether this is a dependent template name. bool isDependent() const; - /// \brief Determines whether this is a template name that somehow + /// Determines whether this is a template name that somehow /// depends on a template parameter. bool isInstantiationDependent() const; - /// \brief Determines whether this template name contains an + /// Determines whether this template name contains an /// unexpanded parameter pack (for C++0x variadic templates). bool containsUnexpandedParameterPack() const; - /// \brief Print the template name. + /// Print the template name. /// /// \param OS the output stream to which the template name will be /// printed. @@ -295,10 +295,10 @@ public: void print(raw_ostream &OS, const PrintingPolicy &Policy, bool SuppressNNS = false) const; - /// \brief Debugging aid that dumps the template name. + /// Debugging aid that dumps the template name. void dump(raw_ostream &OS) const; - /// \brief Debugging aid that dumps the template name to standard + /// Debugging aid that dumps the template name to standard /// error. void dump() const; @@ -306,10 +306,10 @@ public: ID.AddPointer(Storage.getOpaqueValue()); } - /// \brief Retrieve the template name as a void pointer. + /// Retrieve the template name as a void pointer. void *getAsVoidPointer() const { return Storage.getOpaqueValue(); } - /// \brief Build a template name from a void pointer. + /// Build a template name from a void pointer. static TemplateName getFromVoidPointer(void *Ptr) { return TemplateName(Ptr); } @@ -320,7 +320,7 @@ public: const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, TemplateName N); -/// \brief A structure for storing the information associated with a +/// A structure for storing the information associated with a /// substituted template template parameter. class SubstTemplateTemplateParmStorage : public UncommonTemplateNameStorage, public llvm::FoldingSetNode { @@ -352,7 +352,7 @@ inline TemplateName TemplateName::getUnderlying() const { return *this; } -/// \brief Represents a template name that was expressed as a +/// Represents a template name that was expressed as a /// qualified name. /// /// This kind of template name refers to a template name that was @@ -366,7 +366,7 @@ inline TemplateName TemplateName::getUnderlying() const { class QualifiedTemplateName : public llvm::FoldingSetNode { friend class ASTContext; - /// \brief The nested name specifier that qualifies the template name. + /// The nested name specifier that qualifies the template name. /// /// The bit is used to indicate whether the "template" keyword was /// present before the template name itself. Note that the @@ -375,7 +375,7 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { /// this name with DependentTemplateName). llvm::PointerIntPair<NestedNameSpecifier *, 1> Qualifier; - /// \brief The template declaration or set of overloaded function templates + /// The template declaration or set of overloaded function templates /// that this qualified name refers to. TemplateDecl *Template; @@ -384,18 +384,18 @@ class QualifiedTemplateName : public llvm::FoldingSetNode { : Qualifier(NNS, TemplateKeyword? 1 : 0), Template(Template) {} public: - /// \brief Return the nested name specifier that qualifies this name. + /// Return the nested name specifier that qualifies this name. NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } - /// \brief Whether the template name was prefixed by the "template" + /// Whether the template name was prefixed by the "template" /// keyword. bool hasTemplateKeyword() const { return Qualifier.getInt(); } - /// \brief The template declaration that this qualified name refers + /// The template declaration that this qualified name refers /// to. TemplateDecl *getDecl() const { return Template; } - /// \brief The template declaration to which this qualified name + /// The template declaration to which this qualified name /// refers. TemplateDecl *getTemplateDecl() const { return Template; } @@ -411,7 +411,7 @@ public: } }; -/// \brief Represents a dependent template name that cannot be +/// Represents a dependent template name that cannot be /// resolved prior to template instantiation. /// /// This kind of template name refers to a dependent template name, @@ -422,7 +422,7 @@ public: class DependentTemplateName : public llvm::FoldingSetNode { friend class ASTContext; - /// \brief The nested name specifier that qualifies the template + /// The nested name specifier that qualifies the template /// name. /// /// The bit stored in this qualifier describes whether the \c Name field @@ -430,20 +430,20 @@ class DependentTemplateName : public llvm::FoldingSetNode { /// overloaded operator kind (when set). llvm::PointerIntPair<NestedNameSpecifier *, 1, bool> Qualifier; - /// \brief The dependent template name. + /// The dependent template name. union { - /// \brief The identifier template name. + /// The identifier template name. /// /// Only valid when the bit on \c Qualifier is clear. const IdentifierInfo *Identifier; - /// \brief The overloaded operator name. + /// The overloaded operator name. /// /// Only valid when the bit on \c Qualifier is set. OverloadedOperatorKind Operator; }; - /// \brief The canonical template name to which this dependent + /// The canonical template name to which this dependent /// template name refers. /// /// The canonical template name for a dependent template name is @@ -474,23 +474,23 @@ class DependentTemplateName : public llvm::FoldingSetNode { CanonicalTemplateName(Canon) {} public: - /// \brief Return the nested name specifier that qualifies this name. + /// Return the nested name specifier that qualifies this name. NestedNameSpecifier *getQualifier() const { return Qualifier.getPointer(); } - /// \brief Determine whether this template name refers to an identifier. + /// Determine whether this template name refers to an identifier. bool isIdentifier() const { return !Qualifier.getInt(); } - /// \brief Returns the identifier to which this template name refers. + /// Returns the identifier to which this template name refers. const IdentifierInfo *getIdentifier() const { assert(isIdentifier() && "Template name isn't an identifier?"); return Identifier; } - /// \brief Determine whether this template name refers to an overloaded + /// Determine whether this template name refers to an overloaded /// operator. bool isOverloadedOperator() const { return Qualifier.getInt(); } - /// \brief Return the overloaded operator to which this template name refers. + /// Return the overloaded operator to which this template name refers. OverloadedOperatorKind getOperator() const { assert(isOverloadedOperator() && "Template name isn't an overloaded operator?"); @@ -523,7 +523,7 @@ public: namespace llvm { -/// \brief The clang::TemplateName class is effectively a pointer. +/// The clang::TemplateName class is effectively a pointer. template<> struct PointerLikeTypeTraits<clang::TemplateName> { static inline void *getAsVoidPointer(clang::TemplateName TN) { diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 882878bb7e1e7..c692707847a69 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief C Language Family Type Representation +/// C Language Family Type Representation /// /// This file defines the clang::Type interface and subclasses, used to /// represent types for languages in the C family. @@ -30,6 +30,7 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/Visibility.h" #include "llvm/ADT/APInt.h" +#include "llvm/ADT/APSInt.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/None.h" @@ -56,6 +57,7 @@ namespace clang { class ExtQuals; class QualType; +class TagDecl; class Type; enum { @@ -445,7 +447,7 @@ public: } } - /// \brief Remove the qualifiers from the given set from this set. + /// Remove the qualifiers from the given set from this set. void removeQualifiers(Qualifiers Q) { // If the other set doesn't have any non-boolean qualifiers, just // bit-and the inverse in. @@ -508,7 +510,7 @@ public: (!other.hasUnaligned() || hasUnaligned()); } - /// \brief Determines if these qualifiers compatibly include another set of + /// Determines if these qualifiers compatibly include another set of /// qualifiers from the narrow perspective of Objective-C ARC lifetime. /// /// One set of Objective-C lifetime qualifiers compatibly includes the other @@ -528,7 +530,7 @@ public: return hasConst(); } - /// \brief Determine whether this set of qualifiers is a strict superset of + /// Determine whether this set of qualifiers is a strict superset of /// another set of qualifiers, not considering qualifier compatibility. bool isStrictSupersetOf(Qualifiers Other) const; @@ -554,7 +556,7 @@ public: return *this; } - /// \brief Compute the difference between two qualifier sets. + /// Compute the difference between two qualifier sets. friend Qualifiers operator-(Qualifiers L, Qualifiers R) { L -= R; return L; @@ -667,8 +669,7 @@ class QualType { const ExtQualsTypeCommonBase *getCommonPtr() const { assert(!isNull() && "Cannot retrieve a NULL type pointer"); - uintptr_t CommonPtrVal - = reinterpret_cast<uintptr_t>(Value.getOpaqueValue()); + auto CommonPtrVal = reinterpret_cast<uintptr_t>(Value.getOpaqueValue()); CommonPtrVal &= ~(uintptr_t)((1 << TypeAlignmentInBits) - 1); return reinterpret_cast<ExtQualsTypeCommonBase*>(CommonPtrVal); } @@ -720,69 +721,69 @@ public: return Value.getPointer().isNull(); } - /// \brief Determine whether this particular QualType instance has the + /// Determine whether this particular QualType instance has the /// "const" qualifier set, without looking through typedefs that may have /// added "const" at a different level. bool isLocalConstQualified() const { return (getLocalFastQualifiers() & Qualifiers::Const); } - /// \brief Determine whether this type is const-qualified. + /// Determine whether this type is const-qualified. bool isConstQualified() const; - /// \brief Determine whether this particular QualType instance has the + /// Determine whether this particular QualType instance has the /// "restrict" qualifier set, without looking through typedefs that may have /// added "restrict" at a different level. bool isLocalRestrictQualified() const { return (getLocalFastQualifiers() & Qualifiers::Restrict); } - /// \brief Determine whether this type is restrict-qualified. + /// Determine whether this type is restrict-qualified. bool isRestrictQualified() const; - /// \brief Determine whether this particular QualType instance has the + /// Determine whether this particular QualType instance has the /// "volatile" qualifier set, without looking through typedefs that may have /// added "volatile" at a different level. bool isLocalVolatileQualified() const { return (getLocalFastQualifiers() & Qualifiers::Volatile); } - /// \brief Determine whether this type is volatile-qualified. + /// Determine whether this type is volatile-qualified. bool isVolatileQualified() const; - /// \brief Determine whether this particular QualType instance has any + /// Determine whether this particular QualType instance has any /// qualifiers, without looking through any typedefs that might add /// qualifiers at a different level. bool hasLocalQualifiers() const { return getLocalFastQualifiers() || hasLocalNonFastQualifiers(); } - /// \brief Determine whether this type has any qualifiers. + /// Determine whether this type has any qualifiers. bool hasQualifiers() const; - /// \brief Determine whether this particular QualType instance has any + /// Determine whether this particular QualType instance has any /// "non-fast" qualifiers, e.g., those that are stored in an ExtQualType /// instance. bool hasLocalNonFastQualifiers() const { return Value.getPointer().is<const ExtQuals*>(); } - /// \brief Retrieve the set of qualifiers local to this particular QualType + /// Retrieve the set of qualifiers local to this particular QualType /// instance, not including any qualifiers acquired through typedefs or /// other sugar. Qualifiers getLocalQualifiers() const; - /// \brief Retrieve the set of qualifiers applied to this type. + /// Retrieve the set of qualifiers applied to this type. Qualifiers getQualifiers() const; - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// Retrieve the set of CVR (const-volatile-restrict) qualifiers /// local to this particular QualType instance, not including any qualifiers /// acquired through typedefs or other sugar. unsigned getLocalCVRQualifiers() const { return getLocalFastQualifiers(); } - /// \brief Retrieve the set of CVR (const-volatile-restrict) qualifiers + /// Retrieve the set of CVR (const-volatile-restrict) qualifiers /// applied to this type. unsigned getCVRQualifiers() const; @@ -790,7 +791,7 @@ public: return QualType::isConstant(*this, Ctx); } - /// \brief Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). + /// Determine whether this is a Plain Old Data (POD) type (C++ 3.9p10). bool isPODType(const ASTContext &Context) const; /// Return true if this is a POD type according to the rules of the C++98 @@ -799,7 +800,8 @@ public: /// Return true if this is a POD type according to the more relaxed rules /// of the C++11 standard, regardless of the current compilation's language. - /// (C++0x [basic.types]p9) + /// (C++0x [basic.types]p9). Note that, unlike + /// CXXRecordDecl::isCXX11StandardLayout, this takes DRs into account. bool isCXX11PODType(const ASTContext &Context) const; /// Return true if this is a trivial type per (C++0x [basic.types]p9) @@ -808,6 +810,13 @@ public: /// Return true if this is a trivially copyable type (C++0x [basic.types]p9) bool isTriviallyCopyableType(const ASTContext &Context) const; + + /// Returns true if it is a class and it might be dynamic. + bool mayBeDynamicClass() const; + + /// Returns true if it is not a class or if the class might not be dynamic. + bool mayBeNotDynamicClass() const; + // Don't promise in the API that anything besides 'const' can be // easily added. @@ -879,12 +888,12 @@ public: QualType getCanonicalType() const; - /// \brief Return this type with all of the instance-specific qualifiers + /// Return this type with all of the instance-specific qualifiers /// removed, but without removing any qualifiers that may have been applied /// through typedefs. QualType getLocalUnqualifiedType() const { return QualType(getTypePtr(), 0); } - /// \brief Retrieve the unqualified variant of the given type, + /// Retrieve the unqualified variant of the given type, /// removing as little sugar as possible. /// /// This routine looks through various kinds of sugar to find the @@ -915,17 +924,17 @@ public: /// ASTContext::getUnqualifiedArrayType. inline SplitQualType getSplitUnqualifiedType() const; - /// \brief Determine whether this type is more qualified than the other + /// Determine whether this type is more qualified than the other /// given type, requiring exact equality for non-CVR qualifiers. bool isMoreQualifiedThan(QualType Other) const; - /// \brief Determine whether this type is at least as qualified as the other + /// Determine whether this type is at least as qualified as the other /// given type, requiring exact equality for non-CVR qualifiers. bool isAtLeastAsQualifiedAs(QualType Other) const; QualType getNonReferenceType() const; - /// \brief Determine the type of a (typically non-lvalue) expression with the + /// Determine the type of a (typically non-lvalue) expression with the /// specified result type. /// /// This routine should be used for expressions for which the return type is @@ -951,7 +960,7 @@ public: return getSplitDesugaredType(*this); } - /// \brief Return the specified type with one level of "sugar" removed from + /// Return the specified type with one level of "sugar" removed from /// the type. /// /// This routine takes off the first typedef, typeof, etc. If the outer level @@ -1082,11 +1091,79 @@ public: // true when Type is objc's weak and weak is enabled but ARC isn't. bool isNonWeakInMRRWithObjCWeak(const ASTContext &Context) const; + enum PrimitiveDefaultInitializeKind { + /// The type does not fall into any of the following categories. Note that + /// this case is zero-valued so that values of this enum can be used as a + /// boolean condition for non-triviality. + PDIK_Trivial, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __strong qualifier. + PDIK_ARCStrong, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __weak qualifier. + PDIK_ARCWeak, + + /// The type is a struct containing a field whose type is not PCK_Trivial. + PDIK_Struct + }; + + /// Functions to query basic properties of non-trivial C struct types. + + /// Check if this is a non-trivial type that would cause a C struct + /// transitively containing this type to be non-trivial to default initialize + /// and return the kind. + PrimitiveDefaultInitializeKind + isNonTrivialToPrimitiveDefaultInitialize() const; + + enum PrimitiveCopyKind { + /// The type does not fall into any of the following categories. Note that + /// this case is zero-valued so that values of this enum can be used as a + /// boolean condition for non-triviality. + PCK_Trivial, + + /// The type would be trivial except that it is volatile-qualified. Types + /// that fall into one of the other non-trivial cases may additionally be + /// volatile-qualified. + PCK_VolatileTrivial, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __strong qualifier. + PCK_ARCStrong, + + /// The type is an Objective-C retainable pointer type that is qualified + /// with the ARC __weak qualifier. + PCK_ARCWeak, + + /// The type is a struct containing a field whose type is neither + /// PCK_Trivial nor PCK_VolatileTrivial. + /// Note that a C++ struct type does not necessarily match this; C++ copying + /// semantics are too complex to express here, in part because they depend + /// on the exact constructor or assignment operator that is chosen by + /// overload resolution to do the copy. + PCK_Struct + }; + + /// Check if this is a non-trivial type that would cause a C struct + /// transitively containing this type to be non-trivial to copy and return the + /// kind. + PrimitiveCopyKind isNonTrivialToPrimitiveCopy() const; + + /// Check if this is a non-trivial type that would cause a C struct + /// transitively containing this type to be non-trivial to destructively + /// move and return the kind. Destructive move in this context is a C++-style + /// move in which the source object is placed in a valid but unspecified state + /// after it is moved, as opposed to a truly destructive move in which the + /// source object is placed in an uninitialized state. + PrimitiveCopyKind isNonTrivialToPrimitiveDestructiveMove() const; + enum DestructionKind { DK_none, DK_cxx_destructor, DK_objc_strong_lifetime, - DK_objc_weak_lifetime + DK_objc_weak_lifetime, + DK_nontrivial_c_struct }; /// Returns a nonzero value if objects of this type require @@ -1204,7 +1281,7 @@ struct PointerLikeTypeTraits<clang::QualType> { namespace clang { -/// \brief Base class that is common to both the \c ExtQuals and \c Type +/// Base class that is common to both the \c ExtQuals and \c Type /// classes, which allows \c QualType to access the common fields between the /// two. class ExtQualsTypeCommonBase { @@ -1212,14 +1289,14 @@ class ExtQualsTypeCommonBase { friend class QualType; friend class Type; - /// \brief The "base" type of an extended qualifiers type (\c ExtQuals) or + /// The "base" type of an extended qualifiers type (\c ExtQuals) or /// a self-referential pointer (for \c Type). /// /// This pointer allows an efficient mapping from a QualType to its /// underlying type pointer. const Type *const BaseType; - /// \brief The canonical type of this type. A QualType. + /// The canonical type of this type. A QualType. QualType CanonicalType; ExtQualsTypeCommonBase(const Type *baseType, QualType canon) @@ -1300,25 +1377,25 @@ public: /// This determines whether a member function's "this" object can be an /// lvalue, rvalue, or neither. enum RefQualifierKind { - /// \brief No ref-qualifier was provided. + /// No ref-qualifier was provided. RQ_None = 0, - /// \brief An lvalue ref-qualifier was provided (\c &). + /// An lvalue ref-qualifier was provided (\c &). RQ_LValue, - /// \brief An rvalue ref-qualifier was provided (\c &&). + /// An rvalue ref-qualifier was provided (\c &&). RQ_RValue }; /// Which keyword(s) were used to create an AutoType. enum class AutoTypeKeyword { - /// \brief auto + /// auto Auto, - /// \brief decltype(auto) + /// decltype(auto) DecltypeAuto, - /// \brief __auto_type (GNU extension) + /// __auto_type (GNU extension) GNUAutoType }; @@ -1377,21 +1454,21 @@ private: /// Whether this type is a variably-modified type (C99 6.7.5). unsigned VariablyModified : 1; - /// \brief Whether this type contains an unexpanded parameter pack + /// Whether this type contains an unexpanded parameter pack /// (for C++11 variadic templates). unsigned ContainsUnexpandedParameterPack : 1; - /// \brief True if the cache (i.e. the bitfields here starting with + /// True if the cache (i.e. the bitfields here starting with /// 'Cache') is valid. mutable unsigned CacheValid : 1; - /// \brief Linkage of this type. + /// Linkage of this type. mutable unsigned CachedLinkage : 3; - /// \brief Whether this type involves and local or unnamed types. + /// Whether this type involves and local or unnamed types. mutable unsigned CachedLocalOrUnnamed : 1; - /// \brief Whether this type comes from an AST file. + /// Whether this type comes from an AST file. mutable unsigned FromAST : 1; bool isCacheValid() const { @@ -1446,7 +1523,7 @@ protected: /// Extra information which affects how the function is called, like /// regparm and the calling convention. - unsigned ExtInfo : 11; + unsigned ExtInfo : 12; /// Used only by FunctionProtoType, put here to pack with the /// other bitfields. @@ -1456,7 +1533,7 @@ protected: /// cv-qualifier-seq, [...], are part of the function type. unsigned TypeQuals : 4; - /// \brief The ref-qualifier associated with a \c FunctionProtoType. + /// The ref-qualifier associated with a \c FunctionProtoType. /// /// This is a value of type \c RefQualifierKind. unsigned RefQualifier : 2; @@ -1513,6 +1590,7 @@ protected: class VectorTypeBitfields { friend class VectorType; + friend class DependentVectorType; unsigned : NumTypeBits; @@ -1561,7 +1639,7 @@ protected: private: template <class T> friend class TypePropertyCache; - /// \brief Set whether this type comes from an AST file. + /// Set whether this type comes from an AST file. void setFromAST(bool V = true) const { TypeBits.FromAST = V; } @@ -1612,10 +1690,10 @@ public: TypeClass getTypeClass() const { return static_cast<TypeClass>(TypeBits.TC); } - /// \brief Whether this type comes from an AST file. + /// Whether this type comes from an AST file. bool isFromAST() const { return TypeBits.FromAST; } - /// \brief Whether this type is or contains an unexpanded parameter + /// Whether this type is or contains an unexpanded parameter /// pack, used to support C++0x variadic templates. /// /// A type that contains a parameter pack shall be expanded by the @@ -1653,7 +1731,7 @@ public: /// determine its size (e.g. void, or a fwd declared struct). Clients of this /// routine will need to determine if the size is actually required. /// - /// \brief Def If non-null, and the type refers to some kind of declaration + /// Def If non-null, and the type refers to some kind of declaration /// that can be completed (such as a C struct, C++ class, or Objective-C /// class), will be set to the declaration. bool isIncompleteType(NamedDecl **Def = nullptr) const; @@ -1664,7 +1742,7 @@ public: return !isFunctionType(); } - /// \brief Determine whether this type is an object type. + /// Determine whether this type is an object type. bool isObjectType() const { // C++ [basic.types]p8: // An object type is a (possibly cv-qualified) type that is not a @@ -1706,9 +1784,13 @@ public: /// isComplexIntegerType() can be used to test for complex integers. bool isIntegerType() const; // C99 6.2.5p17 (int, char, bool, enum) bool isEnumeralType() const; + + /// Determine whether this type is a scoped enumeration type. + bool isScopedEnumeralType() const; bool isBooleanType() const; bool isCharType() const; bool isWideCharType() const; + bool isChar8Type() const; bool isChar16Type() const; bool isChar32Type() const; bool isAnyCharacterType() const; @@ -1728,6 +1810,8 @@ public: bool isAnyComplexType() const; // C99 6.2.5p11 (complex) + Complex Int. bool isFloatingType() const; // C99 6.2.5p11 (real floating + complex) bool isHalfType() const; // OpenCL 6.1.1.1, NEON (IEEE 754-2008 half) + bool isFloat16Type() const; // C11 extension ISO/IEC TS 18661 + bool isFloat128Type() const; bool isRealType() const; // C99 6.2.5p17 (real floating + integer) bool isArithmeticType() const; // C99 6.2.5p18 (integer + floating) bool isVoidType() const; // C99 6.2.5p19 @@ -1857,7 +1941,7 @@ public: /// somehow depends on a template parameter (C++ [temp.dep.type]). bool isDependentType() const { return TypeBits.Dependent; } - /// \brief Determine whether this type is an instantiation-dependent type, + /// Determine whether this type is an instantiation-dependent type, /// meaning that the type involves a template parameter (even if the /// definition does not actually depend on the type substituted for that /// template parameter). @@ -1865,24 +1949,24 @@ public: return TypeBits.InstantiationDependent; } - /// \brief Determine whether this type is an undeduced type, meaning that + /// Determine whether this type is an undeduced type, meaning that /// it somehow involves a C++11 'auto' type or similar which has not yet been /// deduced. bool isUndeducedType() const; - /// \brief Whether this type is a variably-modified type (C99 6.7.5). + /// Whether this type is a variably-modified type (C99 6.7.5). bool isVariablyModifiedType() const { return TypeBits.VariablyModified; } - /// \brief Whether this type involves a variable-length array type + /// Whether this type involves a variable-length array type /// with a definite size. bool hasSizedVLAType() const; - /// \brief Whether this type is or contains a local or unnamed type. + /// Whether this type is or contains a local or unnamed type. bool hasUnnamedOrLocalType() const; bool isOverloadableType() const; - /// \brief Determine wither this type is a C++ elaborated-type-specifier. + /// Determine wither this type is a C++ elaborated-type-specifier. bool isElaboratedTypeSpecifier() const; bool canDecayToPointerType() const; @@ -1896,19 +1980,19 @@ public: /// purpose of GC'ability bool hasObjCPointerRepresentation() const; - /// \brief Determine whether this type has an integer representation + /// Determine whether this type has an integer representation /// of some sort, e.g., it is an integer type or a vector. bool hasIntegerRepresentation() const; - /// \brief Determine whether this type has an signed integer representation + /// Determine whether this type has an signed integer representation /// of some sort, e.g., it is an signed integer type or a vector. bool hasSignedIntegerRepresentation() const; - /// \brief Determine whether this type has an unsigned integer representation + /// Determine whether this type has an unsigned integer representation /// of some sort, e.g., it is an unsigned integer type or a vector. bool hasUnsignedIntegerRepresentation() const; - /// \brief Determine whether this type has a floating-point representation + /// Determine whether this type has a floating-point representation /// of some sort, e.g., it is a floating-point type or a vector thereof. bool hasFloatingRepresentation() const; @@ -1928,18 +2012,18 @@ public: const ObjCObjectPointerType *getAsObjCQualifiedClassType() const; const ObjCObjectType *getAsObjCQualifiedInterfaceType() const; - /// \brief Retrieves the CXXRecordDecl that this type refers to, either + /// Retrieves the CXXRecordDecl that this type refers to, either /// because the type is a RecordType or because it is the injected-class-name /// type of a class template or class template partial specialization. CXXRecordDecl *getAsCXXRecordDecl() const; - /// \brief Retrieves the TagDecl that this type refers to, either + /// 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. + /// CXXRecordDecl that the type refers to. /// /// If this is not a pointer or reference, or the type being pointed to does /// not refer to a CXXRecordDecl, returns NULL. @@ -2037,6 +2121,26 @@ public: /// enumeration types whose underlying type is a unsigned integer type. bool isUnsignedIntegerOrEnumerationType() const; + /// Return true if this is a fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. + bool isFixedPointType() const; + + /// Return true if this is a saturated fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned. + bool isSaturatedFixedPointType() const; + + /// Return true if this is a saturated fixed point type according to + /// ISO/IEC JTC1 SC22 WG14 N1169. This type can be signed or unsigned. + bool isUnsaturatedFixedPointType() const; + + /// Return true if this is a fixed point type that is signed according + /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated. + bool isSignedFixedPointType() const; + + /// Return true if this is a fixed point type that is unsigned according + /// to ISO/IEC JTC1 SC22 WG14 N1169. This type can also be saturated. + bool isUnsignedFixedPointType() const; + /// Return true if this is not a variable sized type, /// according to the rules of C99 6.7.5p3. It is not legal to call this on /// incomplete types. @@ -2113,16 +2217,16 @@ public: void dump(llvm::raw_ostream &OS) const; }; -/// \brief This will check for a TypedefType by removing any existing sugar +/// This will check for a TypedefType by removing any existing sugar /// until it reaches a TypedefType or a non-sugared type. template <> const TypedefType *Type::getAs() const; -/// \brief This will check for a TemplateSpecializationType by removing any +/// This will check for a TemplateSpecializationType by removing any /// existing sugar until it reaches a TemplateSpecializationType or a /// non-sugared type. template <> const TemplateSpecializationType *Type::getAs() const; -/// \brief This will check for an AttributedType by removing any existing sugar +/// This will check for an AttributedType by removing any existing sugar /// until it reaches an AttributedType or a non-sugared type. template <> const AttributedType *Type::getAs() const; @@ -2152,7 +2256,9 @@ public: #include "clang/AST/BuiltinTypes.def" }; -public: +private: + friend class ASTContext; // ASTContext creates these. + BuiltinType(Kind K) : Type(Builtin, QualType(), /*Dependent=*/(K == Dependent), /*InstantiationDependent=*/(K == Dependent), @@ -2161,6 +2267,7 @@ public: BuiltinTypeBits.Kind = K; } +public: Kind getKind() const { return static_cast<Kind>(BuiltinTypeBits.Kind); } StringRef getName(const PrintingPolicy &Policy) const; @@ -2637,13 +2744,13 @@ public: bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } - /// \brief Determine the number of bits required to address a member of + /// Determine the number of bits required to address a member of // an array with the given element type and number of elements. static unsigned getNumAddressingBits(const ASTContext &Context, QualType ElementType, const llvm::APInt &NumElements); - /// \brief Determine the maximum number of active bits that an array's size + /// Determine the maximum number of active bits that an array's size /// can require, which limits the maximum size of the array. static unsigned getMaxSizeBits(const ASTContext &Context); @@ -2774,7 +2881,7 @@ class DependentSizedArrayType : public ArrayType { const ASTContext &Context; - /// \brief An assignment expression that will instantiate to the + /// An assignment expression that will instantiate to the /// size of the array. /// /// The expression itself might be null, in which case the array @@ -2979,6 +3086,51 @@ public: } }; +/// Represents a vector type where either the type or size is dependent. +//// +/// For example: +/// \code +/// template<typename T, int Size> +/// class vector { +/// typedef T __attribute__((vector_size(Size))) type; +/// } +/// \endcode +class DependentVectorType : public Type, public llvm::FoldingSetNode { + friend class ASTContext; + + const ASTContext &Context; + QualType ElementType; + Expr *SizeExpr; + SourceLocation Loc; + + DependentVectorType(const ASTContext &Context, QualType ElementType, + QualType CanonType, Expr *SizeExpr, + SourceLocation Loc, VectorType::VectorKind vecKind); + +public: + Expr *getSizeExpr() const { return SizeExpr; } + QualType getElementType() const { return ElementType; } + SourceLocation getAttributeLoc() const { return Loc; } + VectorType::VectorKind getVectorKind() const { + return VectorType::VectorKind(VectorTypeBits.VecKind); + } + + bool isSugared() const { return false; } + QualType desugar() const { return QualType(this, 0); } + + static bool classof(const Type *T) { + return T->getTypeClass() == DependentVector; + } + + void Profile(llvm::FoldingSetNodeID &ID) { + Profile(ID, Context, getElementType(), getSizeExpr(), getVectorKind()); + } + + static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context, + QualType ElementType, const Expr *SizeExpr, + VectorType::VectorKind VecKind); +}; + /// ExtVectorType - Extended vector type. This type is created using /// __attribute__((ext_vector_type(n)), where "n" is the number of elements. /// Unlike vector_size, ext_vector_type is only allowed on typedef's. This @@ -3081,24 +3233,24 @@ public: class ExtInfo { friend class FunctionType; - // Feel free to rearrange or add bits, but if you go over 11, + // Feel free to rearrange or add bits, but if you go over 12, // you'll need to adjust both the Bits field below and // Type::FunctionTypeBitfields. - // | CC |noreturn|produces|nocallersavedregs|regparm| - // |0 .. 4| 5 | 6 | 7 |8 .. 10| + // | CC |noreturn|produces|nocallersavedregs|regparm|nocfcheck| + // |0 .. 4| 5 | 6 | 7 |8 .. 10| 11 | // // regparm is either 0 (no regparm attribute) or the regparm value+1. enum { CallConvMask = 0x1F }; enum { NoReturnMask = 0x20 }; enum { ProducesResultMask = 0x40 }; enum { NoCallerSavedRegsMask = 0x80 }; + enum { NoCfCheckMask = 0x800 }; enum { RegParmMask = ~(CallConvMask | NoReturnMask | ProducesResultMask | - NoCallerSavedRegsMask), + NoCallerSavedRegsMask | NoCfCheckMask), RegParmOffset = 8 }; // Assumed to be the last field - uint16_t Bits = CC_C; ExtInfo(unsigned Bits) : Bits(static_cast<uint16_t>(Bits)) {} @@ -3107,12 +3259,13 @@ public: // Constructor with no defaults. Use this when you know that you // have all the elements (when reading an AST file for example). ExtInfo(bool noReturn, bool hasRegParm, unsigned regParm, CallingConv cc, - bool producesResult, bool noCallerSavedRegs) { + bool producesResult, bool noCallerSavedRegs, bool NoCfCheck) { assert((!hasRegParm || regParm < 7) && "Invalid regparm value"); Bits = ((unsigned)cc) | (noReturn ? NoReturnMask : 0) | (producesResult ? ProducesResultMask : 0) | (noCallerSavedRegs ? NoCallerSavedRegsMask : 0) | - (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0); + (hasRegParm ? ((regParm + 1) << RegParmOffset) : 0) | + (NoCfCheck ? NoCfCheckMask : 0); } // Constructor with all defaults. Use when for example creating a @@ -3126,10 +3279,11 @@ public: bool getNoReturn() const { return Bits & NoReturnMask; } bool getProducesResult() const { return Bits & ProducesResultMask; } bool getNoCallerSavedRegs() const { return Bits & NoCallerSavedRegsMask; } + bool getNoCfCheck() const { return Bits & NoCfCheckMask; } bool getHasRegParm() const { return (Bits >> RegParmOffset) != 0; } unsigned getRegParm() const { - unsigned RegParm = Bits >> RegParmOffset; + unsigned RegParm = (Bits & RegParmMask) >> RegParmOffset; if (RegParm > 0) --RegParm; return RegParm; @@ -3168,6 +3322,13 @@ public: return ExtInfo(Bits & ~NoCallerSavedRegsMask); } + ExtInfo withNoCfCheck(bool noCfCheck) const { + if (noCfCheck) + return ExtInfo(Bits | NoCfCheckMask); + else + return ExtInfo(Bits & ~NoCfCheckMask); + } + ExtInfo withRegParm(unsigned RegParm) const { assert(RegParm < 7 && "Invalid regparm value"); return ExtInfo((Bits & ~RegParmMask) | @@ -3214,7 +3375,7 @@ public: bool isVolatile() const { return getTypeQuals() & Qualifiers::Volatile; } bool isRestrict() const { return getTypeQuals() & Qualifiers::Restrict; } - /// \brief Determine the type of an expression that calls a function of + /// Determine the type of an expression that calls a function of /// this type. QualType getCallResultType(const ASTContext &Context) const { return getReturnType().getNonLValueExprType(Context); @@ -3367,7 +3528,7 @@ public: /// Explicitly-specified list of exception types. ArrayRef<QualType> Exceptions; - /// Noexcept expression, if this is EST_ComputedNoexcept. + /// Noexcept expression, if this is a computed noexcept specification. Expr *NoexceptExpr = nullptr; /// The function whose exception specification this is, for @@ -3409,7 +3570,7 @@ public: private: friend class ASTContext; // ASTContext creates these. - /// \brief Determine whether there are any argument types that + /// Determine whether there are any argument types that /// contain an unexpanded parameter pack. static bool containsAnyUnexpandedParameterPack(const QualType *ArgArray, unsigned numArgs) { @@ -3464,26 +3625,41 @@ private: assert(hasExtParameterInfos()); // Find the end of the exception specification. - const char *ptr = reinterpret_cast<const char *>(exception_begin()); + const auto *ptr = reinterpret_cast<const char *>(exception_begin()); ptr += getExceptionSpecSize(); return reinterpret_cast<const ExtParameterInfo *>(ptr); } - size_t getExceptionSpecSize() const { - switch (getExceptionSpecType()) { - case EST_None: return 0; - case EST_DynamicNone: return 0; - case EST_MSAny: return 0; - case EST_BasicNoexcept: return 0; - case EST_Unparsed: return 0; - case EST_Dynamic: return getNumExceptions() * sizeof(QualType); - case EST_ComputedNoexcept: return sizeof(Expr*); - case EST_Uninstantiated: return 2 * sizeof(FunctionDecl*); - case EST_Unevaluated: return sizeof(FunctionDecl*); + static size_t getExceptionSpecSize(ExceptionSpecificationType EST, + unsigned NumExceptions) { + switch (EST) { + case EST_None: + case EST_DynamicNone: + case EST_MSAny: + case EST_BasicNoexcept: + case EST_Unparsed: + return 0; + + case EST_Dynamic: + return NumExceptions * sizeof(QualType); + + case EST_DependentNoexcept: + case EST_NoexceptFalse: + case EST_NoexceptTrue: + return sizeof(Expr *); + + case EST_Uninstantiated: + return 2 * sizeof(FunctionDecl *); + + case EST_Unevaluated: + return sizeof(FunctionDecl *); } llvm_unreachable("bad exception specification kind"); } + size_t getExceptionSpecSize() const { + return getExceptionSpecSize(getExceptionSpecType(), getNumExceptions()); + } public: unsigned getNumParams() const { return NumParams; } @@ -3507,7 +3683,7 @@ public: EPI.RefQualifier = getRefQualifier(); if (EPI.ExceptionSpec.Type == EST_Dynamic) { EPI.ExceptionSpec.Exceptions = exceptions(); - } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { + } else if (isComputedNoexcept(EPI.ExceptionSpec.Type)) { EPI.ExceptionSpec.NoexceptExpr = getNoexceptExpr(); } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { EPI.ExceptionSpec.SourceDecl = getExceptionSpecDecl(); @@ -3547,39 +3723,19 @@ public: /// spec. bool hasInstantiationDependentExceptionSpec() const; - /// Result type of getNoexceptSpec(). - enum NoexceptResult { - /// There is no noexcept specifier. - NR_NoNoexcept, - - /// The noexcept specifier has a bad expression. - NR_BadNoexcept, - - /// The noexcept specifier is dependent. - NR_Dependent, - - /// The noexcept specifier evaluates to false. - NR_Throw, - - /// The noexcept specifier evaluates to true. - NR_Nothrow - }; - - /// Get the meaning of the noexcept spec on this function, if any. - NoexceptResult getNoexceptSpec(const ASTContext &Ctx) const; unsigned getNumExceptions() const { return NumExceptions; } QualType getExceptionType(unsigned i) const { assert(i < NumExceptions && "Invalid exception number!"); return exception_begin()[i]; } Expr *getNoexceptExpr() const { - if (getExceptionSpecType() != EST_ComputedNoexcept) + if (!isComputedNoexcept(getExceptionSpecType())) return nullptr; // NoexceptExpr sits where the arguments end. return *reinterpret_cast<Expr *const *>(param_type_end()); } - /// \brief If this function type has an exception specification which hasn't + /// If this function type has an exception specification which hasn't /// been determined yet (either because it has not been evaluated or because /// it has not been instantiated), this is the function whose exception /// specification is represented by this type. @@ -3590,7 +3746,7 @@ public: return reinterpret_cast<FunctionDecl *const *>(param_type_end())[0]; } - /// \brief If this function type has an uninstantiated exception + /// If this function type has an uninstantiated exception /// specification, this is the function whose exception specification /// should be instantiated to find the exception specification for /// this type. @@ -3602,14 +3758,14 @@ public: /// Determine whether this function type has a non-throwing exception /// specification. - CanThrowResult canThrow(const ASTContext &Ctx) const; + CanThrowResult canThrow() const; /// Determine whether this function type has a non-throwing exception /// specification. If this depends on template arguments, returns /// \c ResultIfDependent. - bool isNothrow(const ASTContext &Ctx, bool ResultIfDependent = false) const { - return ResultIfDependent ? canThrow(Ctx) != CT_Can - : canThrow(Ctx) == CT_Cannot; + bool isNothrow(bool ResultIfDependent = false) const { + return ResultIfDependent ? canThrow() != CT_Can + : canThrow() == CT_Cannot; } bool isVariadic() const { return Variadic; } @@ -3719,7 +3875,7 @@ public: bool Canonical); }; -/// \brief Represents the dependent type named by a dependently-scoped +/// Represents the dependent type named by a dependently-scoped /// typename using declaration, e.g. /// using typename Base<T>::foo; /// @@ -3790,16 +3946,16 @@ protected: public: Expr *getUnderlyingExpr() const { return TOExpr; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const; - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == TypeOfExpr; } }; -/// \brief Internal representation of canonical, dependent +/// Internal representation of canonical, dependent /// `typeof(expr)` types. /// /// This class is used internally by the ASTContext to manage @@ -3839,10 +3995,10 @@ class TypeOfType : public Type { public: QualType getUnderlyingType() const { return TOType; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const { return getUnderlyingType(); } - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } static bool classof(const Type *T) { return T->getTypeClass() == TypeOf; } @@ -3862,16 +4018,16 @@ public: Expr *getUnderlyingExpr() const { return E; } QualType getUnderlyingType() const { return UnderlyingType; } - /// \brief Remove a single level of sugar. + /// Remove a single level of sugar. QualType desugar() const; - /// \brief Returns whether this type directly provides sugar. + /// Returns whether this type directly provides sugar. bool isSugared() const; static bool classof(const Type *T) { return T->getTypeClass() == Decltype; } }; -/// \brief Internal representation of canonical, dependent +/// Internal representation of canonical, dependent /// decltype(expr) types. /// /// This class is used internally by the ASTContext to manage @@ -3927,7 +4083,7 @@ public: } }; -/// \brief Internal representation of canonical, dependent +/// Internal representation of canonical, dependent /// __underlying_type(type) types. /// /// This class is used internally by the ASTContext to manage @@ -4054,6 +4210,7 @@ public: // No operand. attr_noreturn, + attr_nocf_check, attr_cdecl, attr_fastcall, attr_stdcall, @@ -4246,7 +4403,7 @@ public: } }; -/// \brief Represents the result of substituting a type for a template +/// Represents the result of substituting a type for a template /// type parameter. /// /// Within an instantiated template, all template type parameters have @@ -4297,7 +4454,7 @@ public: } }; -/// \brief Represents the result of substituting a set of types for a template +/// Represents the result of substituting a set of types for a template /// type parameter pack. /// /// When a pack expansion in the source code contains multiple parameter packs @@ -4312,14 +4469,14 @@ public: class SubstTemplateTypeParmPackType : public Type, public llvm::FoldingSetNode { friend class ASTContext; - /// \brief The original type parameter. + /// The original type parameter. const TemplateTypeParmType *Replaced; - /// \brief A pointer to the set of template arguments that this + /// A pointer to the set of template arguments that this /// parameter pack is instantiated with. const TemplateArgument *Arguments; - /// \brief The number of template arguments in \c Arguments. + /// The number of template arguments in \c Arguments. unsigned NumArguments; SubstTemplateTypeParmPackType(const TemplateTypeParmType *Param, @@ -4349,7 +4506,7 @@ public: } }; -/// \brief Common base class for placeholders for types that get replaced by +/// Common base class for placeholders for types that get replaced by /// placeholder type deduction: C++11 auto, C++14 decltype(auto), C++17 deduced /// class template types, and (eventually) constrained type names from the C++ /// Concepts TS. @@ -4382,7 +4539,7 @@ public: bool isSugared() const { return !isCanonicalUnqualified(); } QualType desugar() const { return getCanonicalTypeInternal(); } - /// \brief Get the type deduced for this placeholder type, or null if it's + /// Get the type deduced for this placeholder type, or null if it's /// either not been deduced or was deduced to a dependent type. QualType getDeducedType() const { return !isCanonicalUnqualified() ? getCanonicalTypeInternal() : QualType(); @@ -4397,7 +4554,7 @@ public: } }; -/// \brief Represents a C++11 auto or C++14 decltype(auto) type. +/// Represents a C++11 auto or C++14 decltype(auto) type. class AutoType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4433,7 +4590,7 @@ public: } }; -/// \brief Represents a C++17 deduced template specialization type. +/// Represents a C++17 deduced template specialization type. class DeducedTemplateSpecializationType : public DeducedType, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4470,7 +4627,7 @@ public: } }; -/// \brief Represents a type template specialization; the template +/// Represents a type template specialization; the template /// must be a class template, a type alias template, or a template /// template parameter. A template which cannot be resolved to one of /// these, e.g. because it is written with a dependent scope @@ -4490,7 +4647,7 @@ public: /// TemplateArguments, followed by a QualType representing the /// non-canonical aliased type when the template is a type alias /// template. -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) TemplateSpecializationType +class alignas(8) TemplateSpecializationType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4530,7 +4687,7 @@ public: return isa<InjectedClassNameType>(getCanonicalTypeInternal()); } - /// \brief Determine if this template specialization type is for a type alias + /// Determine if this template specialization type is for a type alias /// template that has been substituted. /// /// Nearly every template specialization type whose template is an alias @@ -4599,7 +4756,7 @@ public: } }; -/// \brief Print a template argument list, including the '<' and '>' +/// Print a template argument list, including the '<' and '>' /// enclosing the template arguments. void printTemplateArgumentList(raw_ostream &OS, ArrayRef<TemplateArgument> Args, @@ -4682,47 +4839,47 @@ public: } }; -/// \brief The kind of a tag type. +/// The kind of a tag type. enum TagTypeKind { - /// \brief The "struct" keyword. + /// The "struct" keyword. TTK_Struct, - /// \brief The "__interface" keyword. + /// The "__interface" keyword. TTK_Interface, - /// \brief The "union" keyword. + /// The "union" keyword. TTK_Union, - /// \brief The "class" keyword. + /// The "class" keyword. TTK_Class, - /// \brief The "enum" keyword. + /// The "enum" keyword. TTK_Enum }; -/// \brief The elaboration keyword that precedes a qualified type name or +/// The elaboration keyword that precedes a qualified type name or /// introduces an elaborated-type-specifier. enum ElaboratedTypeKeyword { - /// \brief The "struct" keyword introduces the elaborated-type-specifier. + /// The "struct" keyword introduces the elaborated-type-specifier. ETK_Struct, - /// \brief The "__interface" keyword introduces the elaborated-type-specifier. + /// The "__interface" keyword introduces the elaborated-type-specifier. ETK_Interface, - /// \brief The "union" keyword introduces the elaborated-type-specifier. + /// The "union" keyword introduces the elaborated-type-specifier. ETK_Union, - /// \brief The "class" keyword introduces the elaborated-type-specifier. + /// The "class" keyword introduces the elaborated-type-specifier. ETK_Class, - /// \brief The "enum" keyword introduces the elaborated-type-specifier. + /// The "enum" keyword introduces the elaborated-type-specifier. ETK_Enum, - /// \brief The "typename" keyword precedes the qualified type name, e.g., + /// The "typename" keyword precedes the qualified type name, e.g., /// \c typename T::type. ETK_Typename, - /// \brief No keyword precedes the qualified type name. + /// No keyword precedes the qualified type name. ETK_None }; @@ -4773,7 +4930,7 @@ public: static CannotCastToThisType classof(const Type *); }; -/// \brief Represents a type that was referred to using an elaborated type +/// Represents a type that was referred to using an elaborated type /// keyword, e.g., struct S, or via a qualified name, e.g., N::M::type, /// or both. /// @@ -4790,14 +4947,18 @@ class ElaboratedType : public TypeWithKeyword, public llvm::FoldingSetNode { /// The type that this qualified name refers to. QualType NamedType; + /// The (re)declaration of this tag type owned by this occurrence, or nullptr + /// if none. + TagDecl *OwnedTagDecl; + ElaboratedType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, - QualType NamedType, QualType CanonType) + QualType NamedType, QualType CanonType, TagDecl *OwnedTagDecl) : TypeWithKeyword(Keyword, Elaborated, CanonType, NamedType->isDependentType(), NamedType->isInstantiationDependentType(), NamedType->isVariablyModifiedType(), NamedType->containsUnexpandedParameterPack()), - NNS(NNS), NamedType(NamedType) { + NNS(NNS), NamedType(NamedType), OwnedTagDecl(OwnedTagDecl) { assert(!(Keyword == ETK_None && NNS == nullptr) && "ElaboratedType cannot have elaborated type keyword " "and name qualifier both null."); @@ -4818,15 +4979,21 @@ public: /// Returns whether this type directly provides sugar. bool isSugared() const { return true; } + /// Return the (re)declaration of this type owned by this occurrence of this + /// type, or nullptr if none. + TagDecl *getOwnedTagDecl() const { return OwnedTagDecl; } + void Profile(llvm::FoldingSetNodeID &ID) { - Profile(ID, getKeyword(), NNS, NamedType); + Profile(ID, getKeyword(), NNS, NamedType, OwnedTagDecl); } static void Profile(llvm::FoldingSetNodeID &ID, ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, QualType NamedType) { + NestedNameSpecifier *NNS, QualType NamedType, + TagDecl *OwnedTagDecl) { ID.AddInteger(Keyword); ID.AddPointer(NNS); NamedType.Profile(ID); + ID.AddPointer(OwnedTagDecl); } static bool classof(const Type *T) { @@ -4834,7 +5001,7 @@ public: } }; -/// \brief Represents a qualified type name for which the type name is +/// Represents a qualified type name for which the type name is /// dependent. /// /// DependentNameType represents a class of dependent types that involve a @@ -4849,10 +5016,10 @@ public: class DependentNameType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - /// \brief The nested name specifier containing the qualifier. + /// The nested name specifier containing the qualifier. NestedNameSpecifier *NNS; - /// \brief The type that this typename specifier refers to. + /// The type that this typename specifier refers to. const IdentifierInfo *Name; DependentNameType(ElaboratedTypeKeyword Keyword, NestedNameSpecifier *NNS, @@ -4898,7 +5065,7 @@ public: /// Represents a template specialization type whose template cannot be /// resolved, e.g. /// A<T>::template B<T> -class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType +class alignas(8) DependentTemplateSpecializationType : public TypeWithKeyword, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these @@ -4909,7 +5076,7 @@ class LLVM_ALIGNAS(/*alignof(uint64_t)*/ 8) DependentTemplateSpecializationType /// The identifier of the template. const IdentifierInfo *Name; - /// \brief The number of template arguments named in this class template + /// The number of template arguments named in this class template /// specialization. unsigned NumArgs; @@ -4931,12 +5098,12 @@ public: NestedNameSpecifier *getQualifier() const { return NNS; } const IdentifierInfo *getIdentifier() const { return Name; } - /// \brief Retrieve the template arguments. + /// Retrieve the template arguments. const TemplateArgument *getArgs() const { return getArgBuffer(); } - /// \brief Retrieve the number of template arguments. + /// Retrieve the number of template arguments. unsigned getNumArgs() const { return NumArgs; } const TemplateArgument &getArg(unsigned Idx) const; // in TemplateBase.h @@ -4969,7 +5136,7 @@ public: } }; -/// \brief Represents a pack expansion of types. +/// Represents a pack expansion of types. /// /// Pack expansions are part of C++11 variadic templates. A pack /// expansion contains a pattern, which itself contains one or more @@ -4994,10 +5161,10 @@ public: class PackExpansionType : public Type, public llvm::FoldingSetNode { friend class ASTContext; // ASTContext creates these - /// \brief The pattern of the pack expansion. + /// The pattern of the pack expansion. QualType Pattern; - /// \brief The number of expansions that this pack expansion will + /// The number of expansions that this pack expansion will /// generate when substituted (+1), or indicates that /// /// This field will only have a non-zero value when some of the parameter @@ -5015,12 +5182,12 @@ class PackExpansionType : public Type, public llvm::FoldingSetNode { NumExpansions(NumExpansions ? *NumExpansions + 1 : 0) {} public: - /// \brief Retrieve the pattern of this pack expansion, which is the + /// Retrieve the pattern of this pack expansion, which is the /// type that will be repeatedly instantiated when instantiating the /// pack expansion itself. QualType getPattern() const { return Pattern; } - /// \brief Retrieve the number of expansions that this pack expansion will + /// Retrieve the number of expansions that this pack expansion will /// generate, if known. Optional<unsigned> getNumExpansions() const { if (NumExpansions) @@ -5418,8 +5585,8 @@ public: inline ObjCInterfaceDecl *ObjCObjectType::getInterface() const { QualType baseType = getBaseType(); - while (const ObjCObjectType *ObjT = baseType->getAs<ObjCObjectType>()) { - if (const ObjCInterfaceType *T = dyn_cast<ObjCInterfaceType>(ObjT)) + while (const auto *ObjT = baseType->getAs<ObjCObjectType>()) { + if (const auto *T = dyn_cast<ObjCInterfaceType>(ObjT)) return T->getDecl(); baseType = ObjT->getBaseType(); @@ -5841,10 +6008,10 @@ inline Qualifiers::GC QualType::getObjCGCAttr() const { } inline FunctionType::ExtInfo getFunctionExtInfo(const Type &t) { - if (const PointerType *PT = t.getAs<PointerType>()) { - if (const FunctionType *FT = PT->getPointeeType()->getAs<FunctionType>()) + if (const auto *PT = t.getAs<PointerType>()) { + if (const auto *FT = PT->getPointeeType()->getAs<FunctionType>()) return FT->getExtInfo(); - } else if (const FunctionType *FT = t.getAs<FunctionType>()) + } else if (const auto *FT = t.getAs<FunctionType>()) return FT->getExtInfo(); return FunctionType::ExtInfo(); @@ -5889,7 +6056,7 @@ inline bool QualType::isAtLeastAsQualifiedAs(QualType other) const { /// analysis, the expression designates the object or function /// denoted by the reference, and the expression is an lvalue. inline QualType QualType::getNonReferenceType() const { - if (const ReferenceType *RefType = (*this)->getAs<ReferenceType>()) + if (const auto *RefType = (*this)->getAs<ReferenceType>()) return RefType->getPointeeType(); else return *this; @@ -5964,7 +6131,7 @@ inline bool Type::isRValueReferenceType() const { } inline bool Type::isFunctionPointerType() const { - if (const PointerType *T = getAs<PointerType>()) + if (const auto *T = getAs<PointerType>()) return T->getPointeeType()->isFunctionType(); else return false; @@ -5975,14 +6142,14 @@ inline bool Type::isMemberPointerType() const { } inline bool Type::isMemberFunctionPointerType() const { - if (const MemberPointerType* T = getAs<MemberPointerType>()) + if (const auto *T = getAs<MemberPointerType>()) return T->isMemberFunctionPointer(); else return false; } inline bool Type::isMemberDataPointerType() const { - if (const MemberPointerType* T = getAs<MemberPointerType>()) + if (const auto *T = getAs<MemberPointerType>()) return T->isMemberDataPointer(); else return false; @@ -6054,31 +6221,31 @@ inline bool Type::isAtomicType() const { } inline bool Type::isObjCQualifiedIdType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedIdType(); return false; } inline bool Type::isObjCQualifiedClassType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCQualifiedClassType(); return false; } inline bool Type::isObjCIdType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCIdType(); return false; } inline bool Type::isObjCClassType() const { - if (const ObjCObjectPointerType *OPT = getAs<ObjCObjectPointerType>()) + if (const auto *OPT = getAs<ObjCObjectPointerType>()) return OPT->isObjCClassType(); return false; } inline bool Type::isObjCSelType() const { - if (const PointerType *OPT = getAs<PointerType>()) + if (const auto *OPT = getAs<PointerType>()) return OPT->getPointeeType()->isSpecificBuiltinType(BuiltinType::ObjCSel); return false; } @@ -6141,13 +6308,13 @@ inline bool Type::isSpecificBuiltinType(unsigned K) const { } inline bool Type::isPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) return BT->isPlaceholderType(); return false; } inline const BuiltinType *Type::getAsPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) if (BT->isPlaceholderType()) return BT; return nullptr; @@ -6155,32 +6322,44 @@ inline const BuiltinType *Type::getAsPlaceholderType() const { inline bool Type::isSpecificPlaceholderType(unsigned K) const { assert(BuiltinType::isPlaceholderTypeKind((BuiltinType::Kind) K)); - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) return (BT->getKind() == (BuiltinType::Kind) K); return false; } inline bool Type::isNonOverloadPlaceholderType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(this)) + if (const auto *BT = dyn_cast<BuiltinType>(this)) return BT->isNonOverloadPlaceholderType(); return false; } inline bool Type::isVoidType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Void; return false; } inline bool Type::isHalfType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Half; // FIXME: Should we allow complex __fp16? Probably not. return false; } +inline bool Type::isFloat16Type() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Float16; + return false; +} + +inline bool Type::isFloat128Type() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) + return BT->getKind() == BuiltinType::Float128; + return false; +} + inline bool Type::isNullPtrType() const { - if (const BuiltinType *BT = getAs<BuiltinType>()) + if (const auto *BT = getAs<BuiltinType>()) return BT->getKind() == BuiltinType::NullPtr; return false; } @@ -6189,7 +6368,7 @@ bool IsEnumDeclComplete(EnumDecl *); bool IsEnumDeclScoped(EnumDecl *); inline bool Type::isIntegerType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) { @@ -6201,8 +6380,46 @@ inline bool Type::isIntegerType() const { return false; } +inline bool Type::isFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::ShortAccum && + BT->getKind() <= BuiltinType::SatULongFract; + } + return false; +} + +inline bool Type::isSaturatedFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return BT->getKind() >= BuiltinType::SatShortAccum && + BT->getKind() <= BuiltinType::SatULongFract; + } + return false; +} + +inline bool Type::isUnsaturatedFixedPointType() const { + return isFixedPointType() && !isSaturatedFixedPointType(); +} + +inline bool Type::isSignedFixedPointType() const { + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) { + return ((BT->getKind() >= BuiltinType::ShortAccum && + BT->getKind() <= BuiltinType::LongAccum) || + (BT->getKind() >= BuiltinType::ShortFract && + BT->getKind() <= BuiltinType::LongFract) || + (BT->getKind() >= BuiltinType::SatShortAccum && + BT->getKind() <= BuiltinType::SatLongAccum) || + (BT->getKind() >= BuiltinType::SatShortFract && + BT->getKind() <= BuiltinType::SatLongFract)); + } + return false; +} + +inline bool Type::isUnsignedFixedPointType() const { + return isFixedPointType() && !isSignedFixedPointType(); +} + inline bool Type::isScalarType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() > BuiltinType::Void && BT->getKind() <= BuiltinType::NullPtr; if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) @@ -6217,20 +6434,20 @@ inline bool Type::isScalarType() const { } inline bool Type::isIntegralOrEnumerationType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() >= BuiltinType::Bool && BT->getKind() <= BuiltinType::Int128; // Check for a complete enum type; incomplete enum types are not properly an // enumeration type in the sense required here. - if (const EnumType *ET = dyn_cast<EnumType>(CanonicalType)) + if (const auto *ET = dyn_cast<EnumType>(CanonicalType)) return IsEnumDeclComplete(ET->getDecl()); return false; } inline bool Type::isBooleanType() const { - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CanonicalType)) + if (const auto *BT = dyn_cast<BuiltinType>(CanonicalType)) return BT->getKind() == BuiltinType::Bool; return false; } @@ -6240,13 +6457,13 @@ inline bool Type::isUndeducedType() const { return DT && !DT->isDeduced(); } -/// \brief Determines whether this is a type for which one can define +/// Determines whether this is a type for which one can define /// an overloaded operator. inline bool Type::isOverloadableType() const { return isDependentType() || isRecordType() || isEnumeralType(); } -/// \brief Determines whether this type can decay to a pointer type. +/// Determines whether this type can decay to a pointer type. inline bool Type::canDecayToPointerType() const { return isFunctionType() || isArrayType(); } @@ -6307,7 +6524,7 @@ template <typename T> const T *Type::getAs() const { "ArrayType cannot be used with getAs!"); // If this is directly a T type, return it. - if (const T *Ty = dyn_cast<T>(this)) + if (const auto *Ty = dyn_cast<T>(this)) return Ty; // If the canonical form of this type isn't the right kind, reject it. @@ -6323,7 +6540,7 @@ template <typename T> const T *Type::getAsAdjusted() const { static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with getAsAdjusted!"); // If this is directly a T type, return it. - if (const T *Ty = dyn_cast<T>(this)) + if (const auto *Ty = dyn_cast<T>(this)) return Ty; // If the canonical form of this type isn't the right kind, reject it. @@ -6353,7 +6570,7 @@ template <typename T> const T *Type::getAsAdjusted() const { inline const ArrayType *Type::getAsArrayTypeUnsafe() const { // If this is directly an array type, return it. - if (const ArrayType *arr = dyn_cast<ArrayType>(this)) + if (const auto *arr = dyn_cast<ArrayType>(this)) return arr; // If the canonical form of this type isn't the right kind, reject it. @@ -6369,14 +6586,14 @@ template <typename T> const T *Type::castAs() const { static_assert(!TypeIsArrayType<T>::value, "ArrayType cannot be used with castAs!"); - if (const T *ty = dyn_cast<T>(this)) return ty; + if (const auto *ty = dyn_cast<T>(this)) return ty; assert(isa<T>(CanonicalType)); return cast<T>(getUnqualifiedDesugaredType()); } inline const ArrayType *Type::castAsArrayTypeUnsafe() const { assert(isa<ArrayType>(CanonicalType)); - if (const ArrayType *arr = dyn_cast<ArrayType>(this)) return arr; + if (const auto *arr = dyn_cast<ArrayType>(this)) return arr; return cast<ArrayType>(getUnqualifiedDesugaredType()); } @@ -6396,6 +6613,12 @@ QualType DecayedType::getPointeeType() const { return cast<PointerType>(Decayed)->getPointeeType(); } +// Get the decimal string representation of a fixed point type, represented +// as a scaled integer. +void FixedPointValueToString(SmallVectorImpl<char> &Str, + const llvm::APSInt &Val, + unsigned Scale, unsigned Radix); + } // namespace clang #endif // LLVM_CLANG_AST_TYPE_H diff --git a/include/clang/AST/TypeLoc.h b/include/clang/AST/TypeLoc.h index b805160a27807..25cd014efe5f4 100644 --- a/include/clang/AST/TypeLoc.h +++ b/include/clang/AST/TypeLoc.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::TypeLoc interface and its subclasses. +/// Defines the clang::TypeLoc interface and its subclasses. // //===----------------------------------------------------------------------===// @@ -49,7 +49,7 @@ class UnresolvedUsingTypenameDecl; class Class##TypeLoc; #include "clang/AST/TypeLocNodes.def" -/// \brief Base wrapper for a particular "section" of type source info. +/// Base wrapper for a particular "section" of type source info. /// /// A client should use the TypeLoc subclasses through castAs()/getAs() /// in order to get at the actual information. @@ -67,7 +67,7 @@ public: TypeLoc(const Type *ty, void *opaqueData) : Ty(ty), Data(opaqueData) {} - /// \brief Convert to the specified TypeLoc type, asserting that this TypeLoc + /// Convert to the specified TypeLoc type, asserting that this TypeLoc /// is of the desired type. /// /// \pre T::isKind(*this) @@ -80,21 +80,21 @@ public: return t; } - /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if + /// Convert to the specified TypeLoc type, returning a null TypeLoc if /// this TypeLoc is not of the desired type. template<typename T> T getAs() const { if (!T::isKind(*this)) - return T(); + return {}; T t; TypeLoc& tl = t; tl = *this; return t; } - /// \brief Convert to the specified TypeLoc type, returning a null TypeLoc if - /// this TypeLock is not of the desired type. It will consider type - /// adjustments from a type that wad written as a T to another type that is + /// Convert to the specified TypeLoc type, returning a null TypeLoc if + /// this TypeLoc is not of the desired type. It will consider type + /// adjustments from a type that was written as a T to another type that is /// still canonically a T (ignores parens, attributes, elaborated types, etc). template <typename T> T getAsAdjusted() const; @@ -118,14 +118,14 @@ public: bool isNull() const { return !Ty; } explicit operator bool() const { return Ty; } - /// \brief Returns the size of type source info data block for the given type. + /// Returns the size of type source info data block for the given type. static unsigned getFullDataSizeForType(QualType Ty); - /// \brief Returns the alignment of type source info data block for + /// Returns the alignment of type source info data block for /// the given type. static unsigned getLocalAlignmentForType(QualType Ty); - /// \brief Get the type for which this source info wrapper provides + /// Get the type for which this source info wrapper provides /// information. QualType getType() const { return QualType::getFromOpaquePtr(Ty); @@ -135,18 +135,18 @@ public: return QualType::getFromOpaquePtr(Ty).getTypePtr(); } - /// \brief Get the pointer where source information is stored. + /// Get the pointer where source information is stored. void *getOpaqueData() const { return Data; } - /// \brief Get the begin source location. + /// Get the begin source location. SourceLocation getBeginLoc() const; - /// \brief Get the end source location. + /// Get the end source location. SourceLocation getEndLoc() const; - /// \brief Get the full source range. + /// Get the full source range. SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(getBeginLoc(), getEndLoc()); } @@ -154,28 +154,28 @@ public: SourceLocation getLocStart() const LLVM_READONLY { return getBeginLoc(); } SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } - /// \brief Get the local source range. + /// Get the local source range. SourceRange getLocalSourceRange() const { return getLocalSourceRangeImpl(*this); } - /// \brief Returns the size of the type source info data block. + /// Returns the size of the type source info data block. unsigned getFullDataSize() const { return getFullDataSizeForType(getType()); } - /// \brief Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the + /// Get the next TypeLoc pointed by this TypeLoc, e.g for "int*" the /// TypeLoc is a PointerLoc and next TypeLoc is for "int". TypeLoc getNextTypeLoc() const { return getNextTypeLocImpl(*this); } - /// \brief Skips past any qualifiers, if this is qualified. + /// Skips past any qualifiers, if this is qualified. UnqualTypeLoc getUnqualifiedLoc() const; // implemented in this header TypeLoc IgnoreParens() const; - /// \brief Find a type with the location of an explicit type qualifier. + /// Find a type with the location of an explicit type qualifier. /// /// The result, if non-null, will be one of: /// QualifiedTypeLoc @@ -183,7 +183,7 @@ public: /// AttributedTypeLoc, for those type attributes that behave as qualifiers TypeLoc findExplicitQualifierLoc() const; - /// \brief Initializes this to state that every location in this + /// Initializes this to state that every location in this /// type is the given location. /// /// This method exists to provide a simple transition for code that @@ -192,14 +192,14 @@ public: initializeImpl(Context, *this, Loc); } - /// \brief Initializes this by copying its information from another + /// Initializes this by copying its information from another /// TypeLoc of the same type. void initializeFullCopy(TypeLoc Other) { assert(getType() == Other.getType()); copy(Other); } - /// \brief Initializes this by copying its information from another + /// Initializes this by copying its information from another /// TypeLoc of the same type. The given size must be the full data /// size. void initializeFullCopy(TypeLoc Other, unsigned Size) { @@ -235,13 +235,13 @@ private: static SourceRange getLocalSourceRangeImpl(TypeLoc TL); }; -/// \brief Return the TypeLoc for a type source info. +/// Return the TypeLoc for a type source info. inline TypeLoc TypeSourceInfo::getTypeLoc() const { // TODO: is this alignment already sufficient? return TypeLoc(Ty, const_cast<void*>(static_cast<const void*>(this + 1))); } -/// \brief Wrapper of type source information for a type with +/// Wrapper of type source information for a type with /// no direct qualifiers. class UnqualTypeLoc : public TypeLoc { public: @@ -264,7 +264,7 @@ private: } }; -/// \brief Wrapper of type source information for a type with +/// Wrapper of type source information for a type with /// non-trivial direct qualifiers. /// /// Currently, we intentionally do not provide source location for @@ -276,7 +276,7 @@ public: UnqualTypeLoc getUnqualifiedLoc() const { unsigned align = TypeLoc::getLocalAlignmentForType(QualType(getTypePtr(), 0)); - uintptr_t dataInt = reinterpret_cast<uintptr_t>(Data); + auto dataInt = reinterpret_cast<uintptr_t>(Data); dataInt = llvm::alignTo(dataInt, align); return UnqualTypeLoc(getTypePtr(), reinterpret_cast<void*>(dataInt)); } @@ -295,7 +295,7 @@ public: return getUnqualifiedLoc(); } - /// \brief Returns the size of the type source info data block that is + /// Returns the size of the type source info data block that is /// specific to this type. unsigned getLocalDataSize() const { // In fact, we don't currently preserve any location information @@ -303,7 +303,7 @@ public: return 0; } - /// \brief Returns the alignment of the type source info data block that is + /// Returns the alignment of the type source info data block that is /// specific to this type. unsigned getLocalDataAlignment() const { // We don't preserve any location information. @@ -429,7 +429,7 @@ protected: } void *getNonLocalData() const { - uintptr_t data = reinterpret_cast<uintptr_t>(Base::Data); + auto data = reinterpret_cast<uintptr_t>(Base::Data); data += asDerived()->getLocalDataSize(); data = llvm::alignTo(data, getNextTypeAlign()); return reinterpret_cast<void*>(data); @@ -503,7 +503,7 @@ struct TypeSpecLocInfo { SourceLocation NameLoc; }; -/// \brief A reasonable base class for TypeLocs that correspond to +/// A reasonable base class for TypeLocs that correspond to /// types that are written as a type-specifier. class TypeSpecTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, TypeSpecTypeLoc, @@ -541,7 +541,7 @@ struct BuiltinLocInfo { SourceRange BuiltinRange; }; -/// \brief Wrapper for source info for builtin types. +/// Wrapper for source info for builtin types. class BuiltinTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, BuiltinTypeLoc, BuiltinType, @@ -661,7 +661,7 @@ public: } }; -/// \brief Wrapper for source info for typedefs. +/// Wrapper for source info for typedefs. class TypedefTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TypedefTypeLoc, TypedefType> { @@ -671,7 +671,7 @@ public: } }; -/// \brief Wrapper for source info for injected class names of class +/// Wrapper for source info for injected class names of class /// templates. class InjectedClassNameTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, @@ -683,7 +683,7 @@ public: } }; -/// \brief Wrapper for source info for unresolved typename using decls. +/// Wrapper for source info for unresolved typename using decls. class UnresolvedUsingTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, UnresolvedUsingTypeLoc, @@ -694,7 +694,7 @@ public: } }; -/// \brief Wrapper for source info for tag types. Note that this only +/// Wrapper for source info for tag types. Note that this only /// records source info for the name itself; a type written 'struct foo' /// should be represented as an ElaboratedTypeLoc. We currently /// only do that when C++ is enabled because of the expense of @@ -705,7 +705,7 @@ class TagTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, public: TagDecl *getDecl() const { return getTypePtr()->getDecl(); } - /// \brief True if the tag was defined in this type specifier. + /// True if the tag was defined in this type specifier. bool isDefinition() const { TagDecl *D = getDecl(); return D->isCompleteDefinition() && @@ -713,7 +713,7 @@ public: } }; -/// \brief Wrapper for source info for record types. +/// Wrapper for source info for record types. class RecordTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, RecordTypeLoc, RecordType> { @@ -721,7 +721,7 @@ public: RecordDecl *getDecl() const { return getTypePtr()->getDecl(); } }; -/// \brief Wrapper for source info for enum types. +/// Wrapper for source info for enum types. class EnumTypeLoc : public InheritingConcreteTypeLoc<TagTypeLoc, EnumTypeLoc, EnumType> { @@ -729,7 +729,7 @@ public: EnumDecl *getDecl() const { return getTypePtr()->getDecl(); } }; -/// \brief Wrapper for template type parameters. +/// Wrapper for template type parameters. class TemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, TemplateTypeParmTypeLoc, @@ -828,14 +828,14 @@ public: } }; -/// \brief Wrapper for substituted template type parameters. +/// Wrapper for substituted template type parameters. class SubstTemplateTypeParmTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, SubstTemplateTypeParmTypeLoc, SubstTemplateTypeParmType> { }; - /// \brief Wrapper for substituted template type parameters. + /// Wrapper for substituted template type parameters. class SubstTemplateTypeParmPackTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, SubstTemplateTypeParmPackTypeLoc, @@ -855,7 +855,7 @@ struct AttributedLocInfo { SourceLocation AttrLoc; }; -/// \brief Type source information for an attributed type. +/// Type source information for an attributed type. class AttributedTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, AttributedTypeLoc, AttributedType, @@ -1114,7 +1114,7 @@ struct ObjCInterfaceLocInfo { SourceLocation NameEndLoc; }; -/// \brief Wrapper for source info for ObjC interfaces. +/// Wrapper for source info for ObjC interfaces. class ObjCInterfaceTypeLoc : public ConcreteTypeLoc<ObjCObjectTypeLoc, ObjCInterfaceTypeLoc, ObjCInterfaceType, @@ -1227,7 +1227,7 @@ public: } }; -/// \brief Wrapper for source info for pointers decayed from arrays and +/// Wrapper for source info for pointers decayed from arrays and /// functions. class DecayedTypeLoc : public InheritingConcreteTypeLoc< AdjustedTypeLoc, DecayedTypeLoc, DecayedType> { @@ -1267,7 +1267,7 @@ public: } }; -/// \brief Wrapper for source info for pointers. +/// Wrapper for source info for pointers. class PointerTypeLoc : public PointerLikeTypeLoc<PointerTypeLoc, PointerType> { public: @@ -1280,7 +1280,7 @@ public: } }; -/// \brief Wrapper for source info for block pointers. +/// Wrapper for source info for block pointers. class BlockPointerTypeLoc : public PointerLikeTypeLoc<BlockPointerTypeLoc, BlockPointerType> { public: @@ -1297,7 +1297,7 @@ struct MemberPointerLocInfo : public PointerLikeLocInfo { TypeSourceInfo *ClassTInfo; }; -/// \brief Wrapper for source info for member pointers. +/// Wrapper for source info for member pointers. class MemberPointerTypeLoc : public PointerLikeTypeLoc<MemberPointerTypeLoc, MemberPointerType, MemberPointerLocInfo> { @@ -1392,7 +1392,7 @@ struct FunctionLocInfo { SourceLocation LocalRangeEnd; }; -/// \brief Wrapper for source info for functions. +/// Wrapper for source info for functions. class FunctionTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, FunctionTypeLoc, FunctionType, @@ -1496,7 +1496,7 @@ public: setExceptionSpecRange(Loc); } - /// \brief Returns the size of the type source info data block that is + /// Returns the size of the type source info data block that is /// specific to this type. unsigned getExtraLocalDataSize() const { unsigned ExceptSpecSize = hasExceptionSpec() ? sizeof(SourceRange) : 0; @@ -1525,7 +1525,7 @@ struct ArrayLocInfo { Expr *Size; }; -/// \brief Wrapper for source info for arrays. +/// Wrapper for source info for arrays. class ArrayTypeLoc : public ConcreteTypeLoc<UnqualTypeLoc, ArrayTypeLoc, ArrayType, @@ -1670,7 +1670,7 @@ public: getLocalData()->NameLoc = Loc; } - /// \brief - Copy the location information from the given info. + /// - Copy the location information from the given info. void copy(TemplateSpecializationTypeLoc Loc) { unsigned size = getFullDataSize(); assert(size == Loc.getFullDataSize()); @@ -1798,6 +1798,13 @@ class VectorTypeLoc : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, VectorType> { }; +// FIXME: size expression and attribute locations (or keyword if we +// ever fully support altivec syntax). +class DependentVectorTypeLoc + : public InheritingConcreteTypeLoc<TypeSpecTypeLoc, + DependentVectorTypeLoc, + DependentVectorType> {}; + // FIXME: size expression and attribute locations. class ExtVectorTypeLoc : public InheritingConcreteTypeLoc<VectorTypeLoc, ExtVectorTypeLoc, @@ -1989,7 +1996,7 @@ public: struct ElaboratedLocInfo { SourceLocation ElaboratedKWLoc; - /// \brief Data associated with the nested-name-specifier location. + /// Data associated with the nested-name-specifier location. void *QualifierData; }; diff --git a/include/clang/AST/TypeNodes.def b/include/clang/AST/TypeNodes.def index 66697fa0d0faf..8638f94bda143 100644 --- a/include/clang/AST/TypeNodes.def +++ b/include/clang/AST/TypeNodes.def @@ -75,6 +75,7 @@ DEPENDENT_TYPE(DependentSizedArray, ArrayType) DEPENDENT_TYPE(DependentSizedExtVector, Type) DEPENDENT_TYPE(DependentAddressSpace, Type) TYPE(Vector, Type) +DEPENDENT_TYPE(DependentVector, Type) TYPE(ExtVector, VectorType) ABSTRACT_TYPE(Function, Type) TYPE(FunctionProto, FunctionType) diff --git a/include/clang/AST/TypeOrdering.h b/include/clang/AST/TypeOrdering.h index fa64fae8824fa..d29dd6d601247 100644 --- a/include/clang/AST/TypeOrdering.h +++ b/include/clang/AST/TypeOrdering.h @@ -1,4 +1,4 @@ -//===-------------- TypeOrdering.h - Total ordering for types -------------===// +//===-------------- TypeOrdering.h - Total ordering for types ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Allows QualTypes to be sorted and hence used in maps and sets. +/// Allows QualTypes to be sorted and hence used in maps and sets. /// /// Defines clang::QualTypeOrdering, a total ordering on clang::QualType, /// and hence enables QualType values to be sorted and to be used in @@ -25,7 +25,7 @@ namespace clang { -/// \brief Function object that provides a total ordering on QualType values. +/// Function object that provides a total ordering on QualType values. struct QualTypeOrdering { bool operator()(QualType T1, QualType T2) const { return std::less<void*>()(T1.getAsOpaquePtr(), T2.getAsOpaquePtr()); diff --git a/include/clang/AST/TypeVisitor.h b/include/clang/AST/TypeVisitor.h index 11e5a47f1f294..75fa0ec15ce2a 100644 --- a/include/clang/AST/TypeVisitor.h +++ b/include/clang/AST/TypeVisitor.h @@ -22,7 +22,7 @@ namespace clang { return static_cast<ImplClass*>(this)-> \ Visit##CLASS(static_cast<const CLASS*>(T)) -/// \brief An operation on a type. +/// An operation on a type. /// /// \tparam ImplClass Class implementing the operation. Must be inherited from /// TypeVisitor. @@ -65,7 +65,7 @@ template<typename ImplClass, typename RetTy=void> class TypeVisitor { public: - /// \brief Performs the operation associated with this visitor object. + /// Performs the operation associated with this visitor object. RetTy Visit(const Type *T) { // Top switch stmt: dispatch to VisitFooType for each FooType. switch (T->getTypeClass()) { @@ -83,7 +83,7 @@ public: } #include "clang/AST/TypeNodes.def" - /// \brief Method called if \c ImpClass doesn't provide specific handler + /// Method called if \c ImpClass doesn't provide specific handler /// for some type class. RetTy VisitType(const Type*) { return RetTy(); } }; diff --git a/include/clang/AST/UnresolvedSet.h b/include/clang/AST/UnresolvedSet.h index 614ff9bf2efda..d6b01cb573347 100644 --- a/include/clang/AST/UnresolvedSet.h +++ b/include/clang/AST/UnresolvedSet.h @@ -57,7 +57,7 @@ public: NamedDecl *operator->() const { return **this; } }; -/// \brief A set of unresolved declarations. +/// A set of unresolved declarations. class UnresolvedSetImpl { using DeclsTy = SmallVectorImpl<DeclAccessPair>; @@ -140,7 +140,7 @@ private: } }; -/// \brief A set of unresolved declarations. +/// A set of unresolved declarations. template <unsigned InlineCapacity> class UnresolvedSet : public UnresolvedSetImpl { SmallVector<DeclAccessPair, InlineCapacity> Decls; diff --git a/include/clang/AST/VTTBuilder.h b/include/clang/AST/VTTBuilder.h index 178139477d001..84661c8cc7f24 100644 --- a/include/clang/AST/VTTBuilder.h +++ b/include/clang/AST/VTTBuilder.h @@ -68,48 +68,48 @@ struct VTTComponent { : VTableIndex(VTableIndex), VTableBase(VTableBase) {} }; -/// \brief Class for building VTT layout information. +/// Class for building VTT layout information. class VTTBuilder { ASTContext &Ctx; - /// \brief The most derived class for which we're building this vtable. + /// The most derived class for which we're building this vtable. const CXXRecordDecl *MostDerivedClass; using VTTVTablesVectorTy = SmallVector<VTTVTable, 64>; - /// \brief The VTT vtables. + /// The VTT vtables. VTTVTablesVectorTy VTTVTables; using VTTComponentsVectorTy = SmallVector<VTTComponent, 64>; - /// \brief The VTT components. + /// The VTT components. VTTComponentsVectorTy VTTComponents; - /// \brief The AST record layout of the most derived class. + /// The AST record layout of the most derived class. const ASTRecordLayout &MostDerivedClassLayout; using VisitedVirtualBasesSetTy = llvm::SmallPtrSet<const CXXRecordDecl *, 4>; using AddressPointsMapTy = llvm::DenseMap<BaseSubobject, uint64_t>; - /// \brief The sub-VTT indices for the bases of the most derived class. + /// The sub-VTT indices for the bases of the most derived class. llvm::DenseMap<BaseSubobject, uint64_t> SubVTTIndicies; - /// \brief The secondary virtual pointer indices of all subobjects of + /// The secondary virtual pointer indices of all subobjects of /// the most derived class. llvm::DenseMap<BaseSubobject, uint64_t> SecondaryVirtualPointerIndices; - /// \brief Whether the VTT builder should generate LLVM IR for the VTT. + /// Whether the VTT builder should generate LLVM IR for the VTT. bool GenerateDefinition; - /// \brief Add a vtable pointer to the VTT currently being built. + /// Add a vtable pointer to the VTT currently being built. void AddVTablePointer(BaseSubobject Base, uint64_t VTableIndex, const CXXRecordDecl *VTableClass); - /// \brief Lay out the secondary VTTs of the given base subobject. + /// Lay out the secondary VTTs of the given base subobject. void LayoutSecondaryVTTs(BaseSubobject Base); - /// \brief Lay out the secondary virtual pointers for the given base + /// Lay out the secondary virtual pointers for the given base /// subobject. /// /// \param BaseIsMorallyVirtual whether the base subobject is a virtual base @@ -120,17 +120,17 @@ class VTTBuilder { const CXXRecordDecl *VTableClass, VisitedVirtualBasesSetTy &VBases); - /// \brief Lay out the secondary virtual pointers for the given base + /// Lay out the secondary virtual pointers for the given base /// subobject. void LayoutSecondaryVirtualPointers(BaseSubobject Base, uint64_t VTableIndex); - /// \brief Lay out the VTTs for the virtual base classes of the given + /// Lay out the VTTs for the virtual base classes of the given /// record declaration. void LayoutVirtualVTTs(const CXXRecordDecl *RD, VisitedVirtualBasesSetTy &VBases); - /// \brief Lay out the VTT for the given subobject, including any + /// Lay out the VTT for the given subobject, including any /// secondary VTTs, secondary virtual pointers and virtual VTTs. void LayoutVTT(BaseSubobject Base, bool BaseIsVirtual); @@ -138,22 +138,22 @@ public: VTTBuilder(ASTContext &Ctx, const CXXRecordDecl *MostDerivedClass, bool GenerateDefinition); - // \brief Returns a reference to the VTT components. + // Returns a reference to the VTT components. const VTTComponentsVectorTy &getVTTComponents() const { return VTTComponents; } - // \brief Returns a reference to the VTT vtables. + // Returns a reference to the VTT vtables. const VTTVTablesVectorTy &getVTTVTables() const { return VTTVTables; } - /// \brief Returns a reference to the sub-VTT indices. + /// Returns a reference to the sub-VTT indices. const llvm::DenseMap<BaseSubobject, uint64_t> &getSubVTTIndicies() const { return SubVTTIndicies; } - /// \brief Returns a reference to the secondary virtual pointer indices. + /// Returns a reference to the secondary virtual pointer indices. const llvm::DenseMap<BaseSubobject, uint64_t> & getSecondaryVirtualPointerIndices() const { return SecondaryVirtualPointerIndices; diff --git a/include/clang/AST/VTableBuilder.h b/include/clang/AST/VTableBuilder.h index b0b71e473516d..643103916149b 100644 --- a/include/clang/AST/VTableBuilder.h +++ b/include/clang/AST/VTableBuilder.h @@ -26,7 +26,7 @@ namespace clang { class CXXRecordDecl; -/// \brief Represents a single component in a vtable. +/// Represents a single component in a vtable. class VTableComponent { public: enum Kind { @@ -36,13 +36,13 @@ public: CK_RTTI, CK_FunctionPointer, - /// \brief A pointer to the complete destructor. + /// A pointer to the complete destructor. CK_CompleteDtorPointer, - /// \brief A pointer to the deleting destructor. + /// A pointer to the deleting destructor. CK_DeletingDtorPointer, - /// \brief An entry that is never used. + /// An entry that is never used. /// /// In some cases, a vtable function pointer will end up never being /// called. Such vtable function pointers are represented as a @@ -93,11 +93,7 @@ public: reinterpret_cast<uintptr_t>(MD)); } - static VTableComponent getFromOpaqueInteger(uint64_t I) { - return VTableComponent(I); - } - - /// \brief Get the kind of this vtable component. + /// Get the kind of this vtable component. Kind getKind() const { return (Kind)(Value & 0x7); } @@ -226,9 +222,6 @@ private: return static_cast<uintptr_t>(Value & ~7ULL); } - explicit VTableComponent(uint64_t Value) - : Value(Value) { } - /// The kind is stored in the lower 3 bits of the value. For offsets, we /// make use of the facts that classes can't be larger than 2^55 bytes, /// so we store the offset in the lower part of the 61 bits that remain. @@ -255,10 +248,10 @@ private: OwningArrayRef<VTableComponent> VTableComponents; - /// \brief Contains thunks needed by vtables, sorted by indices. + /// Contains thunks needed by vtables, sorted by indices. OwningArrayRef<VTableThunkTy> VTableThunks; - /// \brief Address points for all vtables. + /// Address points for all vtables. AddressPointsMapTy AddressPoints; public: @@ -324,7 +317,7 @@ public: protected: typedef llvm::DenseMap<const CXXMethodDecl *, ThunkInfoVectorTy> ThunksMapTy; - /// \brief Contains all thunks that a given method decl will need. + /// Contains all thunks that a given method decl will need. ThunksMapTy Thunks; /// Compute and store all vtable related information (vtable layout, vbase @@ -355,7 +348,7 @@ public: class ItaniumVTableContext : public VTableContextBase { private: - /// \brief Contains the index (relative to the vtable address point) + /// Contains the index (relative to the vtable address point) /// where the function pointer for a virtual function is stored. typedef llvm::DenseMap<GlobalDecl, int64_t> MethodVTableIndicesTy; MethodVTableIndicesTy MethodVTableIndices; @@ -368,7 +361,7 @@ private: typedef std::pair<const CXXRecordDecl *, const CXXRecordDecl *> ClassPairTy; - /// \brief vtable offsets for offsets of virtual bases of a class. + /// vtable offsets for offsets of virtual bases of a class. /// /// Contains the vtable offset (relative to the address point) in chars /// where the offsets for virtual bases of a class are stored. @@ -393,7 +386,7 @@ public: const CXXRecordDecl *MostDerivedClass, CharUnits MostDerivedClassOffset, bool MostDerivedClassIsVirtual, const CXXRecordDecl *LayoutClass); - /// \brief Locate a virtual function in the vtable. + /// Locate a virtual function in the vtable. /// /// Return the index (relative to the vtable address point) where the /// function pointer for the given virtual function is stored. @@ -479,41 +472,42 @@ struct VirtualBaseInfo { VPtrInfoVector VBPtrPaths; }; +struct MethodVFTableLocation { + /// If nonzero, holds the vbtable index of the virtual base with the vfptr. + uint64_t VBTableIndex; + + /// If nonnull, holds the last vbase which contains the vfptr that the + /// method definition is adjusted to. + const CXXRecordDecl *VBase; + + /// This is the offset of the vfptr from the start of the last vbase, or the + /// complete type if there are no virtual bases. + CharUnits VFPtrOffset; + + /// Method's index in the vftable. + uint64_t Index; + + MethodVFTableLocation() + : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()), + Index(0) {} + + MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, + CharUnits VFPtrOffset, uint64_t Index) + : VBTableIndex(VBTableIndex), VBase(VBase), VFPtrOffset(VFPtrOffset), + Index(Index) {} + + bool operator<(const MethodVFTableLocation &other) const { + if (VBTableIndex != other.VBTableIndex) { + assert(VBase != other.VBase); + return VBTableIndex < other.VBTableIndex; + } + return std::tie(VFPtrOffset, Index) < + std::tie(other.VFPtrOffset, other.Index); + } +}; + class MicrosoftVTableContext : public VTableContextBase { public: - struct MethodVFTableLocation { - /// If nonzero, holds the vbtable index of the virtual base with the vfptr. - uint64_t VBTableIndex; - - /// If nonnull, holds the last vbase which contains the vfptr that the - /// method definition is adjusted to. - const CXXRecordDecl *VBase; - - /// This is the offset of the vfptr from the start of the last vbase, or the - /// complete type if there are no virtual bases. - CharUnits VFPtrOffset; - - /// Method's index in the vftable. - uint64_t Index; - - MethodVFTableLocation() - : VBTableIndex(0), VBase(nullptr), VFPtrOffset(CharUnits::Zero()), - Index(0) {} - - MethodVFTableLocation(uint64_t VBTableIndex, const CXXRecordDecl *VBase, - CharUnits VFPtrOffset, uint64_t Index) - : VBTableIndex(VBTableIndex), VBase(VBase), - VFPtrOffset(VFPtrOffset), Index(Index) {} - - bool operator<(const MethodVFTableLocation &other) const { - if (VBTableIndex != other.VBTableIndex) { - assert(VBase != other.VBase); - return VBTableIndex < other.VBTableIndex; - } - return std::tie(VFPtrOffset, Index) < - std::tie(other.VFPtrOffset, other.Index); - } - }; private: ASTContext &Context; @@ -522,7 +516,7 @@ private: MethodVFTableLocationsTy; MethodVFTableLocationsTy MethodVFTableLocations; - typedef llvm::DenseMap<const CXXRecordDecl *, VPtrInfoVector> + typedef llvm::DenseMap<const CXXRecordDecl *, std::unique_ptr<VPtrInfoVector>> VFPtrLocationsMapTy; VFPtrLocationsMapTy VFPtrLocations; @@ -559,7 +553,7 @@ public: const VTableLayout &getVFTableLayout(const CXXRecordDecl *RD, CharUnits VFPtrOffset); - const MethodVFTableLocation &getMethodVFTableLocation(GlobalDecl GD); + MethodVFTableLocation getMethodVFTableLocation(GlobalDecl GD); const ThunkInfoVectorTy *getThunkInfo(GlobalDecl GD) override { // Complete destructors don't have a slot in a vftable, so no thunks needed. @@ -569,7 +563,7 @@ public: return VTableContextBase::getThunkInfo(GD); } - /// \brief Returns the index of VBase in the vbtable of Derived. + /// Returns the index of VBase in the vbtable of Derived. /// VBase must be a morally virtual base of Derived. /// The vbtable is an array of i32 offsets. The first entry is a self entry, /// and the rest are offsets from the vbptr to virtual bases. diff --git a/include/clang/ASTMatchers/ASTMatchFinder.h b/include/clang/ASTMatchers/ASTMatchFinder.h index 389af1b6e259a..324c02db3fe06 100644 --- a/include/clang/ASTMatchers/ASTMatchFinder.h +++ b/include/clang/ASTMatchers/ASTMatchFinder.h @@ -50,7 +50,7 @@ namespace clang { namespace ast_matchers { -/// \brief A class to allow finding matches over the Clang AST. +/// A class to allow finding matches over the Clang AST. /// /// After creation, you can add multiple matchers to the MatchFinder via /// calls to addMatcher(...). @@ -68,52 +68,52 @@ namespace ast_matchers { /// Not intended to be subclassed. class MatchFinder { public: - /// \brief Contains all information for a given match. + /// Contains all information for a given match. /// /// Every time a match is found, the MatchFinder will invoke the registered /// MatchCallback with a MatchResult containing information about the match. struct MatchResult { MatchResult(const BoundNodes &Nodes, clang::ASTContext *Context); - /// \brief Contains the nodes bound on the current match. + /// Contains the nodes bound on the current match. /// /// This allows user code to easily extract matched AST nodes. const BoundNodes Nodes; - /// \brief Utilities for interpreting the matched AST structures. + /// Utilities for interpreting the matched AST structures. /// @{ clang::ASTContext * const Context; clang::SourceManager * const SourceManager; /// @} }; - /// \brief Called when the Match registered for it was successfully found + /// Called when the Match registered for it was successfully found /// in the AST. class MatchCallback { public: virtual ~MatchCallback(); - /// \brief Called on every match by the \c MatchFinder. + /// Called on every match by the \c MatchFinder. virtual void run(const MatchResult &Result) = 0; - /// \brief Called at the start of each translation unit. + /// Called at the start of each translation unit. /// /// Optionally override to do per translation unit tasks. virtual void onStartOfTranslationUnit() {} - /// \brief Called at the end of each translation unit. + /// Called at the end of each translation unit. /// /// Optionally override to do per translation unit tasks. virtual void onEndOfTranslationUnit() {} - /// \brief An id used to group the matchers. + /// 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. + /// Called when parsing is finished. Intended for testing only. class ParsingDoneTestCallback { public: virtual ~ParsingDoneTestCallback(); @@ -125,11 +125,11 @@ public: Profiling(llvm::StringMap<llvm::TimeRecord> &Records) : Records(Records) {} - /// \brief Per bucket timing information. + /// Per bucket timing information. llvm::StringMap<llvm::TimeRecord> &Records; }; - /// \brief Enables per-check timers. + /// Enables per-check timers. /// /// It prints a report after match. llvm::Optional<Profiling> CheckProfiling; @@ -138,7 +138,7 @@ public: MatchFinder(MatchFinderOptions Options = MatchFinderOptions()); ~MatchFinder(); - /// \brief Adds a matcher to execute when running over the AST. + /// Adds a matcher to execute when running over the AST. /// /// Calls 'Action' with the BoundNodes on every match. /// Adding more than one 'NodeMatch' allows finding different matches in a @@ -162,7 +162,7 @@ public: MatchCallback *Action); /// @} - /// \brief Adds a matcher to execute when running over the AST. + /// Adds a matcher to execute when running over the AST. /// /// This is similar to \c addMatcher(), but it uses the dynamic interface. It /// is more flexible, but the lost type information enables a caller to pass @@ -173,10 +173,10 @@ public: bool addDynamicMatcher(const internal::DynTypedMatcher &NodeMatch, MatchCallback *Action); - /// \brief Creates a clang ASTConsumer that finds all matches. + /// Creates a clang ASTConsumer that finds all matches. std::unique_ptr<clang::ASTConsumer> newASTConsumer(); - /// \brief Calls the registered callbacks on all matches on the given \p Node. + /// Calls the registered callbacks on all matches on the given \p Node. /// /// Note that there can be multiple matches on a single node, for /// example when using decl(forEachDescendant(stmt())). @@ -189,17 +189,17 @@ public: ASTContext &Context); /// @} - /// \brief Finds all matches in the given AST. + /// Finds all matches in the given AST. void matchAST(ASTContext &Context); - /// \brief Registers a callback to notify the end of parsing. + /// Registers a callback to notify the end of parsing. /// /// The provided closure is called after parsing is done, before the AST is /// traversed. Useful for benchmarking. /// Each call to FindAll(...) will call the closure once. void registerTestCallbackAfterParsing(ParsingDoneTestCallback *ParsingDone); - /// \brief For each \c Matcher<> a \c MatchCallback that will be called + /// For each \c Matcher<> a \c MatchCallback that will be called /// when it matches. struct MatchersByType { std::vector<std::pair<internal::DynTypedMatcher, MatchCallback *>> @@ -211,7 +211,7 @@ public: NestedNameSpecifierLoc; std::vector<std::pair<TypeLocMatcher, MatchCallback *>> TypeLoc; std::vector<std::pair<CXXCtorInitializerMatcher, MatchCallback *>> CtorInit; - /// \brief All the callbacks in one container to simplify iteration. + /// All the callbacks in one container to simplify iteration. llvm::SmallPtrSet<MatchCallback *, 16> AllCallbacks; }; @@ -220,11 +220,11 @@ private: MatchFinderOptions Options; - /// \brief Called when parsing is done. + /// Called when parsing is done. ParsingDoneTestCallback *ParsingDone; }; -/// \brief Returns the results of matching \p Matcher on \p Node. +/// Returns the results of matching \p Matcher on \p Node. /// /// Collects the \c BoundNodes of all callback invocations when matching /// \p Matcher on \p Node and returns the collected results. @@ -248,12 +248,12 @@ match(MatcherT Matcher, const ast_type_traits::DynTypedNode &Node, ASTContext &Context); /// @} -/// \brief Returns the results of matching \p Matcher on the translation unit of +/// Returns the results of matching \p Matcher on the translation unit of /// \p Context and collects the \c BoundNodes of all callback invocations. template <typename MatcherT> SmallVector<BoundNodes, 1> match(MatcherT Matcher, ASTContext &Context); -/// \brief Returns the first result of type \c NodeT bound to \p BoundTo. +/// Returns the first result of type \c NodeT bound to \p BoundTo. /// /// Returns \c NULL if there is no match, or if the matching node cannot be /// casted to \c NodeT. diff --git a/include/clang/ASTMatchers/ASTMatchers.h b/include/clang/ASTMatchers/ASTMatchers.h index 64e7e908d51ed..58f65a39fb48b 100644 --- a/include/clang/ASTMatchers/ASTMatchers.h +++ b/include/clang/ASTMatchers/ASTMatchers.h @@ -92,7 +92,7 @@ namespace clang { namespace ast_matchers { -/// \brief Maps string IDs to AST nodes matched by parts of a matcher. +/// Maps string IDs to AST nodes matched by parts of a matcher. /// /// The bound nodes are generated by calling \c bind("id") on the node matchers /// of the nodes we want to access later. @@ -101,7 +101,7 @@ namespace ast_matchers { /// callbacks are executed every time a match is found. class BoundNodes { public: - /// \brief Returns the AST node bound to \c ID. + /// Returns the AST node bound to \c ID. /// /// Returns NULL if there was no node bound to \c ID or if there is a node but /// it cannot be converted to the specified type. @@ -110,12 +110,12 @@ public: return MyBoundNodes.getNodeAs<T>(ID); } - /// \brief Type of mapping from binding identifiers to bound nodes. This type + /// Type of mapping from binding identifiers to bound nodes. This type /// is an associative container with a key type of \c std::string and a value /// type of \c clang::ast_type_traits::DynTypedNode using IDToNodeMap = internal::BoundNodesMap::IDToNodeMap; - /// \brief Retrieve mapping from binding identifiers to bound nodes. + /// Retrieve mapping from binding identifiers to bound nodes. const IDToNodeMap &getMap() const { return MyBoundNodes.getMap(); } @@ -123,14 +123,14 @@ public: private: friend class internal::BoundNodesTreeBuilder; - /// \brief Create BoundNodes from a pre-filled map of bindings. + /// Create BoundNodes from a pre-filled map of bindings. BoundNodes(internal::BoundNodesMap &MyBoundNodes) : MyBoundNodes(MyBoundNodes) {} internal::BoundNodesMap MyBoundNodes; }; -/// \brief If the provided matcher matches a node, binds the node to \c ID. +/// If the provided matcher matches a node, binds the node to \c ID. /// /// FIXME: Do we want to support this now that we have bind()? template <typename T> @@ -139,7 +139,7 @@ internal::Matcher<T> id(StringRef ID, return InnerMatcher.bind(ID); } -/// \brief Types of matchers for the top-level classes in the AST class +/// Types of matchers for the top-level classes in the AST class /// hierarchy. /// @{ using DeclarationMatcher = internal::Matcher<Decl>; @@ -151,7 +151,7 @@ using NestedNameSpecifierLocMatcher = internal::Matcher<NestedNameSpecifierLoc>; using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>; /// @} -/// \brief Matches any node. +/// Matches any node. /// /// Useful when another matcher requires a child matcher, but there's no /// additional constraint. This will often be used with an explicit conversion @@ -167,7 +167,7 @@ using CXXCtorInitializerMatcher = internal::Matcher<CXXCtorInitializer>; /// Usable as: Any Matcher inline internal::TrueMatcher anything() { return internal::TrueMatcher(); } -/// \brief Matches the top declaration context. +/// Matches the top declaration context. /// /// Given /// \code @@ -181,7 +181,7 @@ inline internal::TrueMatcher anything() { return internal::TrueMatcher(); } extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> translationUnitDecl; -/// \brief Matches typedef declarations. +/// Matches typedef declarations. /// /// Given /// \code @@ -193,7 +193,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TranslationUnitDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> typedefDecl; -/// \brief Matches typedef name declarations. +/// Matches typedef name declarations. /// /// Given /// \code @@ -205,7 +205,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> typedefNameDecl; -/// \brief Matches type alias declarations. +/// Matches type alias declarations. /// /// Given /// \code @@ -217,7 +217,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypedefNameDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> typeAliasDecl; -/// \brief Matches type alias template declarations. +/// Matches type alias template declarations. /// /// typeAliasTemplateDecl() matches /// \code @@ -227,7 +227,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, TypeAliasTemplateDecl> typeAliasTemplateDecl; -/// \brief Matches AST nodes that were expanded within the main-file. +/// Matches AST nodes that were expanded within the main-file. /// /// Example matches X but not Y /// (matcher = cxxRecordDecl(isExpansionInMainFile()) @@ -248,7 +248,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInMainFile, SourceManager.getExpansionLoc(Node.getLocStart())); } -/// \brief Matches AST nodes that were expanded within system-header-files. +/// Matches AST nodes that were expanded within system-header-files. /// /// Example matches Y but not X /// (matcher = cxxRecordDecl(isExpansionInSystemHeader()) @@ -272,7 +272,7 @@ AST_POLYMORPHIC_MATCHER(isExpansionInSystemHeader, return SourceManager.isInSystemHeader(ExpansionLoc); } -/// \brief Matches AST nodes that were expanded within files whose name is +/// Matches AST nodes that were expanded within files whose name is /// partially matching a given regex. /// /// Example matches Y but not X @@ -306,7 +306,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching, return RE.match(Filename); } -/// \brief Matches declarations. +/// Matches declarations. /// /// Examples matches \c X, \c C, and the friend declaration inside \c C; /// \code @@ -317,7 +317,7 @@ AST_POLYMORPHIC_MATCHER_P(isExpansionInFileMatching, /// \endcode extern const internal::VariadicAllOfMatcher<Decl> decl; -/// \brief Matches a declaration of a linkage specification. +/// Matches a declaration of a linkage specification. /// /// Given /// \code @@ -328,7 +328,7 @@ extern const internal::VariadicAllOfMatcher<Decl> decl; extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> linkageSpecDecl; -/// \brief Matches a declaration of anything that could have a name. +/// 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; /// \code @@ -341,7 +341,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, LinkageSpecDecl> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; -/// \brief Matches a declaration of label. +/// Matches a declaration of label. /// /// Given /// \code @@ -352,7 +352,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamedDecl> namedDecl; /// matches 'FOO:' extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; -/// \brief Matches a declaration of a namespace. +/// Matches a declaration of a namespace. /// /// Given /// \code @@ -364,7 +364,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, LabelDecl> labelDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> namespaceDecl; -/// \brief Matches a declaration of a namespace alias. +/// Matches a declaration of a namespace alias. /// /// Given /// \code @@ -376,7 +376,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> namespaceAliasDecl; -/// \brief Matches class, struct, and union declarations. +/// Matches class, struct, and union declarations. /// /// Example matches \c X, \c Z, \c U, and \c S /// \code @@ -387,7 +387,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NamespaceAliasDecl> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl; -/// \brief Matches C++ class declarations. +/// Matches C++ class declarations. /// /// Example matches \c X, \c Z /// \code @@ -397,7 +397,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, RecordDecl> recordDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> cxxRecordDecl; -/// \brief Matches C++ class template declarations. +/// Matches C++ class template declarations. /// /// Example matches \c Z /// \code @@ -406,7 +406,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXRecordDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ClassTemplateDecl> classTemplateDecl; -/// \brief Matches C++ class template specializations. +/// Matches C++ class template specializations. /// /// Given /// \code @@ -420,7 +420,7 @@ extern const internal::VariadicDynCastAllOfMatcher< Decl, ClassTemplateSpecializationDecl> classTemplateSpecializationDecl; -/// \brief Matches declarator declarations (field, variable, function +/// Matches declarator declarations (field, variable, function /// and non-type template parameter declarations). /// /// Given @@ -432,7 +432,7 @@ extern const internal::VariadicDynCastAllOfMatcher< extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> declaratorDecl; -/// \brief Matches parameter variable declarations. +/// Matches parameter variable declarations. /// /// Given /// \code @@ -443,7 +443,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, DeclaratorDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> parmVarDecl; -/// \brief Matches C++ access specifier declarations. +/// Matches C++ access specifier declarations. /// /// Given /// \code @@ -457,7 +457,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ParmVarDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl> accessSpecDecl; -/// \brief Matches constructor initializers. +/// Matches constructor initializers. /// /// Examples matches \c i(42). /// \code @@ -469,7 +469,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, AccessSpecDecl> extern const internal::VariadicAllOfMatcher<CXXCtorInitializer> cxxCtorInitializer; -/// \brief Matches template arguments. +/// Matches template arguments. /// /// Given /// \code @@ -480,7 +480,7 @@ extern const internal::VariadicAllOfMatcher<CXXCtorInitializer> /// matches 'int' in C<int>. extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; -/// \brief Matches template name. +/// Matches template name. /// /// Given /// \code @@ -491,7 +491,7 @@ extern const internal::VariadicAllOfMatcher<TemplateArgument> templateArgument; /// matches 'X' in X<int>. extern const internal::VariadicAllOfMatcher<TemplateName> templateName; -/// \brief Matches non-type template parameter declarations. +/// Matches non-type template parameter declarations. /// /// Given /// \code @@ -503,7 +503,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, NonTypeTemplateParmDecl> nonTypeTemplateParmDecl; -/// \brief Matches template type parameter declarations. +/// Matches template type parameter declarations. /// /// Given /// \code @@ -514,7 +514,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, extern const internal::VariadicDynCastAllOfMatcher<Decl, TemplateTypeParmDecl> templateTypeParmDecl; -/// \brief Matches public C++ declarations. +/// Matches public C++ declarations. /// /// Given /// \code @@ -530,7 +530,7 @@ AST_MATCHER(Decl, isPublic) { return Node.getAccess() == AS_public; } -/// \brief Matches protected C++ declarations. +/// Matches protected C++ declarations. /// /// Given /// \code @@ -546,7 +546,7 @@ AST_MATCHER(Decl, isProtected) { return Node.getAccess() == AS_protected; } -/// \brief Matches private C++ declarations. +/// Matches private C++ declarations. /// /// Given /// \code @@ -562,7 +562,7 @@ AST_MATCHER(Decl, isPrivate) { return Node.getAccess() == AS_private; } -/// \brief Matches non-static data members that are bit-fields. +/// Matches non-static data members that are bit-fields. /// /// Given /// \code @@ -577,7 +577,7 @@ AST_MATCHER(FieldDecl, isBitField) { return Node.isBitField(); } -/// \brief Matches non-static data members that are bit-fields of the specified +/// Matches non-static data members that are bit-fields of the specified /// bit width. /// /// Given @@ -595,7 +595,7 @@ AST_MATCHER_P(FieldDecl, hasBitWidth, unsigned, Width) { Node.getBitWidthValue(Finder->getASTContext()) == Width; } -/// \brief Matches non-static data members that have an in-class initializer. +/// Matches non-static data members that have an in-class initializer. /// /// Given /// \code @@ -616,7 +616,13 @@ AST_MATCHER_P(FieldDecl, hasInClassInitializer, internal::Matcher<Expr>, InnerMatcher.matches(*Initializer, Finder, Builder)); } -/// \brief Matches the specialized template of a specialization declaration. +/// Determines whether the function is "main", which is the entry point +/// into an executable program. +AST_MATCHER(FunctionDecl, isMain) { + return Node.isMain(); +} + +/// Matches the specialized template of a specialization declaration. /// /// Given /// \code @@ -633,13 +639,13 @@ AST_MATCHER_P(ClassTemplateSpecializationDecl, hasSpecializedTemplate, InnerMatcher.matches(*Decl, Finder, Builder)); } -/// \brief Matches a declaration that has been implicitly added +/// Matches a declaration that has been implicitly added /// by the compiler (eg. implicit default/copy constructors). AST_MATCHER(Decl, isImplicit) { return Node.isImplicit(); } -/// \brief Matches classTemplateSpecializations, templateSpecializationType and +/// Matches classTemplateSpecializations, templateSpecializationType and /// functionDecl that have at least one TemplateArgument matching the given /// InnerMatcher. /// @@ -672,7 +678,7 @@ AST_POLYMORPHIC_MATCHER_P( Builder); } -/// \brief Matches expressions that match InnerMatcher after any implicit AST +/// Matches expressions that match InnerMatcher after any implicit AST /// nodes are stripped off. /// /// Parentheses and explicit casts are not discarded. @@ -693,12 +699,12 @@ AST_POLYMORPHIC_MATCHER_P( /// varDecl(hasInitializer(cxxConstructExpr())) /// \endcode /// only match the declarations for b and c. -AST_MATCHER_P(Expr, ignoringImplicit, ast_matchers::internal::Matcher<Expr>, +AST_MATCHER_P(Expr, ignoringImplicit, internal::Matcher<Expr>, InnerMatcher) { return InnerMatcher.matches(*Node.IgnoreImplicit(), Finder, Builder); } -/// \brief Matches expressions that match InnerMatcher after any implicit casts +/// Matches expressions that match InnerMatcher after any implicit casts /// are stripped off. /// /// Parentheses and explicit casts are not discarded. @@ -728,7 +734,7 @@ AST_MATCHER_P(Expr, ignoringImpCasts, return InnerMatcher.matches(*Node.IgnoreImpCasts(), Finder, Builder); } -/// \brief Matches expressions that match InnerMatcher after parentheses and +/// Matches expressions that match InnerMatcher after parentheses and /// casts are stripped off. /// /// Implicit and non-C Style casts are also discarded. @@ -749,7 +755,7 @@ AST_MATCHER_P(Expr, ignoringParenCasts, internal::Matcher<Expr>, InnerMatcher) { return InnerMatcher.matches(*Node.IgnoreParenCasts(), Finder, Builder); } -/// \brief Matches expressions that match InnerMatcher after implicit casts and +/// Matches expressions that match InnerMatcher after implicit casts and /// parentheses are stripped off. /// /// Explicit casts are not discarded. @@ -775,7 +781,7 @@ AST_MATCHER_P(Expr, ignoringParenImpCasts, return InnerMatcher.matches(*Node.IgnoreParenImpCasts(), Finder, Builder); } -/// \brief Matches types that match InnerMatcher after any parens are stripped. +/// Matches types that match InnerMatcher after any parens are stripped. /// /// Given /// \code @@ -791,7 +797,7 @@ AST_MATCHER_P(QualType, ignoringParens, return InnerMatcher.matches(Node.IgnoreParens(), Finder, Builder); } -/// \brief Matches classTemplateSpecializations, templateSpecializationType and +/// Matches classTemplateSpecializations, templateSpecializationType and /// functionDecl where the n'th TemplateArgument matches the given InnerMatcher. /// /// Given @@ -800,7 +806,7 @@ AST_MATCHER_P(QualType, ignoringParens, /// A<bool, int> b; /// A<int, bool> c; /// -/// template<typename T> f() {}; +/// template<typename T> void f() {} /// void func() { f<int>(); }; /// \endcode /// classTemplateSpecializationDecl(hasTemplateArgument( @@ -822,7 +828,7 @@ AST_POLYMORPHIC_MATCHER_P2( return InnerMatcher.matches(List[N], Finder, Builder); } -/// \brief Matches if the number of template arguments equals \p N. +/// Matches if the number of template arguments equals \p N. /// /// Given /// \code @@ -839,7 +845,7 @@ AST_POLYMORPHIC_MATCHER_P( return internal::getTemplateSpecializationArgs(Node).size() == N; } -/// \brief Matches a TemplateArgument that refers to a certain type. +/// Matches a TemplateArgument that refers to a certain type. /// /// Given /// \code @@ -857,7 +863,7 @@ AST_MATCHER_P(TemplateArgument, refersToType, return InnerMatcher.matches(Node.getAsType(), Finder, Builder); } -/// \brief Matches a TemplateArgument that refers to a certain template. +/// Matches a TemplateArgument that refers to a certain template. /// /// Given /// \code @@ -875,17 +881,17 @@ AST_MATCHER_P(TemplateArgument, refersToTemplate, return InnerMatcher.matches(Node.getAsTemplate(), Finder, Builder); } -/// \brief Matches a canonical TemplateArgument that refers to a certain +/// Matches a canonical TemplateArgument that refers to a certain /// declaration. /// /// Given /// \code -/// template<typename T> struct A {}; -/// struct B { B* next; }; +/// struct B { int next; }; +/// template<int(B::*next_ptr)> struct A {}; /// A<&B::next> a; /// \endcode /// classTemplateSpecializationDecl(hasAnyTemplateArgument( -/// refersToDeclaration(fieldDecl(hasName("next")))) +/// refersToDeclaration(fieldDecl(hasName("next"))))) /// matches the specialization \c A<&B::next> with \c fieldDecl(...) matching /// \c B::next AST_MATCHER_P(TemplateArgument, refersToDeclaration, @@ -895,12 +901,12 @@ AST_MATCHER_P(TemplateArgument, refersToDeclaration, return false; } -/// \brief Matches a sugar TemplateArgument that refers to a certain expression. +/// Matches a sugar TemplateArgument that refers to a certain expression. /// /// Given /// \code -/// template<typename T> struct A {}; -/// struct B { B* next; }; +/// struct B { int next; }; +/// template<int(B::*next_ptr)> struct A {}; /// A<&B::next> a; /// \endcode /// templateSpecializationType(hasAnyTemplateArgument( @@ -913,11 +919,11 @@ AST_MATCHER_P(TemplateArgument, isExpr, internal::Matcher<Expr>, InnerMatcher) { return false; } -/// \brief Matches a TemplateArgument that is an integral value. +/// Matches a TemplateArgument that is an integral value. /// /// Given /// \code -/// template<int T> struct A {}; +/// template<int T> struct C {}; /// C<42> c; /// \endcode /// classTemplateSpecializationDecl( @@ -928,11 +934,11 @@ AST_MATCHER(TemplateArgument, isIntegral) { return Node.getKind() == TemplateArgument::Integral; } -/// \brief Matches a TemplateArgument that referes to an integral type. +/// Matches a TemplateArgument that referes to an integral type. /// /// Given /// \code -/// template<int T> struct A {}; +/// template<int T> struct C {}; /// C<42> c; /// \endcode /// classTemplateSpecializationDecl( @@ -945,7 +951,7 @@ AST_MATCHER_P(TemplateArgument, refersToIntegralType, return InnerMatcher.matches(Node.getIntegralType(), Finder, Builder); } -/// \brief Matches a TemplateArgument of integral type with a given value. +/// 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 @@ -953,7 +959,7 @@ AST_MATCHER_P(TemplateArgument, refersToIntegralType, /// /// Given /// \code -/// template<int T> struct A {}; +/// template<int T> struct C {}; /// C<42> c; /// \endcode /// classTemplateSpecializationDecl( @@ -966,7 +972,20 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue, return Node.getAsIntegral().toString(10) == Value; } -/// \brief Matches any value declaration. +/// Matches an Objective-C autorelease pool statement. +/// +/// Given +/// \code +/// @autoreleasepool { +/// int x = 0; +/// } +/// \endcode +/// autoreleasePoolStmt(stmt()) matches the declaration of "x" +/// inside the autorelease pool. +extern const internal::VariadicDynCastAllOfMatcher<Stmt, + ObjCAutoreleasePoolStmt> autoreleasePoolStmt; + +/// Matches any value declaration. /// /// Example matches A, B, C and F /// \code @@ -975,7 +994,7 @@ AST_MATCHER_P(TemplateArgument, equalsIntegralValue, /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; -/// \brief Matches C++ constructor declarations. +/// Matches C++ constructor declarations. /// /// Example matches Foo::Foo() and Foo::Foo(int) /// \code @@ -989,7 +1008,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ValueDecl> valueDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl> cxxConstructorDecl; -/// \brief Matches explicit C++ destructor declarations. +/// Matches explicit C++ destructor declarations. /// /// Example matches Foo::~Foo() /// \code @@ -1001,7 +1020,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConstructorDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> cxxDestructorDecl; -/// \brief Matches enum declarations. +/// Matches enum declarations. /// /// Example matches X /// \code @@ -1011,7 +1030,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXDestructorDecl> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; -/// \brief Matches enum constants. +/// Matches enum constants. /// /// Example matches A, B, C /// \code @@ -1022,7 +1041,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumDecl> enumDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> enumConstantDecl; -/// \brief Matches method declarations. +/// Matches method declarations. /// /// Example matches y /// \code @@ -1031,7 +1050,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, EnumConstantDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> cxxMethodDecl; -/// \brief Matches conversion operator declarations. +/// Matches conversion operator declarations. /// /// Example matches the operator. /// \code @@ -1040,7 +1059,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXMethodDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> cxxConversionDecl; -/// \brief Matches variable declarations. +/// Matches variable declarations. /// /// Note: this does not match declarations of member variables, which are /// "field" declarations in Clang parlance. @@ -1051,7 +1070,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, CXXConversionDecl> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; -/// \brief Matches field declarations. +/// Matches field declarations. /// /// Given /// \code @@ -1061,7 +1080,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, VarDecl> varDecl; /// matches 'm'. extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; -/// \brief Matches function declarations. +/// Matches function declarations. /// /// Example matches f /// \code @@ -1070,7 +1089,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FieldDecl> fieldDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> functionDecl; -/// \brief Matches C++ function template declarations. +/// Matches C++ function template declarations. /// /// Example matches f /// \code @@ -1079,7 +1098,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl> functionTemplateDecl; -/// \brief Matches friend declarations. +/// Matches friend declarations. /// /// Given /// \code @@ -1089,7 +1108,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FunctionTemplateDecl> /// matches 'friend void foo()'. extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; -/// \brief Matches statements. +/// Matches statements. /// /// Given /// \code @@ -1099,7 +1118,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, FriendDecl> friendDecl; /// matches both the compound statement '{ ++a; }' and '++a'. extern const internal::VariadicAllOfMatcher<Stmt> stmt; -/// \brief Matches declaration statements. +/// Matches declaration statements. /// /// Given /// \code @@ -1109,7 +1128,7 @@ extern const internal::VariadicAllOfMatcher<Stmt> stmt; /// matches 'int a'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt; -/// \brief Matches member expressions. +/// Matches member expressions. /// /// Given /// \code @@ -1122,7 +1141,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclStmt> declStmt; /// matches this->x, x, y.x, a, this->b extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; -/// \brief Matches call expressions. +/// Matches call expressions. /// /// Example matches x.y() and y() /// \code @@ -1132,7 +1151,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, MemberExpr> memberExpr; /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; -/// \brief Matches lambda expressions. +/// Matches lambda expressions. /// /// Example matches [&](){return 5;} /// \code @@ -1140,7 +1159,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CallExpr> callExpr; /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; -/// \brief Matches member call expressions. +/// Matches member call expressions. /// /// Example matches x.y() /// \code @@ -1150,7 +1169,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, LambdaExpr> lambdaExpr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> cxxMemberCallExpr; -/// \brief Matches ObjectiveC Message invocation expressions. +/// Matches ObjectiveC Message invocation expressions. /// /// The innermost message send invokes the "alloc" class method on the /// NSString class, while the outermost message send invokes the @@ -1162,7 +1181,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXMemberCallExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> objcMessageExpr; -/// \brief Matches Objective-C interface declarations. +/// Matches Objective-C interface declarations. /// /// Example matches Foo /// \code @@ -1172,7 +1191,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCMessageExpr> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> objcInterfaceDecl; -/// \brief Matches Objective-C implementation declarations. +/// Matches Objective-C implementation declarations. /// /// Example matches Foo /// \code @@ -1182,7 +1201,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCInterfaceDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl> objcImplementationDecl; -/// \brief Matches Objective-C protocol declarations. +/// Matches Objective-C protocol declarations. /// /// Example matches FooDelegate /// \code @@ -1192,7 +1211,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCImplementationDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl> objcProtocolDecl; -/// \brief Matches Objective-C category declarations. +/// Matches Objective-C category declarations. /// /// Example matches Foo (Additions) /// \code @@ -1202,7 +1221,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCProtocolDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl> objcCategoryDecl; -/// \brief Matches Objective-C category definitions. +/// Matches Objective-C category definitions. /// /// Example matches Foo (Additions) /// \code @@ -1212,7 +1231,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl> objcCategoryImplDecl; -/// \brief Matches Objective-C method declarations. +/// Matches Objective-C method declarations. /// /// Example matches both declaration and definition of -[Foo method] /// \code @@ -1227,7 +1246,20 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCCategoryImplDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> objcMethodDecl; -/// \brief Matches Objective-C instance variable declarations. +/// Matches block declarations. +/// +/// Example matches the declaration of the nameless block printing an input +/// integer. +/// +/// \code +/// myFunc(^(int p) { +/// printf("%d", p); +/// }) +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Decl, BlockDecl> + blockDecl; + +/// Matches Objective-C instance variable declarations. /// /// Example matches _enabled /// \code @@ -1239,7 +1271,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCMethodDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> objcIvarDecl; -/// \brief Matches Objective-C property declarations. +/// Matches Objective-C property declarations. /// /// Example matches enabled /// \code @@ -1250,7 +1282,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCIvarDecl> extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl> objcPropertyDecl; -/// \brief Matches Objective-C \@throw statements. +/// Matches Objective-C \@throw statements. /// /// Example matches \@throw /// \code @@ -1259,7 +1291,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, ObjCPropertyDecl> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt> objcThrowStmt; -/// \brief Matches Objective-C @try statements. +/// Matches Objective-C @try statements. /// /// Example matches @try /// \code @@ -1269,7 +1301,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtThrowStmt> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> objcTryStmt; -/// \brief Matches Objective-C @catch statements. +/// Matches Objective-C @catch statements. /// /// Example matches @catch /// \code @@ -1279,7 +1311,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtTryStmt> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt> objcCatchStmt; -/// \brief Matches Objective-C @finally statements. +/// Matches Objective-C @finally statements. /// /// Example matches @finally /// \code @@ -1289,7 +1321,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtCatchStmt> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt> objcFinallyStmt; -/// \brief Matches expressions that introduce cleanups to be run at the end +/// Matches expressions that introduce cleanups to be run at the end /// of the sub-expression's evaluation. /// /// Example matches std::string() @@ -1299,7 +1331,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCAtFinallyStmt> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups> exprWithCleanups; -/// \brief Matches init list expressions. +/// Matches init list expressions. /// /// Given /// \code @@ -1312,7 +1344,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExprWithCleanups> extern const internal::VariadicDynCastAllOfMatcher<Stmt, InitListExpr> initListExpr; -/// \brief Matches the syntactic form of init list expressions +/// Matches the syntactic form of init list expressions /// (if expression have it). AST_MATCHER_P(InitListExpr, hasSyntacticForm, internal::Matcher<Expr>, InnerMatcher) { @@ -1321,7 +1353,7 @@ AST_MATCHER_P(InitListExpr, hasSyntacticForm, InnerMatcher.matches(*SyntForm, Finder, Builder)); } -/// \brief Matches C++ initializer list expressions. +/// Matches C++ initializer list expressions. /// /// Given /// \code @@ -1336,7 +1368,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStdInitializerListExpr> cxxStdInitializerListExpr; -/// \brief Matches implicit initializers of init list expressions. +/// Matches implicit initializers of init list expressions. /// /// Given /// \code @@ -1347,7 +1379,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr> implicitValueInitExpr; -/// \brief Matches paren list expressions. +/// Matches paren list expressions. /// ParenListExprs don't have a predefined type and are used for late parsing. /// In the final AST, they can be met in template declarations. /// @@ -1365,7 +1397,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitValueInitExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenListExpr> parenListExpr; -/// \brief Matches substitutions of non-type template parameters. +/// Matches substitutions of non-type template parameters. /// /// Given /// \code @@ -1379,7 +1411,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, SubstNonTypeTemplateParmExpr> substNonTypeTemplateParmExpr; -/// \brief Matches using declarations. +/// Matches using declarations. /// /// Given /// \code @@ -1390,7 +1422,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, /// matches \code using X::x \endcode extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; -/// \brief Matches using namespace declarations. +/// Matches using namespace declarations. /// /// Given /// \code @@ -1402,7 +1434,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDecl> usingDecl; extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl> usingDirectiveDecl; -/// \brief Matches reference to a name that can be looked up during parsing +/// Matches reference to a name that can be looked up during parsing /// but could not be resolved to a specific declaration. /// /// Given @@ -1419,7 +1451,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UsingDirectiveDecl> extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnresolvedLookupExpr> unresolvedLookupExpr; -/// \brief Matches unresolved using value declarations. +/// Matches unresolved using value declarations. /// /// Given /// \code @@ -1434,7 +1466,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingValueDecl> unresolvedUsingValueDecl; -/// \brief Matches unresolved using value declarations that involve the +/// Matches unresolved using value declarations that involve the /// typename. /// /// Given @@ -1453,7 +1485,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, UnresolvedUsingTypenameDecl> unresolvedUsingTypenameDecl; -/// \brief Matches parentheses used in expressions. +/// Matches parentheses used in expressions. /// /// Example matches (foo() + 1) /// \code @@ -1462,7 +1494,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr; -/// \brief Matches constructor call expressions (including implicit ones). +/// Matches constructor call expressions (including implicit ones). /// /// Example matches string(ptr, n) and ptr within arguments of f /// (matcher = cxxConstructExpr()) @@ -1475,7 +1507,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ParenExpr> parenExpr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstructExpr> cxxConstructExpr; -/// \brief Matches unresolved constructor call expressions. +/// Matches unresolved constructor call expressions. /// /// Example matches T(t) in return statement of f /// (matcher = cxxUnresolvedConstructExpr()) @@ -1487,7 +1519,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXUnresolvedConstructExpr> cxxUnresolvedConstructExpr; -/// \brief Matches implicit and explicit this expressions. +/// Matches implicit and explicit this expressions. /// /// Example matches the implicit this expression in "return i". /// (matcher = cxxThisExpr()) @@ -1500,7 +1532,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> cxxThisExpr; -/// \brief Matches nodes where temporaries are created. +/// Matches nodes where temporaries are created. /// /// Example matches FunctionTakesString(GetStringByValue()) /// (matcher = cxxBindTemporaryExpr()) @@ -1511,7 +1543,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThisExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr> cxxBindTemporaryExpr; -/// \brief Matches nodes where temporaries are materialized. +/// Matches nodes where temporaries are materialized. /// /// Example: Given /// \code @@ -1523,17 +1555,17 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBindTemporaryExpr> /// \code /// T u(f()); /// g(f()); +/// f().func(); /// \endcode /// but does not match /// \code /// f(); -/// f().func(); /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, MaterializeTemporaryExpr> materializeTemporaryExpr; -/// \brief Matches new expressions. +/// Matches new expressions. /// /// Given /// \code @@ -1543,7 +1575,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, /// matches 'new X'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; -/// \brief Matches delete expressions. +/// Matches delete expressions. /// /// Given /// \code @@ -1554,7 +1586,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNewExpr> cxxNewExpr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> cxxDeleteExpr; -/// \brief Matches array subscript expressions. +/// Matches array subscript expressions. /// /// Given /// \code @@ -1565,7 +1597,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDeleteExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr> arraySubscriptExpr; -/// \brief Matches the value of a default argument at the call site. +/// Matches the value of a default argument at the call site. /// /// Example matches the CXXDefaultArgExpr placeholder inserted for the /// default value of the second parameter in the call expression f(42) @@ -1577,7 +1609,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ArraySubscriptExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr> cxxDefaultArgExpr; -/// \brief Matches overloaded operator calls. +/// Matches overloaded operator calls. /// /// Note that if an operator isn't overloaded, it won't match. Instead, use /// binaryOperator matcher. @@ -1594,7 +1626,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDefaultArgExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr> cxxOperatorCallExpr; -/// \brief Matches expressions. +/// Matches expressions. /// /// Example matches x() /// \code @@ -1602,7 +1634,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXOperatorCallExpr> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; -/// \brief Matches expressions that refer to declarations. +/// Matches expressions that refer to declarations. /// /// Example matches x in if (x) /// \code @@ -1612,7 +1644,22 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, Expr> expr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> declRefExpr; -/// \brief Matches if statements. +/// Matches a reference to an ObjCIvar. +/// +/// Example: matches "a" in "init" method: +/// \code +/// @implementation A { +/// NSString *a; +/// } +/// - (void) init { +/// a = @"hello"; +/// } +//} +/// \endcode +extern const internal::VariadicDynCastAllOfMatcher<Stmt, ObjCIvarRefExpr> + objcIvarRefExpr; + +/// Matches if statements. /// /// Example matches 'if (x) {}' /// \code @@ -1620,7 +1667,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DeclRefExpr> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; -/// \brief Matches for statements. +/// Matches for statements. /// /// Example matches 'for (;;) {}' /// \code @@ -1629,7 +1676,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, IfStmt> ifStmt; /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, ForStmt> forStmt; -/// \brief Matches the increment statement of a for loop. +/// Matches the increment statement of a for loop. /// /// Example: /// forStmt(hasIncrement(unaryOperator(hasOperatorName("++")))) @@ -1644,7 +1691,7 @@ AST_MATCHER_P(ForStmt, hasIncrement, internal::Matcher<Stmt>, InnerMatcher.matches(*Increment, Finder, Builder)); } -/// \brief Matches the initialization statement of a for loop. +/// Matches the initialization statement of a for loop. /// /// Example: /// forStmt(hasLoopInit(declStmt())) @@ -1658,7 +1705,7 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder)); } -/// \brief Matches range-based for statements. +/// Matches range-based for statements. /// /// cxxForRangeStmt() matches 'for (auto a : i)' /// \code @@ -1668,7 +1715,7 @@ AST_MATCHER_P(ForStmt, hasLoopInit, internal::Matcher<Stmt>, extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXForRangeStmt> cxxForRangeStmt; -/// \brief Matches the initialization statement of a for loop. +/// Matches the initialization statement of a for loop. /// /// Example: /// forStmt(hasLoopVariable(anything())) @@ -1682,7 +1729,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasLoopVariable, internal::Matcher<VarDecl>, return (Var != nullptr && InnerMatcher.matches(*Var, Finder, Builder)); } -/// \brief Matches the range initialization statement of a for loop. +/// Matches the range initialization statement of a for loop. /// /// Example: /// forStmt(hasRangeInit(anything())) @@ -1696,7 +1743,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>, return (Init != nullptr && InnerMatcher.matches(*Init, Finder, Builder)); } -/// \brief Matches while statements. +/// Matches while statements. /// /// Given /// \code @@ -1706,7 +1753,7 @@ AST_MATCHER_P(CXXForRangeStmt, hasRangeInit, internal::Matcher<Expr>, /// matches 'while (true) {}'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; -/// \brief Matches do statements. +/// Matches do statements. /// /// Given /// \code @@ -1716,7 +1763,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, WhileStmt> whileStmt; /// matches 'do {} while(true)' extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; -/// \brief Matches break statements. +/// Matches break statements. /// /// Given /// \code @@ -1726,7 +1773,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, DoStmt> doStmt; /// matches 'break' extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; -/// \brief Matches continue statements. +/// Matches continue statements. /// /// Given /// \code @@ -1737,7 +1784,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BreakStmt> breakStmt; extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> continueStmt; -/// \brief Matches return statements. +/// Matches return statements. /// /// Given /// \code @@ -1747,7 +1794,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ContinueStmt> /// matches 'return 1' extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; -/// \brief Matches goto statements. +/// Matches goto statements. /// /// Given /// \code @@ -1758,7 +1805,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ReturnStmt> returnStmt; /// matches 'goto FOO' extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; -/// \brief Matches label statements. +/// Matches label statements. /// /// Given /// \code @@ -1769,7 +1816,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, GotoStmt> gotoStmt; /// matches 'FOO:' extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; -/// \brief Matches address of label statements (GNU extension). +/// Matches address of label statements (GNU extension). /// /// Given /// \code @@ -1782,7 +1829,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, LabelStmt> labelStmt; extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> addrLabelExpr; -/// \brief Matches switch statements. +/// Matches switch statements. /// /// Given /// \code @@ -1792,47 +1839,47 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AddrLabelExpr> /// matches 'switch(a)'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchStmt> switchStmt; -/// \brief Matches case and default statements inside switch statements. +/// Matches case and default statements inside switch statements. /// /// Given /// \code /// switch(a) { case 42: break; default: break; } /// \endcode /// switchCase() -/// matches 'case 42: break;' and 'default: break;'. +/// matches 'case 42:' and 'default:'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, SwitchCase> switchCase; -/// \brief Matches case statements inside switch statements. +/// Matches case statements inside switch statements. /// /// Given /// \code /// switch(a) { case 42: break; default: break; } /// \endcode /// caseStmt() -/// matches 'case 42: break;'. +/// matches 'case 42:'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, CaseStmt> caseStmt; -/// \brief Matches default statements inside switch statements. +/// Matches default statements inside switch statements. /// /// Given /// \code /// switch(a) { case 42: break; default: break; } /// \endcode /// defaultStmt() -/// matches 'default: break;'. +/// matches 'default:'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, DefaultStmt> defaultStmt; -/// \brief Matches compound statements. +/// Matches compound statements. /// -/// Example matches '{}' and '{{}}'in 'for (;;) {{}}' +/// Example matches '{}' and '{{}}' in 'for (;;) {{}}' /// \code /// for (;;) {{}} /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> compoundStmt; -/// \brief Matches catch statements. +/// Matches catch statements. /// /// \code /// try {} catch(int i) {} @@ -1842,7 +1889,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundStmt> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> cxxCatchStmt; -/// \brief Matches try statements. +/// Matches try statements. /// /// \code /// try {} catch(int i) {} @@ -1851,7 +1898,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXCatchStmt> /// matches 'try {}' extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; -/// \brief Matches throw expressions. +/// Matches throw expressions. /// /// \code /// try { throw 5; } catch(int i) {} @@ -1861,7 +1908,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTryStmt> cxxTryStmt; extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> cxxThrowExpr; -/// \brief Matches null statements. +/// Matches null statements. /// /// \code /// foo();; @@ -1870,7 +1917,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXThrowExpr> /// matches the second ';' extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; -/// \brief Matches asm statements. +/// Matches asm statements. /// /// \code /// int i = 100; @@ -1880,7 +1927,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, NullStmt> nullStmt; /// matches '__asm("mov al, 2")' extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; -/// \brief Matches bool literals. +/// Matches bool literals. /// /// Example matches true /// \code @@ -1889,7 +1936,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AsmStmt> asmStmt; extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr> cxxBoolLiteral; -/// \brief Matches string literals (also matches wide string literals). +/// Matches string literals (also matches wide string literals). /// /// Example matches "abcd", L"abcd" /// \code @@ -1899,7 +1946,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXBoolLiteralExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> stringLiteral; -/// \brief Matches character literals (also matches wchar_t). +/// Matches character literals (also matches wchar_t). /// /// Not matching Hex-encoded chars (e.g. 0x1234, which is a IntegerLiteral), /// though. @@ -1912,14 +1959,14 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, StringLiteral> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CharacterLiteral> characterLiteral; -/// \brief Matches integer literals of all sizes / encodings, e.g. +/// Matches integer literals of all sizes / encodings, e.g. /// 1, 1L, 0x1 and 1U. /// /// Does not match character-encoded integers such as L'a'. extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral> integerLiteral; -/// \brief Matches float literals of all sizes / encodings, e.g. +/// Matches float literals of all sizes / encodings, e.g. /// 1.0, 1.0f, 1.0L and 1e10. /// /// Does not match implicit conversions such as @@ -1929,13 +1976,13 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, IntegerLiteral> extern const internal::VariadicDynCastAllOfMatcher<Stmt, FloatingLiteral> floatLiteral; -/// \brief Matches user defined literal operator call. +/// Matches user defined literal operator call. /// /// Example match: "foo"_suffix extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> userDefinedLiteral; -/// \brief Matches compound (i.e. non-scalar) literals +/// Matches compound (i.e. non-scalar) literals /// /// Example match: {1}, (1, 2) /// \code @@ -1945,22 +1992,22 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UserDefinedLiteral> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CompoundLiteralExpr> compoundLiteralExpr; -/// \brief Matches nullptr literal. +/// Matches nullptr literal. extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXNullPtrLiteralExpr> cxxNullPtrLiteralExpr; -/// \brief Matches GNU __null expression. +/// Matches GNU __null expression. extern const internal::VariadicDynCastAllOfMatcher<Stmt, GNUNullExpr> gnuNullExpr; -/// \brief Matches atomic builtins. +/// Matches atomic builtins. /// Example matches __atomic_load_n(ptr, 1) /// \code /// void foo() { int *ptr; __atomic_load_n(ptr, 1); } /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; -/// \brief Matches statement expression (GNU extension). +/// Matches statement expression (GNU extension). /// /// Example match: ({ int X = 4; X; }) /// \code @@ -1968,7 +2015,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, AtomicExpr> atomicExpr; /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; -/// \brief Matches binary operator expressions. +/// Matches binary operator expressions. /// /// Example matches a || b /// \code @@ -1977,7 +2024,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, StmtExpr> stmtExpr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator> binaryOperator; -/// \brief Matches unary operator expressions. +/// Matches unary operator expressions. /// /// Example matches !a /// \code @@ -1986,7 +2033,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryOperator> extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> unaryOperator; -/// \brief Matches conditional operator expressions. +/// Matches conditional operator expressions. /// /// Example matches a ? b : c /// \code @@ -1995,7 +2042,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryOperator> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ConditionalOperator> conditionalOperator; -/// \brief Matches binary conditional operator expressions (GNU extension). +/// Matches binary conditional operator expressions (GNU extension). /// /// Example matches a ?: b /// \code @@ -2005,7 +2052,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, BinaryConditionalOperator> binaryConditionalOperator; -/// \brief Matches opaque value expressions. They are used as helpers +/// Matches opaque value expressions. They are used as helpers /// to reference another expressions and can be met /// in BinaryConditionalOperators, for example. /// @@ -2016,7 +2063,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr> opaqueValueExpr; -/// \brief Matches a C++ static_assert declaration. +/// Matches a C++ static_assert declaration. /// /// Example: /// staticAssertExpr() @@ -2032,7 +2079,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, OpaqueValueExpr> extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl> staticAssertDecl; -/// \brief Matches a reinterpret_cast expression. +/// Matches a reinterpret_cast expression. /// /// Either the source expression or the destination type can be matched /// using has(), but hasDestinationType() is more specific and can be @@ -2045,7 +2092,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Decl, StaticAssertDecl> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr> cxxReinterpretCastExpr; -/// \brief Matches a C++ static_cast expression. +/// Matches a C++ static_cast expression. /// /// \see hasDestinationType /// \see reinterpretCast @@ -2061,7 +2108,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXReinterpretCastExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr> cxxStaticCastExpr; -/// \brief Matches a dynamic_cast expression. +/// Matches a dynamic_cast expression. /// /// Example: /// cxxDynamicCastExpr() @@ -2076,7 +2123,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXStaticCastExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr> cxxDynamicCastExpr; -/// \brief Matches a const_cast expression. +/// Matches a const_cast expression. /// /// Example: Matches const_cast<int*>(&r) in /// \code @@ -2087,7 +2134,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXDynamicCastExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr> cxxConstCastExpr; -/// \brief Matches a C-style cast expression. +/// Matches a C-style cast expression. /// /// Example: Matches (int) 2.2f in /// \code @@ -2096,7 +2143,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXConstCastExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr> cStyleCastExpr; -/// \brief Matches explicit cast expressions. +/// Matches explicit cast expressions. /// /// Matches any cast expression written in user code, whether it be a /// C-style cast, a functional-style cast, or a keyword cast. @@ -2120,14 +2167,14 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CStyleCastExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, ExplicitCastExpr> explicitCastExpr; -/// \brief Matches the implicit cast nodes of Clang's AST. +/// Matches the implicit cast nodes of Clang's AST. /// /// This matches many different places, including function call return value /// eliding, as well as any type conversions. extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr> implicitCastExpr; -/// \brief Matches any cast nodes of Clang's AST. +/// Matches any cast nodes of Clang's AST. /// /// Example: castExpr() matches each of the following: /// \code @@ -2142,7 +2189,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, ImplicitCastExpr> /// \endcode extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; -/// \brief Matches functional cast expressions +/// Matches functional cast expressions /// /// Example: Matches Foo(bar); /// \code @@ -2153,7 +2200,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CastExpr> castExpr; extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr> cxxFunctionalCastExpr; -/// \brief Matches functional cast expressions having N != 1 arguments +/// Matches functional cast expressions having N != 1 arguments /// /// Example: Matches Foo(bar, bar) /// \code @@ -2162,7 +2209,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXFunctionalCastExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr> cxxTemporaryObjectExpr; -/// \brief Matches predefined identifier expressions [C99 6.4.2.2]. +/// Matches predefined identifier expressions [C99 6.4.2.2]. /// /// Example: Matches __func__ /// \code @@ -2171,7 +2218,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, CXXTemporaryObjectExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr> predefinedExpr; -/// \brief Matches C99 designated initializer expressions [C99 6.7.8]. +/// Matches C99 designated initializer expressions [C99 6.7.8]. /// /// Example: Matches { [2].y = 1.0, [0].x = 1.0 } /// \code @@ -2180,7 +2227,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, PredefinedExpr> extern const internal::VariadicDynCastAllOfMatcher<Stmt, DesignatedInitExpr> designatedInitExpr; -/// \brief Matches designated initializer expressions that contain +/// Matches designated initializer expressions that contain /// a specific number of designators. /// /// Example: Given @@ -2195,16 +2242,16 @@ AST_MATCHER_P(DesignatedInitExpr, designatorCountIs, unsigned, N) { return Node.size() == N; } -/// \brief Matches \c QualTypes in the clang AST. +/// Matches \c QualTypes in the clang AST. extern const internal::VariadicAllOfMatcher<QualType> qualType; -/// \brief Matches \c Types in the clang AST. +/// Matches \c Types in the clang AST. extern const internal::VariadicAllOfMatcher<Type> type; -/// \brief Matches \c TypeLocs in the clang AST. +/// Matches \c TypeLocs in the clang AST. extern const internal::VariadicAllOfMatcher<TypeLoc> typeLoc; -/// \brief Matches if any of the given matchers matches. +/// Matches if any of the given matchers matches. /// /// Unlike \c anyOf, \c eachOf will generate a match result for each /// matching submatcher. @@ -2227,21 +2274,21 @@ extern const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits<unsigned>::max()> eachOf; -/// \brief Matches if any of the given matchers matches. +/// Matches if any of the given matchers matches. /// /// Usable as: Any Matcher extern const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits<unsigned>::max()> anyOf; -/// \brief Matches if all given matchers match. +/// Matches if all given matchers match. /// /// Usable as: Any Matcher extern const internal::VariadicOperatorMatcherFunc< 2, std::numeric_limits<unsigned>::max()> allOf; -/// \brief Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) +/// Matches sizeof (C99), alignof (C++11) and vec_step (OpenCL) /// /// Given /// \code @@ -2254,7 +2301,7 @@ extern const internal::VariadicDynCastAllOfMatcher<Stmt, UnaryExprOrTypeTraitExpr> unaryExprOrTypeTraitExpr; -/// \brief Matches unary expressions that have a specific type of argument. +/// Matches unary expressions that have a specific type of argument. /// /// Given /// \code @@ -2268,7 +2315,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, hasArgumentOfType, return InnerMatcher.matches(ArgumentType, Finder, Builder); } -/// \brief Matches unary expressions of a certain kind. +/// Matches unary expressions of a certain kind. /// /// Given /// \code @@ -2281,7 +2328,7 @@ AST_MATCHER_P(UnaryExprOrTypeTraitExpr, ofKind, UnaryExprOrTypeTrait, Kind) { return Node.getKind() == Kind; } -/// \brief Same as unaryExprOrTypeTraitExpr, but only matching +/// Same as unaryExprOrTypeTraitExpr, but only matching /// alignof. inline internal::Matcher<Stmt> alignOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { @@ -2289,7 +2336,7 @@ inline internal::Matcher<Stmt> alignOfExpr( ofKind(UETT_AlignOf), InnerMatcher))); } -/// \brief Same as unaryExprOrTypeTraitExpr, but only matching +/// Same as unaryExprOrTypeTraitExpr, but only matching /// sizeof. inline internal::Matcher<Stmt> sizeOfExpr( const internal::Matcher<UnaryExprOrTypeTraitExpr> &InnerMatcher) { @@ -2297,7 +2344,7 @@ inline internal::Matcher<Stmt> sizeOfExpr( allOf(ofKind(UETT_SizeOf), InnerMatcher))); } -/// \brief Matches NamedDecl nodes that have the specified name. +/// Matches NamedDecl nodes that have the specified name. /// /// Supports specifying enclosing namespaces or classes by prefixing the name /// with '<enclosing>::'. @@ -2313,12 +2360,10 @@ inline internal::Matcher<Stmt> sizeOfExpr( /// namespace a { namespace b { class X; } } /// \endcode inline internal::Matcher<NamedDecl> hasName(const std::string &Name) { - std::vector<std::string> Names; - Names.push_back(Name); - return internal::Matcher<NamedDecl>(new internal::HasNameMatcher(Names)); + return internal::Matcher<NamedDecl>(new internal::HasNameMatcher({Name})); } -/// \brief Matches NamedDecl nodes that have any of the specified names. +/// Matches NamedDecl nodes that have any of the specified names. /// /// This matcher is only provided as a performance optimization of hasName. /// \code @@ -2332,7 +2377,7 @@ extern const internal::VariadicFunction<internal::Matcher<NamedDecl>, StringRef, internal::hasAnyNameFunc> hasAnyName; -/// \brief Matches NamedDecl nodes whose fully qualified names contain +/// Matches NamedDecl nodes whose fully qualified names contain /// a substring matched by the given RegExp. /// /// Supports specifying enclosing namespaces or classes by @@ -2355,7 +2400,7 @@ AST_MATCHER_P(NamedDecl, matchesName, std::string, RegExp) { return RE.match(FullNameString); } -/// \brief Matches overloaded operator names. +/// Matches overloaded operator names. /// /// Matches overloaded operator names specified in strings without the /// "operator" prefix: e.g. "<<". @@ -2383,7 +2428,7 @@ hasOverloadedOperatorName(StringRef Name) { AST_POLYMORPHIC_SUPPORTED_TYPES(CXXOperatorCallExpr, FunctionDecl)>(Name); } -/// \brief Matches C++ classes that are directly or indirectly derived from +/// Matches C++ classes that are directly or indirectly derived from /// a class matching \c Base. /// /// Note that a class is not considered to be derived from itself. @@ -2409,13 +2454,13 @@ AST_MATCHER_P(CXXRecordDecl, isDerivedFrom, return Finder->classIsDerivedFrom(&Node, Base, Builder); } -/// \brief Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). +/// Overloaded method as shortcut for \c isDerivedFrom(hasName(...)). AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isDerivedFrom, std::string, BaseName, 1) { assert(!BaseName.empty()); return isDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); } -/// \brief Similar to \c isDerivedFrom(), but also matches classes that directly +/// Similar to \c isDerivedFrom(), but also matches classes that directly /// match \c Base. AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, internal::Matcher<NamedDecl>, Base, 0) { @@ -2423,7 +2468,7 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, .matches(Node, Finder, Builder); } -/// \brief Overloaded method as shortcut for +/// Overloaded method as shortcut for /// \c isSameOrDerivedFrom(hasName(...)). AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string, BaseName, 1) { @@ -2431,7 +2476,7 @@ AST_MATCHER_P_OVERLOAD(CXXRecordDecl, isSameOrDerivedFrom, std::string, return isSameOrDerivedFrom(hasName(BaseName)).matches(Node, Finder, Builder); } -/// \brief Matches the first method of a class or struct that satisfies \c +/// Matches the first method of a class or struct that satisfies \c /// InnerMatcher. /// /// Given: @@ -2448,7 +2493,7 @@ AST_MATCHER_P(CXXRecordDecl, hasMethod, internal::Matcher<CXXMethodDecl>, Node.method_end(), Finder, Builder); } -/// \brief Matches the generated class of lambda expressions. +/// Matches the generated class of lambda expressions. /// /// Given: /// \code @@ -2461,7 +2506,7 @@ AST_MATCHER(CXXRecordDecl, isLambda) { return Node.isLambda(); } -/// \brief Matches AST nodes that have child AST nodes that match the +/// Matches AST nodes that have child AST nodes that match the /// provided matcher. /// /// Example matches X, Y @@ -2481,7 +2526,7 @@ AST_MATCHER(CXXRecordDecl, isLambda) { /// has(ignoringParenImpCasts(expr())). extern const internal::ArgumentAdaptingMatcherFunc<internal::HasMatcher> has; -/// \brief Matches AST nodes that have descendant AST nodes that match the +/// Matches AST nodes that have descendant AST nodes that match the /// provided matcher. /// /// Example matches X, Y, Z @@ -2499,14 +2544,15 @@ extern const internal::ArgumentAdaptingMatcherFunc< internal::HasDescendantMatcher> hasDescendant; -/// \brief Matches AST nodes that have child AST nodes that match the +/// Matches AST nodes that have child AST nodes that match the /// provided matcher. /// -/// Example matches X, Y +/// Example matches X, Y, Y::X, Z::Y, Z::Y::X /// (matcher = cxxRecordDecl(forEach(cxxRecordDecl(hasName("X"))) /// \code -/// class X {}; // Matches X, because X::X is a class of name X inside X. -/// class Y { class X {}; }; +/// class X {}; +/// class Y { class X {}; }; // Matches Y, because Y::X is a class of name X +/// // inside Y. /// class Z { class Y { class X {}; }; }; // Does not match Z. /// \endcode /// @@ -2519,14 +2565,15 @@ extern const internal::ArgumentAdaptingMatcherFunc< extern const internal::ArgumentAdaptingMatcherFunc<internal::ForEachMatcher> forEach; -/// \brief Matches AST nodes that have descendant AST nodes that match the +/// Matches AST nodes that have descendant AST nodes that match the /// provided matcher. /// -/// Example matches X, A, B, C +/// Example matches X, A, A::X, B, B::C, B::C::X /// (matcher = cxxRecordDecl(forEachDescendant(cxxRecordDecl(hasName("X"))))) /// \code -/// class X {}; // Matches X, because X::X is a class of name X inside X. -/// class A { class X {}; }; +/// class X {}; +/// class A { class X {}; }; // Matches A, because A::X is a class of name +/// // X inside A. /// class B { class C { class X {}; }; }; /// \endcode /// @@ -2549,7 +2596,7 @@ extern const internal::ArgumentAdaptingMatcherFunc< internal::ForEachDescendantMatcher> forEachDescendant; -/// \brief Matches if the node or any descendant matches. +/// Matches if the node or any descendant matches. /// /// Generates results for each match. /// @@ -2570,7 +2617,7 @@ internal::Matcher<T> findAll(const internal::Matcher<T> &Matcher) { return eachOf(Matcher, forEachDescendant(Matcher)); } -/// \brief Matches AST nodes that have a parent that matches the provided +/// Matches AST nodes that have a parent that matches the provided /// matcher. /// /// Given @@ -2586,7 +2633,7 @@ extern const internal::ArgumentAdaptingMatcherFunc< internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> hasParent; -/// \brief Matches AST nodes that have an ancestor that matches the provided +/// Matches AST nodes that have an ancestor that matches the provided /// matcher. /// /// Given @@ -2603,7 +2650,7 @@ extern const internal::ArgumentAdaptingMatcherFunc< internal::TypeList<Decl, NestedNameSpecifierLoc, Stmt, TypeLoc>> hasAncestor; -/// \brief Matches if the provided matcher does not match. +/// Matches if the provided matcher does not match. /// /// Example matches Y (matcher = cxxRecordDecl(unless(hasName("X")))) /// \code @@ -2614,7 +2661,7 @@ extern const internal::ArgumentAdaptingMatcherFunc< /// Usable as: Any Matcher extern const internal::VariadicOperatorMatcherFunc<1, 1> unless; -/// \brief Matches a node if the declaration associated with that node +/// Matches a node if the declaration associated with that node /// matches the given matcher. /// /// The associated declaration is: @@ -2623,6 +2670,7 @@ extern const internal::VariadicOperatorMatcherFunc<1, 1> unless; /// - for MemberExpr, the declaration of the referenced member /// - for CXXConstructExpr, the declaration of the constructor /// - for CXXNewExpr, the declaration of the operator new +/// - for ObjCIvarExpr, the declaration of the ivar /// /// For type nodes, hasDeclaration will generally match the declaration of the /// sugared type. Given @@ -2656,7 +2704,7 @@ hasDeclaration(const internal::Matcher<Decl> &InnerMatcher) { void(internal::HasDeclarationSupportedTypes)>(InnerMatcher); } -/// \brief Matches a \c NamedDecl whose underlying declaration matches the given +/// Matches a \c NamedDecl whose underlying declaration matches the given /// matcher. /// /// Given @@ -2675,13 +2723,13 @@ AST_MATCHER_P(NamedDecl, hasUnderlyingDecl, internal::Matcher<NamedDecl>, InnerMatcher.matches(*UnderlyingDecl, Finder, Builder); } -/// \brief Matches on the implicit object argument of a member call expression. +/// Matches on the implicit object argument of a member call expression. /// /// Example matches y.x() /// (matcher = cxxMemberCallExpr(on(hasType(cxxRecordDecl(hasName("Y")))))) /// \code /// class Y { public: void x(); }; -/// void z() { Y y; y.x(); }", +/// void z() { Y y; y.x(); } /// \endcode /// /// FIXME: Overload to allow directly matching types? @@ -2694,7 +2742,7 @@ AST_MATCHER_P(CXXMemberCallExpr, on, internal::Matcher<Expr>, } -/// \brief Matches on the receiver of an ObjectiveC Message expression. +/// Matches on the receiver of an ObjectiveC Message expression. /// /// Example /// matcher = objCMessageExpr(hasReceiverType(asString("UIWebView *"))); @@ -2709,8 +2757,43 @@ AST_MATCHER_P(ObjCMessageExpr, hasReceiverType, internal::Matcher<QualType>, const QualType TypeDecl = Node.getReceiverType(); return InnerMatcher.matches(TypeDecl, Finder, Builder); } - -/// \brief Matches when BaseName == Selector.getAsString() + +/// Returns true when the Objective-C message is sent to an instance. +/// +/// Example +/// matcher = objcMessagaeExpr(isInstanceMessage()) +/// matches +/// \code +/// NSString *x = @"hello"; +/// [x containsString:@"h"]; +/// \endcode +/// but not +/// \code +/// [NSString stringWithFormat:@"format"]; +/// \endcode +AST_MATCHER(ObjCMessageExpr, isInstanceMessage) { + return Node.isInstanceMessage(); +} + +/// Matches if the Objective-C message is sent to an instance, +/// and the inner matcher matches on that instance. +/// +/// For example the method call in +/// \code +/// NSString *x = @"hello"; +/// [x containsString:@"h"]; +/// \endcode +/// is matched by +/// objcMessageExpr(hasReceiver(declRefExpr(to(varDecl(hasName("x")))))) +AST_MATCHER_P(ObjCMessageExpr, hasReceiver, internal::Matcher<Expr>, + InnerMatcher) { + const Expr *ReceiverNode = Node.getInstanceReceiver(); + return (ReceiverNode != nullptr && + InnerMatcher.matches(*ReceiverNode->IgnoreParenImpCasts(), Finder, + Builder)); +} + +/// Matches when BaseName == Selector.getAsString() /// /// matcher = objCMessageExpr(hasSelector("loadHTMLString:baseURL:")); /// matches the outer message expr in the code below, but NOT the message @@ -2723,8 +2806,22 @@ AST_MATCHER_P(ObjCMessageExpr, hasSelector, std::string, BaseName) { return BaseName.compare(Sel.getAsString()) == 0; } - -/// \brief Matches ObjC selectors whose name contains + +/// Matches when at least one of the supplied string equals to the +/// Selector.getAsString() +/// +/// matcher = objCMessageExpr(hasSelector("methodA:", "methodB:")); +/// matches both of the expressions below: +/// \code +/// [myObj methodA:argA]; +/// [myObj methodB:argB]; +/// \endcode +extern const internal::VariadicFunction<internal::Matcher<ObjCMessageExpr>, + StringRef, + internal::hasAnySelectorFunc> + hasAnySelector; + +/// Matches ObjC selectors whose name contains /// a substring matched by the given RegExp. /// matcher = objCMessageExpr(matchesSelector("loadHTMLString\:baseURL?")); /// matches the outer message expr in the code below, but NOT the message @@ -2739,7 +2836,7 @@ AST_MATCHER_P(ObjCMessageExpr, matchesSelector, std::string, RegExp) { return RE.match(SelectorString); } -/// \brief Matches when the selector is the empty selector +/// Matches when the selector is the empty selector /// /// Matches only when the selector of the objCMessageExpr is NULL. This may /// represent an error condition in the tree! @@ -2747,7 +2844,7 @@ AST_MATCHER(ObjCMessageExpr, hasNullSelector) { return Node.getSelector().isNull(); } -/// \brief Matches when the selector is a Unary Selector +/// Matches when the selector is a Unary Selector /// /// matcher = objCMessageExpr(matchesSelector(hasUnarySelector()); /// matches self.bodyView in the code below, but NOT the outer message @@ -2759,7 +2856,7 @@ AST_MATCHER(ObjCMessageExpr, hasUnarySelector) { return Node.getSelector().isUnarySelector(); } -/// \brief Matches when the selector is a keyword selector +/// Matches when the selector is a keyword selector /// /// objCMessageExpr(hasKeywordSelector()) matches the generated setFrame /// message expression in @@ -2775,7 +2872,7 @@ AST_MATCHER(ObjCMessageExpr, hasKeywordSelector) { return Node.getSelector().isKeywordSelector(); } -/// \brief Matches when the selector has the specified number of arguments +/// Matches when the selector has the specified number of arguments /// /// matcher = objCMessageExpr(numSelectorArgs(0)); /// matches self.bodyView in the code below @@ -2790,7 +2887,7 @@ AST_MATCHER_P(ObjCMessageExpr, numSelectorArgs, unsigned, N) { return Node.getSelector().getNumArgs() == N; } -/// \brief Matches if the call expression's callee expression matches. +/// Matches if the call expression's callee expression matches. /// /// Given /// \code @@ -2813,7 +2910,7 @@ AST_MATCHER_P(CallExpr, callee, internal::Matcher<Stmt>, InnerMatcher.matches(*ExprNode, Finder, Builder)); } -/// \brief Matches if the call expression's callee's declaration matches the +/// Matches if the call expression's callee's declaration matches the /// given matcher. /// /// Example matches y.x() (matcher = callExpr(callee( @@ -2827,25 +2924,31 @@ AST_MATCHER_P_OVERLOAD(CallExpr, callee, internal::Matcher<Decl>, InnerMatcher, return callExpr(hasDeclaration(InnerMatcher)).matches(Node, Finder, Builder); } -/// \brief Matches if the expression's or declaration's type matches a type +/// Matches if the expression's or declaration's type matches a type /// matcher. /// /// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X"))))) /// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X"))))) /// and U (matcher = typedefDecl(hasType(asString("int"))) +/// and friend class X (matcher = friendDecl(hasType("X")) /// \code /// class X {}; /// void y(X &x) { x; X z; } /// typedef int U; +/// class Y { friend class X; }; /// \endcode AST_POLYMORPHIC_MATCHER_P_OVERLOAD( - hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, TypedefNameDecl, ValueDecl), + hasType, + AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, TypedefNameDecl, + ValueDecl), internal::Matcher<QualType>, InnerMatcher, 0) { - return InnerMatcher.matches(internal::getUnderlyingType(Node), - Finder, Builder); + QualType QT = internal::getUnderlyingType(Node); + if (!QT.isNull()) + return InnerMatcher.matches(QT, Finder, Builder); + return false; } -/// \brief Overloaded to match the declaration of the expression's or value +/// Overloaded to match the declaration of the expression's or value /// declaration's type. /// /// In case of a value declaration (for example a variable declaration), @@ -2856,21 +2959,24 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD( /// /// Example matches x (matcher = expr(hasType(cxxRecordDecl(hasName("X"))))) /// and z (matcher = varDecl(hasType(cxxRecordDecl(hasName("X"))))) +/// and friend class X (matcher = friendDecl(hasType("X")) /// \code /// class X {}; /// void y(X &x) { x; X z; } +/// class Y { friend class X; }; /// \endcode /// /// Usable as: Matcher<Expr>, Matcher<ValueDecl> -AST_POLYMORPHIC_MATCHER_P_OVERLOAD(hasType, - AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, - ValueDecl), - internal::Matcher<Decl>, InnerMatcher, 1) { - return qualType(hasDeclaration(InnerMatcher)) - .matches(Node.getType(), Finder, Builder); +AST_POLYMORPHIC_MATCHER_P_OVERLOAD( + hasType, AST_POLYMORPHIC_SUPPORTED_TYPES(Expr, FriendDecl, ValueDecl), + internal::Matcher<Decl>, InnerMatcher, 1) { + QualType QT = internal::getUnderlyingType(Node); + if (!QT.isNull()) + return qualType(hasDeclaration(InnerMatcher)).matches(QT, Finder, Builder); + return false; } -/// \brief Matches if the type location of the declarator decl's type matches +/// Matches if the type location of the declarator decl's type matches /// the inner matcher. /// /// Given @@ -2886,7 +2992,7 @@ AST_MATCHER_P(DeclaratorDecl, hasTypeLoc, internal::Matcher<TypeLoc>, Inner) { return Inner.matches(Node.getTypeSourceInfo()->getTypeLoc(), Finder, Builder); } -/// \brief Matches if the matched type is represented by the given string. +/// Matches if the matched type is represented by the given string. /// /// Given /// \code @@ -2899,7 +3005,7 @@ AST_MATCHER_P(QualType, asString, std::string, Name) { return Name == Node.getAsString(); } -/// \brief Matches if the matched type is a pointer type and the pointee type +/// Matches if the matched type is a pointer type and the pointee type /// matches the specified matcher. /// /// Example matches y->x() @@ -2916,14 +3022,14 @@ AST_MATCHER_P( InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); } -/// \brief Overloaded to match the pointee type's declaration. +/// Overloaded to match the pointee type's declaration. AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>, InnerMatcher, 1) { return pointsTo(qualType(hasDeclaration(InnerMatcher))) .matches(Node, Finder, Builder); } -/// \brief Matches if the matched type matches the unqualified desugared +/// Matches if the matched type matches the unqualified desugared /// type of the matched node. /// /// For example, in: @@ -2931,7 +3037,7 @@ AST_MATCHER_P_OVERLOAD(QualType, pointsTo, internal::Matcher<Decl>, /// class A {}; /// using B = A; /// \endcode -/// The matcher type(hasUnqualifeidDesugaredType(recordType())) matches +/// The matcher type(hasUnqualifiedDesugaredType(recordType())) matches /// both B and A. AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>, InnerMatcher) { @@ -2939,7 +3045,7 @@ AST_MATCHER_P(Type, hasUnqualifiedDesugaredType, internal::Matcher<Type>, Builder); } -/// \brief Matches if the matched type is a reference type and the referenced +/// Matches if the matched type is a reference type and the referenced /// type matches the specified matcher. /// /// Example matches X &x and const X &y @@ -2958,7 +3064,7 @@ AST_MATCHER_P(QualType, references, internal::Matcher<QualType>, InnerMatcher.matches(Node->getPointeeType(), Finder, Builder)); } -/// \brief Matches QualTypes whose canonical type matches InnerMatcher. +/// Matches QualTypes whose canonical type matches InnerMatcher. /// /// Given: /// \code @@ -2977,7 +3083,7 @@ AST_MATCHER_P(QualType, hasCanonicalType, internal::Matcher<QualType>, return InnerMatcher.matches(Node.getCanonicalType(), Finder, Builder); } -/// \brief Overloaded to match the referenced type's declaration. +/// Overloaded to match the referenced type's declaration. AST_MATCHER_P_OVERLOAD(QualType, references, internal::Matcher<Decl>, InnerMatcher, 1) { return references(qualType(hasDeclaration(InnerMatcher))) @@ -2991,7 +3097,7 @@ AST_MATCHER_P(CXXMemberCallExpr, onImplicitObjectArgument, InnerMatcher.matches(*ExprNode, Finder, Builder)); } -/// \brief Matches if the expression's type either matches the specified +/// Matches if the expression's type either matches the specified /// matcher, or is a pointer to a type that matches the InnerMatcher. AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, internal::Matcher<QualType>, InnerMatcher, 0) { @@ -3000,7 +3106,7 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, .matches(Node, Finder, Builder); } -/// \brief Overloaded to match the type's declaration. +/// Overloaded to match the type's declaration. AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, internal::Matcher<Decl>, InnerMatcher, 1) { return onImplicitObjectArgument( @@ -3008,7 +3114,7 @@ AST_MATCHER_P_OVERLOAD(CXXMemberCallExpr, thisPointerType, .matches(Node, Finder, Builder); } -/// \brief Matches a DeclRefExpr that refers to a declaration that matches the +/// Matches a DeclRefExpr that refers to a declaration that matches the /// specified matcher. /// /// Example matches x in if(x) @@ -3024,7 +3130,7 @@ AST_MATCHER_P(DeclRefExpr, to, internal::Matcher<Decl>, InnerMatcher.matches(*DeclNode, Finder, Builder)); } -/// \brief Matches a \c DeclRefExpr that refers to a declaration through a +/// Matches a \c DeclRefExpr that refers to a declaration through a /// specific using shadow declaration. /// /// Given @@ -3046,7 +3152,7 @@ AST_MATCHER_P(DeclRefExpr, throughUsingDecl, return false; } -/// \brief Matches an \c OverloadExpr if any of the declarations in the set of +/// Matches an \c OverloadExpr if any of the declarations in the set of /// overloads matches the given matcher. /// /// Given @@ -3067,7 +3173,7 @@ AST_MATCHER_P(OverloadExpr, hasAnyDeclaration, internal::Matcher<Decl>, Node.decls_end(), Finder, Builder); } -/// \brief Matches the Decl of a DeclStmt which has a single declaration. +/// Matches the Decl of a DeclStmt which has a single declaration. /// /// Given /// \code @@ -3084,7 +3190,7 @@ AST_MATCHER_P(DeclStmt, hasSingleDecl, internal::Matcher<Decl>, InnerMatcher) { return false; } -/// \brief Matches a variable declaration that has an initializer expression +/// Matches a variable declaration that has an initializer expression /// that matches the given matcher. /// /// Example matches x (matcher = varDecl(hasInitializer(callExpr()))) @@ -3100,7 +3206,7 @@ AST_MATCHER_P( InnerMatcher.matches(*Initializer, Finder, Builder)); } -/// \brief Matches a variable declaration that has function scope and is a +/// Matches a variable declaration that has function scope and is a /// non-static local variable. /// /// Example matches x (matcher = varDecl(hasLocalStorage()) @@ -3115,7 +3221,7 @@ AST_MATCHER(VarDecl, hasLocalStorage) { return Node.hasLocalStorage(); } -/// \brief Matches a variable declaration that does not have local storage. +/// Matches a variable declaration that does not have local storage. /// /// Example matches y and z (matcher = varDecl(hasGlobalStorage()) /// \code @@ -3129,7 +3235,7 @@ AST_MATCHER(VarDecl, hasGlobalStorage) { return Node.hasGlobalStorage(); } -/// \brief Matches a variable declaration that has automatic storage duration. +/// Matches a variable declaration that has automatic storage duration. /// /// Example matches x, but not y, z, or a. /// (matcher = varDecl(hasAutomaticStorageDuration()) @@ -3145,7 +3251,7 @@ AST_MATCHER(VarDecl, hasAutomaticStorageDuration) { return Node.getStorageDuration() == SD_Automatic; } -/// \brief Matches a variable declaration that has static storage duration. +/// Matches a variable declaration that has static storage duration. /// It includes the variable declared at namespace scope and those declared /// with "static" and "extern" storage class specifiers. /// @@ -3165,7 +3271,7 @@ AST_MATCHER(VarDecl, hasStaticStorageDuration) { return Node.getStorageDuration() == SD_Static; } -/// \brief Matches a variable declaration that has thread storage duration. +/// Matches a variable declaration that has thread storage duration. /// /// Example matches z, but not x, z, or a. /// (matcher = varDecl(hasThreadStorageDuration()) @@ -3181,7 +3287,7 @@ AST_MATCHER(VarDecl, hasThreadStorageDuration) { return Node.getStorageDuration() == SD_Thread; } -/// \brief Matches a variable declaration that is an exception variable from +/// Matches a variable declaration that is an exception variable from /// a C++ catch block, or an Objective-C \@catch statement. /// /// Example matches x (matcher = varDecl(isExceptionVariable()) @@ -3196,7 +3302,7 @@ AST_MATCHER(VarDecl, isExceptionVariable) { return Node.isExceptionVariable(); } -/// \brief Checks that a call expression or a constructor call expression has +/// Checks that a call expression or a constructor call expression has /// a specific number of arguments (including absent default arguments). /// /// Example matches f(0, 0) (matcher = callExpr(argumentCountIs(2))) @@ -3212,7 +3318,7 @@ AST_POLYMORPHIC_MATCHER_P(argumentCountIs, return Node.getNumArgs() == N; } -/// \brief Matches the n'th argument of a call expression or a constructor +/// Matches the n'th argument of a call expression or a constructor /// call expression. /// /// Example matches y in x(y) @@ -3230,7 +3336,7 @@ AST_POLYMORPHIC_MATCHER_P2(hasArgument, *Node.getArg(N)->IgnoreParenImpCasts(), Finder, Builder)); } -/// \brief Matches declaration statements that contain a specific number of +/// Matches declaration statements that contain a specific number of /// declarations. /// /// Example: Given @@ -3245,7 +3351,7 @@ AST_MATCHER_P(DeclStmt, declCountIs, unsigned, N) { return std::distance(Node.decl_begin(), Node.decl_end()) == (ptrdiff_t)N; } -/// \brief Matches the n'th declaration of a declaration statement. +/// Matches the n'th declaration of a declaration statement. /// /// Note that this does not work for global declarations because the AST /// breaks up multiple-declaration DeclStmt's into multiple single-declaration @@ -3274,7 +3380,7 @@ AST_MATCHER_P2(DeclStmt, containsDeclaration, unsigned, N, return InnerMatcher.matches(**Iterator, Finder, Builder); } -/// \brief Matches a C++ catch statement that has a catch-all handler. +/// Matches a C++ catch statement that has a catch-all handler. /// /// Given /// \code @@ -3291,7 +3397,7 @@ AST_MATCHER(CXXCatchStmt, isCatchAll) { return Node.getExceptionDecl() == nullptr; } -/// \brief Matches a constructor initializer. +/// Matches a constructor initializer. /// /// Given /// \code @@ -3310,7 +3416,7 @@ AST_MATCHER_P(CXXConstructorDecl, hasAnyConstructorInitializer, Node.init_end(), Finder, Builder); } -/// \brief Matches the field declaration of a constructor initializer. +/// Matches the field declaration of a constructor initializer. /// /// Given /// \code @@ -3330,7 +3436,7 @@ AST_MATCHER_P(CXXCtorInitializer, forField, InnerMatcher.matches(*NodeAsDecl, Finder, Builder)); } -/// \brief Matches the initializer expression of a constructor initializer. +/// Matches the initializer expression of a constructor initializer. /// /// Given /// \code @@ -3350,7 +3456,7 @@ AST_MATCHER_P(CXXCtorInitializer, withInitializer, InnerMatcher.matches(*NodeAsExpr, Finder, Builder)); } -/// \brief Matches a constructor initializer if it is explicitly written in +/// Matches a constructor initializer if it is explicitly written in /// code (as opposed to implicitly added by the compiler). /// /// Given @@ -3367,7 +3473,7 @@ AST_MATCHER(CXXCtorInitializer, isWritten) { return Node.isWritten(); } -/// \brief Matches a constructor initializer if it is initializing a base, as +/// Matches a constructor initializer if it is initializing a base, as /// opposed to a member. /// /// Given @@ -3387,7 +3493,7 @@ AST_MATCHER(CXXCtorInitializer, isBaseInitializer) { return Node.isBaseInitializer(); } -/// \brief Matches a constructor initializer if it is initializing a member, as +/// Matches a constructor initializer if it is initializing a member, as /// opposed to a base. /// /// Given @@ -3407,8 +3513,8 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) { return Node.isMemberInitializer(); } -/// \brief Matches any argument of a call expression or a constructor call -/// expression. +/// Matches any argument of a call expression or a constructor call +/// expression, or an ObjC-message-send expression. /// /// Given /// \code @@ -3418,9 +3524,18 @@ AST_MATCHER(CXXCtorInitializer, isMemberInitializer) { /// matches x(1, y, 42) /// with hasAnyArgument(...) /// matching y +/// +/// For ObjectiveC, given +/// \code +/// @interface I - (void) f:(int) y; @end +/// void foo(I *i) { [i f:12]; } +/// \endcode +/// objcMessageExpr(hasAnyArgument(integerLiteral(equals(12)))) +/// matches [i f:12] AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, AST_POLYMORPHIC_SUPPORTED_TYPES(CallExpr, - CXXConstructExpr), + CXXConstructExpr, + ObjCMessageExpr), internal::Matcher<Expr>, InnerMatcher) { for (const Expr *Arg : Node.arguments()) { BoundNodesTreeBuilder Result(*Builder); @@ -3432,12 +3547,12 @@ AST_POLYMORPHIC_MATCHER_P(hasAnyArgument, return false; } -/// \brief Matches a constructor call expression which uses list initialization. +/// Matches a constructor call expression which uses list initialization. AST_MATCHER(CXXConstructExpr, isListInitialization) { return Node.isListInitialization(); } -/// \brief Matches a constructor call expression which requires +/// Matches a constructor call expression which requires /// zero initialization. /// /// Given @@ -3453,7 +3568,8 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) { return Node.requiresZeroInitialization(); } -/// \brief Matches the n'th parameter of a function declaration. +/// Matches the n'th parameter of a function or an ObjC method +/// declaration or a block. /// /// Given /// \code @@ -3463,15 +3579,26 @@ AST_MATCHER(CXXConstructExpr, requiresZeroInitialization) { /// matches f(int x) {} /// with hasParameter(...) /// matching int x -AST_MATCHER_P2(FunctionDecl, hasParameter, - unsigned, N, internal::Matcher<ParmVarDecl>, - InnerMatcher) { - return (N < Node.getNumParams() && - InnerMatcher.matches( - *Node.getParamDecl(N), Finder, Builder)); +/// +/// For ObjectiveC, given +/// \code +/// @interface I - (void) f:(int) y; @end +/// \endcode +// +/// the matcher objcMethodDecl(hasParameter(0, hasName("y"))) +/// matches the declaration of method f with hasParameter +/// matching y. +AST_POLYMORPHIC_MATCHER_P2(hasParameter, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + ObjCMethodDecl, + BlockDecl), + unsigned, N, internal::Matcher<ParmVarDecl>, + InnerMatcher) { + return (N < Node.parameters().size() + && InnerMatcher.matches(*Node.parameters()[N], Finder, Builder)); } -/// \brief Matches all arguments and their respective ParmVarDecl. +/// Matches all arguments and their respective ParmVarDecl. /// /// Given /// \code @@ -3525,7 +3652,8 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam, return Matched; } -/// \brief Matches any parameter of a function declaration. +/// Matches any parameter of a function or an ObjC method declaration or a +/// block. /// /// Does not match the 'this' parameter of a method. /// @@ -3537,13 +3665,35 @@ AST_POLYMORPHIC_MATCHER_P2(forEachArgumentWithParam, /// matches f(int x, int y, int z) {} /// with hasAnyParameter(...) /// matching int y -AST_MATCHER_P(FunctionDecl, hasAnyParameter, - internal::Matcher<ParmVarDecl>, InnerMatcher) { +/// +/// For ObjectiveC, given +/// \code +/// @interface I - (void) f:(int) y; @end +/// \endcode +// +/// the matcher objcMethodDecl(hasAnyParameter(hasName("y"))) +/// matches the declaration of method f with hasParameter +/// matching y. +/// +/// For blocks, given +/// \code +/// b = ^(int y) { printf("%d", y) }; +/// \endcode +/// +/// the matcher blockDecl(hasAnyParameter(hasName("y"))) +/// matches the declaration of the block b with hasParameter +/// matching y. +AST_POLYMORPHIC_MATCHER_P(hasAnyParameter, + AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, + ObjCMethodDecl, + BlockDecl), + internal::Matcher<ParmVarDecl>, + InnerMatcher) { return matchesFirstInPointerRange(InnerMatcher, Node.param_begin(), Node.param_end(), Finder, Builder); } -/// \brief Matches \c FunctionDecls and \c FunctionProtoTypes that have a +/// Matches \c FunctionDecls and \c FunctionProtoTypes that have a /// specific parameter count. /// /// Given @@ -3555,11 +3705,11 @@ AST_MATCHER_P(FunctionDecl, hasAnyParameter, /// void k(int x, int y, int z, ...); /// \endcode /// functionDecl(parameterCountIs(2)) -/// matches void g(int i, int j) {} +/// matches \c g and \c h /// functionProtoType(parameterCountIs(2)) -/// matches void h(int i, int j) +/// matches \c g and \c h /// functionProtoType(parameterCountIs(3)) -/// matches void k(int x, int y, int z, ...); +/// matches \c k AST_POLYMORPHIC_MATCHER_P(parameterCountIs, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, FunctionProtoType), @@ -3567,7 +3717,23 @@ AST_POLYMORPHIC_MATCHER_P(parameterCountIs, return Node.getNumParams() == N; } -/// \brief Matches the return type of a function declaration. +/// Matches \c FunctionDecls that have a noreturn attribute. +/// +/// Given +/// \code +/// void nope(); +/// [[noreturn]] void a(); +/// __attribute__((noreturn)) void b(); +/// struct c { [[noreturn]] c(); }; +/// \endcode +/// functionDecl(isNoReturn()) +/// matches all of those except +/// \code +/// void nope(); +/// \endcode +AST_MATCHER(FunctionDecl, isNoReturn) { return Node.isNoReturn(); } + +/// Matches the return type of a function declaration. /// /// Given: /// \code @@ -3580,7 +3746,7 @@ AST_MATCHER_P(FunctionDecl, returns, return InnerMatcher.matches(Node.getReturnType(), Finder, Builder); } -/// \brief Matches extern "C" function or variable declarations. +/// Matches extern "C" function or variable declarations. /// /// Given: /// \code @@ -3600,7 +3766,7 @@ AST_POLYMORPHIC_MATCHER(isExternC, AST_POLYMORPHIC_SUPPORTED_TYPES(FunctionDecl, return Node.isExternC(); } -/// \brief Matches variable/function declarations that have "static" storage +/// Matches variable/function declarations that have "static" storage /// class specifier ("static" keyword) written in the source. /// /// Given: @@ -3620,7 +3786,7 @@ AST_POLYMORPHIC_MATCHER(isStaticStorageClass, return Node.getStorageClass() == SC_Static; } -/// \brief Matches deleted function declarations. +/// Matches deleted function declarations. /// /// Given: /// \code @@ -3633,7 +3799,7 @@ AST_MATCHER(FunctionDecl, isDeleted) { return Node.isDeleted(); } -/// \brief Matches defaulted function declarations. +/// Matches defaulted function declarations. /// /// Given: /// \code @@ -3646,7 +3812,7 @@ AST_MATCHER(FunctionDecl, isDefaulted) { return Node.isDefaulted(); } -/// \brief Matches functions that have a dynamic exception specification. +/// Matches functions that have a dynamic exception specification. /// /// Given: /// \code @@ -3669,7 +3835,7 @@ AST_POLYMORPHIC_MATCHER(hasDynamicExceptionSpec, return false; } -/// \brief Matches functions that have a non-throwing exception specification. +/// Matches functions that have a non-throwing exception specification. /// /// Given: /// \code @@ -3696,27 +3862,32 @@ AST_POLYMORPHIC_MATCHER(isNoThrow, if (isUnresolvedExceptionSpec(FnTy->getExceptionSpecType())) return true; - return FnTy->isNothrow(Finder->getASTContext()); + return FnTy->isNothrow(); } -/// \brief Matches constexpr variable and function declarations. +/// Matches constexpr variable and function declarations, +/// and if constexpr. /// /// Given: /// \code /// constexpr int foo = 42; /// constexpr int bar(); +/// void baz() { if constexpr(1 > 0) {} } /// \endcode /// varDecl(isConstexpr()) /// matches the declaration of foo. /// functionDecl(isConstexpr()) /// matches the declaration of bar. +/// ifStmt(isConstexpr()) +/// matches the if statement in baz. AST_POLYMORPHIC_MATCHER(isConstexpr, AST_POLYMORPHIC_SUPPORTED_TYPES(VarDecl, - FunctionDecl)) { + FunctionDecl, + IfStmt)) { return Node.isConstexpr(); } -/// \brief Matches the condition expression of an if statement, for loop, +/// Matches the condition expression of an if statement, for loop, /// switch statement or conditional operator. /// /// Example matches true (matcher = hasCondition(cxxBoolLiteral(equals(true)))) @@ -3733,7 +3904,7 @@ AST_POLYMORPHIC_MATCHER_P( InnerMatcher.matches(*Condition, Finder, Builder)); } -/// \brief Matches the then-statement of an if statement. +/// Matches the then-statement of an if statement. /// /// Examples matches the if statement /// (matcher = ifStmt(hasThen(cxxBoolLiteral(equals(true))))) @@ -3745,7 +3916,7 @@ AST_MATCHER_P(IfStmt, hasThen, internal::Matcher<Stmt>, InnerMatcher) { return (Then != nullptr && InnerMatcher.matches(*Then, Finder, Builder)); } -/// \brief Matches the else-statement of an if statement. +/// Matches the else-statement of an if statement. /// /// Examples matches the if statement /// (matcher = ifStmt(hasElse(cxxBoolLiteral(equals(true))))) @@ -3757,7 +3928,7 @@ AST_MATCHER_P(IfStmt, hasElse, internal::Matcher<Stmt>, InnerMatcher) { return (Else != nullptr && InnerMatcher.matches(*Else, Finder, Builder)); } -/// \brief Matches if a node equals a previously bound node. +/// Matches if a node equals a previously bound node. /// /// Matches a node if it equals the node previously bound to \p ID. /// @@ -3794,7 +3965,7 @@ AST_POLYMORPHIC_MATCHER_P(equalsBoundNode, return Builder->removeBindings(Predicate); } -/// \brief Matches the condition variable statement in an if statement. +/// Matches the condition variable statement in an if statement. /// /// Given /// \code @@ -3810,7 +3981,7 @@ AST_MATCHER_P(IfStmt, hasConditionVariableStatement, InnerMatcher.matches(*DeclarationStatement, Finder, Builder); } -/// \brief Matches the index expression of an array subscript expression. +/// Matches the index expression of an array subscript expression. /// /// Given /// \code @@ -3826,7 +3997,7 @@ AST_MATCHER_P(ArraySubscriptExpr, hasIndex, return false; } -/// \brief Matches the base expression of an array subscript expression. +/// Matches the base expression of an array subscript expression. /// /// Given /// \code @@ -3843,7 +4014,7 @@ AST_MATCHER_P(ArraySubscriptExpr, hasBase, return false; } -/// \brief Matches a 'for', 'while', 'do while' statement or a function +/// Matches a 'for', 'while', 'do while' statement or a function /// definition that has a given body. /// /// Given @@ -3865,7 +4036,7 @@ AST_POLYMORPHIC_MATCHER_P(hasBody, InnerMatcher.matches(*Statement, Finder, Builder)); } -/// \brief Matches compound statements where at least one substatement matches +/// Matches compound statements where at least one substatement matches /// a given matcher. Also matches StmtExprs that have CompoundStmt as children. /// /// Given @@ -3885,7 +4056,7 @@ AST_POLYMORPHIC_MATCHER_P(hasAnySubstatement, CS->body_end(), Finder, Builder); } -/// \brief Checks that a compound statement contains a specific number of +/// Checks that a compound statement contains a specific number of /// child statements. /// /// Example: Given @@ -3899,7 +4070,7 @@ AST_MATCHER_P(CompoundStmt, statementCountIs, unsigned, N) { return Node.size() == N; } -/// \brief Matches literals that are equal to the given value of type ValueT. +/// Matches literals that are equal to the given value of type ValueT. /// /// Given /// \code @@ -3960,7 +4131,7 @@ AST_POLYMORPHIC_MATCHER_P_OVERLOAD(equals, .matchesNode(Node); } -/// \brief Matches the operator Name of operator expressions (binary or +/// Matches the operator Name of operator expressions (binary or /// unary). /// /// Example matches a || b (matcher = binaryOperator(hasOperatorName("||"))) @@ -3974,7 +4145,27 @@ AST_POLYMORPHIC_MATCHER_P(hasOperatorName, return Name == Node.getOpcodeStr(Node.getOpcode()); } -/// \brief Matches the left hand side of binary operator expressions. +/// Matches all kinds of assignment operators. +/// +/// Example 1: matches a += b (matcher = binaryOperator(isAssignmentOperator())) +/// \code +/// if (a == b) +/// a += b; +/// \endcode +/// +/// Example 2: matches s1 = s2 +/// (matcher = cxxOperatorCallExpr(isAssignmentOperator())) +/// \code +/// struct S { S& operator=(const S&); }; +/// void x() { S s1, s2; s1 = s2; }) +/// \endcode +AST_POLYMORPHIC_MATCHER(isAssignmentOperator, + AST_POLYMORPHIC_SUPPORTED_TYPES(BinaryOperator, + CXXOperatorCallExpr)) { + return Node.isAssignmentOp(); +} + +/// Matches the left hand side of binary operator expressions. /// /// Example matches a (matcher = binaryOperator(hasLHS())) /// \code @@ -3989,7 +4180,7 @@ AST_POLYMORPHIC_MATCHER_P(hasLHS, InnerMatcher.matches(*LeftHandSide, Finder, Builder)); } -/// \brief Matches the right hand side of binary operator expressions. +/// Matches the right hand side of binary operator expressions. /// /// Example matches b (matcher = binaryOperator(hasRHS())) /// \code @@ -4004,14 +4195,14 @@ AST_POLYMORPHIC_MATCHER_P(hasRHS, InnerMatcher.matches(*RightHandSide, Finder, Builder)); } -/// \brief Matches if either the left hand side or the right hand side of a +/// Matches if either the left hand side or the right hand side of a /// binary operator matches. inline internal::Matcher<BinaryOperator> hasEitherOperand( const internal::Matcher<Expr> &InnerMatcher) { return anyOf(hasLHS(InnerMatcher), hasRHS(InnerMatcher)); } -/// \brief Matches if the operand of a unary operator matches. +/// Matches if the operand of a unary operator matches. /// /// Example matches true (matcher = hasUnaryOperand( /// cxxBoolLiteral(equals(true)))) @@ -4025,7 +4216,7 @@ AST_MATCHER_P(UnaryOperator, hasUnaryOperand, InnerMatcher.matches(*Operand, Finder, Builder)); } -/// \brief Matches if the cast's source expression +/// Matches if the cast's source expression /// or opaque value's source expression matches the given matcher. /// /// Example 1: matches "a string" @@ -4050,7 +4241,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSourceExpression, InnerMatcher.matches(*SubExpression, Finder, Builder)); } -/// \brief Matches casts that has a given cast kind. +/// Matches casts that has a given cast kind. /// /// Example: matches the implicit cast around \c 0 /// (matcher = castExpr(hasCastKind(CK_NullToPointer))) @@ -4061,7 +4252,7 @@ AST_MATCHER_P(CastExpr, hasCastKind, CastKind, Kind) { return Node.getCastKind() == Kind; } -/// \brief Matches casts whose destination type matches a given matcher. +/// Matches casts whose destination type matches a given matcher. /// /// (Note: Clang's AST refers to other conversions as "casts" too, and calls /// actual casts "explicit" casts.) @@ -4071,7 +4262,7 @@ AST_MATCHER_P(ExplicitCastExpr, hasDestinationType, return InnerMatcher.matches(NodeType, Finder, Builder); } -/// \brief Matches implicit casts whose destination type matches a given +/// Matches implicit casts whose destination type matches a given /// matcher. /// /// FIXME: Unit test this matcher @@ -4080,7 +4271,7 @@ AST_MATCHER_P(ImplicitCastExpr, hasImplicitDestinationType, return InnerMatcher.matches(Node.getType(), Finder, Builder); } -/// \brief Matches RecordDecl object that are spelled with "struct." +/// Matches RecordDecl object that are spelled with "struct." /// /// Example matches S, but not C or U. /// \code @@ -4092,7 +4283,7 @@ AST_MATCHER(RecordDecl, isStruct) { return Node.isStruct(); } -/// \brief Matches RecordDecl object that are spelled with "union." +/// Matches RecordDecl object that are spelled with "union." /// /// Example matches U, but not C or S. /// \code @@ -4104,7 +4295,7 @@ AST_MATCHER(RecordDecl, isUnion) { return Node.isUnion(); } -/// \brief Matches RecordDecl object that are spelled with "class." +/// Matches RecordDecl object that are spelled with "class." /// /// Example matches C, but not S or U. /// \code @@ -4116,7 +4307,7 @@ AST_MATCHER(RecordDecl, isClass) { return Node.isClass(); } -/// \brief Matches the true branch expression of a conditional operator. +/// Matches the true branch expression of a conditional operator. /// /// Example 1 (conditional ternary operator): matches a /// \code @@ -4134,7 +4325,7 @@ AST_MATCHER_P(AbstractConditionalOperator, hasTrueExpression, InnerMatcher.matches(*Expression, Finder, Builder)); } -/// \brief Matches the false branch expression of a conditional operator +/// Matches the false branch expression of a conditional operator /// (binary or ternary). /// /// Example matches b @@ -4149,7 +4340,7 @@ AST_MATCHER_P(AbstractConditionalOperator, hasFalseExpression, InnerMatcher.matches(*Expression, Finder, Builder)); } -/// \brief Matches if a declaration has a body attached. +/// Matches if a declaration has a body attached. /// /// Example matches A, va, fa /// \code @@ -4176,7 +4367,7 @@ AST_POLYMORPHIC_MATCHER(isDefinition, return Node.isThisDeclarationADefinition(); } -/// \brief Matches if a function declaration is variadic. +/// Matches if a function declaration is variadic. /// /// Example matches f, but not g or h. The function i will not match, even when /// compiled in C mode. @@ -4190,7 +4381,7 @@ AST_MATCHER(FunctionDecl, isVariadic) { return Node.isVariadic(); } -/// \brief Matches the class declaration that the given method declaration +/// Matches the class declaration that the given method declaration /// belongs to. /// /// FIXME: Generalize this for other kinds of declarations. @@ -4214,7 +4405,7 @@ AST_MATCHER_P(CXXMethodDecl, ofClass, InnerMatcher.matches(*Parent, Finder, Builder)); } -/// \brief Matches each method overriden by the given method. This matcher may +/// Matches each method overridden by the given method. This matcher may /// produce multiple matches. /// /// Given @@ -4255,7 +4446,7 @@ AST_MATCHER_P(CXXMethodDecl, forEachOverridden, return Matched; } -/// \brief Matches if the given method declaration is virtual. +/// Matches if the given method declaration is virtual. /// /// Given /// \code @@ -4269,7 +4460,7 @@ AST_MATCHER(CXXMethodDecl, isVirtual) { return Node.isVirtual(); } -/// \brief Matches if the given method declaration has an explicit "virtual". +/// Matches if the given method declaration has an explicit "virtual". /// /// Given /// \code @@ -4287,7 +4478,7 @@ AST_MATCHER(CXXMethodDecl, isVirtualAsWritten) { return Node.isVirtualAsWritten(); } -/// \brief Matches if the given method or class declaration is final. +/// Matches if the given method or class declaration is final. /// /// Given: /// \code @@ -4308,7 +4499,7 @@ AST_POLYMORPHIC_MATCHER(isFinal, return Node.template hasAttr<FinalAttr>(); } -/// \brief Matches if the given method declaration is pure. +/// Matches if the given method declaration is pure. /// /// Given /// \code @@ -4322,7 +4513,7 @@ AST_MATCHER(CXXMethodDecl, isPure) { return Node.isPure(); } -/// \brief Matches if the given method declaration is const. +/// Matches if the given method declaration is const. /// /// Given /// \code @@ -4337,7 +4528,7 @@ AST_MATCHER(CXXMethodDecl, isConst) { return Node.isConst(); } -/// \brief Matches if the given method declaration declares a copy assignment +/// Matches if the given method declaration declares a copy assignment /// operator. /// /// Given @@ -4354,7 +4545,7 @@ AST_MATCHER(CXXMethodDecl, isCopyAssignmentOperator) { return Node.isCopyAssignmentOperator(); } -/// \brief Matches if the given method declaration declares a move assignment +/// Matches if the given method declaration declares a move assignment /// operator. /// /// Given @@ -4371,7 +4562,7 @@ AST_MATCHER(CXXMethodDecl, isMoveAssignmentOperator) { return Node.isMoveAssignmentOperator(); } -/// \brief Matches if the given method declaration overrides another method. +/// Matches if the given method declaration overrides another method. /// /// Given /// \code @@ -4389,7 +4580,7 @@ AST_MATCHER(CXXMethodDecl, isOverride) { return Node.size_overridden_methods() > 0 || Node.hasAttr<OverrideAttr>(); } -/// \brief Matches method declarations that are user-provided. +/// Matches method declarations that are user-provided. /// /// Given /// \code @@ -4404,7 +4595,7 @@ AST_MATCHER(CXXMethodDecl, isUserProvided) { return Node.isUserProvided(); } -/// \brief Matches member expressions that are called with '->' as opposed +/// Matches member expressions that are called with '->' as opposed /// to '.'. /// /// Member calls on the implicit this pointer match as called with '->'. @@ -4423,7 +4614,7 @@ AST_MATCHER(MemberExpr, isArrow) { return Node.isArrow(); } -/// \brief Matches QualType nodes that are of integer type. +/// Matches QualType nodes that are of integer type. /// /// Given /// \code @@ -4437,7 +4628,7 @@ AST_MATCHER(QualType, isInteger) { return Node->isIntegerType(); } -/// \brief Matches QualType nodes that are of unsigned integer type. +/// Matches QualType nodes that are of unsigned integer type. /// /// Given /// \code @@ -4451,7 +4642,7 @@ AST_MATCHER(QualType, isUnsignedInteger) { return Node->isUnsignedIntegerType(); } -/// \brief Matches QualType nodes that are of signed integer type. +/// Matches QualType nodes that are of signed integer type. /// /// Given /// \code @@ -4465,7 +4656,7 @@ AST_MATCHER(QualType, isSignedInteger) { return Node->isSignedIntegerType(); } -/// \brief Matches QualType nodes that are of character type. +/// Matches QualType nodes that are of character type. /// /// Given /// \code @@ -4479,7 +4670,7 @@ AST_MATCHER(QualType, isAnyCharacter) { return Node->isAnyCharacterType(); } -/// \brief Matches QualType nodes that are of any pointer type; this includes +/// Matches QualType nodes that are of any pointer type; this includes /// the Objective-C object pointer type, which is different despite being /// syntactically similar. /// @@ -4499,7 +4690,7 @@ AST_MATCHER(QualType, isAnyPointer) { return Node->isAnyPointerType(); } -/// \brief Matches QualType nodes that are const-qualified, i.e., that +/// Matches QualType nodes that are const-qualified, i.e., that /// include "top-level" const. /// /// Given @@ -4518,7 +4709,7 @@ AST_MATCHER(QualType, isConstQualified) { return Node.isConstQualified(); } -/// \brief Matches QualType nodes that are volatile-qualified, i.e., that +/// Matches QualType nodes that are volatile-qualified, i.e., that /// include "top-level" volatile. /// /// Given @@ -4537,7 +4728,7 @@ AST_MATCHER(QualType, isVolatileQualified) { return Node.isVolatileQualified(); } -/// \brief Matches QualType nodes that have local CV-qualifiers attached to +/// Matches QualType nodes that have local CV-qualifiers attached to /// the node, not hidden within a typedef. /// /// Given @@ -4554,7 +4745,7 @@ AST_MATCHER(QualType, hasLocalQualifiers) { return Node.hasLocalQualifiers(); } -/// \brief Matches a member expression where the member is matched by a +/// Matches a member expression where the member is matched by a /// given matcher. /// /// Given @@ -4571,7 +4762,7 @@ AST_MATCHER_P(MemberExpr, member, return InnerMatcher.matches(*Node.getMemberDecl(), Finder, Builder); } -/// \brief Matches a member expression where the object expression is +/// Matches a member expression where the object expression is /// matched by a given matcher. /// /// Given @@ -4588,7 +4779,7 @@ AST_MATCHER_P(MemberExpr, hasObjectExpression, return InnerMatcher.matches(*Node.getBase(), Finder, Builder); } -/// \brief Matches any using shadow declaration. +/// Matches any using shadow declaration. /// /// Given /// \code @@ -4603,7 +4794,7 @@ AST_MATCHER_P(UsingDecl, hasAnyUsingShadowDecl, Node.shadow_end(), Finder, Builder); } -/// \brief Matches a using shadow declaration where the target declaration is +/// Matches a using shadow declaration where the target declaration is /// matched by the given matcher. /// /// Given @@ -4620,7 +4811,7 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, return InnerMatcher.matches(*Node.getTargetDecl(), Finder, Builder); } -/// \brief Matches template instantiations of function, class, or static +/// Matches template instantiations of function, class, or static /// member variable template instantiations. /// /// Given @@ -4631,6 +4822,10 @@ AST_MATCHER_P(UsingShadowDecl, hasTargetDecl, /// \code /// template <typename T> class X {}; class A {}; template class X<A>; /// \endcode +/// or +/// \code +/// template <typename T> class X {}; class A {}; extern template class X<A>; +/// \endcode /// cxxRecordDecl(hasName("::X"), isTemplateInstantiation()) /// matches the template instantiation of X<A>. /// @@ -4648,10 +4843,12 @@ AST_POLYMORPHIC_MATCHER(isTemplateInstantiation, CXXRecordDecl)) { return (Node.getTemplateSpecializationKind() == TSK_ImplicitInstantiation || Node.getTemplateSpecializationKind() == - TSK_ExplicitInstantiationDefinition); + TSK_ExplicitInstantiationDefinition || + Node.getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDeclaration); } -/// \brief Matches declarations that are template instantiations or are inside +/// Matches declarations that are template instantiations or are inside /// template instantiations. /// /// Given @@ -4668,7 +4865,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Decl>, isInstantiated) { return decl(anyOf(IsInstantiation, hasAncestor(IsInstantiation))); } -/// \brief Matches statements inside of a template instantiation. +/// Matches statements inside of a template instantiation. /// /// Given /// \code @@ -4688,7 +4885,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Stmt>, isInTemplateInstantiation) { functionDecl(isTemplateInstantiation()))))); } -/// \brief Matches explicit template specializations of function, class, or +/// Matches explicit template specializations of function, class, or /// static member variable template instantiations. /// /// Given @@ -4706,7 +4903,7 @@ AST_POLYMORPHIC_MATCHER(isExplicitTemplateSpecialization, return (Node.getTemplateSpecializationKind() == TSK_ExplicitSpecialization); } -/// \brief Matches \c TypeLocs for which the given inner +/// Matches \c TypeLocs for which the given inner /// QualType-matcher matches. AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc, internal::Matcher<QualType>, InnerMatcher, 0) { @@ -4714,7 +4911,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD(internal::BindableMatcher<TypeLoc>, loc, new internal::TypeLocTypeMatcher(InnerMatcher)); } -/// \brief Matches type \c bool. +/// Matches type \c bool. /// /// Given /// \code @@ -4726,7 +4923,7 @@ AST_MATCHER(Type, booleanType) { return Node.isBooleanType(); } -/// \brief Matches type \c void. +/// Matches type \c void. /// /// Given /// \code @@ -4741,7 +4938,7 @@ AST_MATCHER(Type, voidType) { template <typename NodeType> using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>; -/// \brief Matches builtin Types. +/// Matches builtin Types. /// /// Given /// \code @@ -4755,7 +4952,7 @@ using AstTypeMatcher = internal::VariadicDynCastAllOfMatcher<Type, NodeType>; /// matches "int b", "float c" and "bool d" extern const AstTypeMatcher<BuiltinType> builtinType; -/// \brief Matches all kinds of arrays. +/// Matches all kinds of arrays. /// /// Given /// \code @@ -4767,7 +4964,7 @@ extern const AstTypeMatcher<BuiltinType> builtinType; /// matches "int a[]", "int b[4]" and "int c[a[0]]"; extern const AstTypeMatcher<ArrayType> arrayType; -/// \brief Matches C99 complex types. +/// Matches C99 complex types. /// /// Given /// \code @@ -4777,7 +4974,7 @@ extern const AstTypeMatcher<ArrayType> arrayType; /// matches "_Complex float f" extern const AstTypeMatcher<ComplexType> complexType; -/// \brief Matches any real floating-point type (float, double, long double). +/// Matches any real floating-point type (float, double, long double). /// /// Given /// \code @@ -4790,7 +4987,7 @@ AST_MATCHER(Type, realFloatingPointType) { return Node.isRealFloatingType(); } -/// \brief Matches arrays and C99 complex types that have a specific element +/// Matches arrays and C99 complex types that have a specific element /// type. /// /// Given @@ -4807,7 +5004,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement, AST_POLYMORPHIC_SUPPORTED_TYPES(ArrayType, ComplexType)); -/// \brief Matches C arrays with a specified constant size. +/// Matches C arrays with a specified constant size. /// /// Given /// \code @@ -4821,7 +5018,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasElementType, getElement, /// matches "int a[2]" extern const AstTypeMatcher<ConstantArrayType> constantArrayType; -/// \brief Matches nodes that have the specified size. +/// Matches nodes that have the specified size. /// /// Given /// \code @@ -4843,7 +5040,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSize, return internal::HasSizeMatcher<NodeType>::hasSize(Node, N); } -/// \brief Matches C++ arrays whose size is a value-dependent expression. +/// Matches C++ arrays whose size is a value-dependent expression. /// /// Given /// \code @@ -4856,7 +5053,7 @@ AST_POLYMORPHIC_MATCHER_P(hasSize, /// matches "T data[Size]" extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType; -/// \brief Matches C arrays with unspecified size. +/// Matches C arrays with unspecified size. /// /// Given /// \code @@ -4868,7 +5065,7 @@ extern const AstTypeMatcher<DependentSizedArrayType> dependentSizedArrayType; /// matches "int a[]" and "int c[]" extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType; -/// \brief Matches C arrays with a specified size that is not an +/// Matches C arrays with a specified size that is not an /// integer-constant-expression. /// /// Given @@ -4883,7 +5080,7 @@ extern const AstTypeMatcher<IncompleteArrayType> incompleteArrayType; /// matches "int c[a[0]]" extern const AstTypeMatcher<VariableArrayType> variableArrayType; -/// \brief Matches \c VariableArrayType nodes that have a specific size +/// Matches \c VariableArrayType nodes that have a specific size /// expression. /// /// Given @@ -4900,7 +5097,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr, return InnerMatcher.matches(*Node.getSizeExpr(), Finder, Builder); } -/// \brief Matches atomic types. +/// Matches atomic types. /// /// Given /// \code @@ -4910,7 +5107,7 @@ AST_MATCHER_P(VariableArrayType, hasSizeExpr, /// matches "_Atomic(int) i" extern const AstTypeMatcher<AtomicType> atomicType; -/// \brief Matches atomic types with a specific value type. +/// Matches atomic types with a specific value type. /// /// Given /// \code @@ -4924,7 +5121,7 @@ extern const AstTypeMatcher<AtomicType> atomicType; AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue, AST_POLYMORPHIC_SUPPORTED_TYPES(AtomicType)); -/// \brief Matches types nodes representing C++11 auto types. +/// Matches types nodes representing C++11 auto types. /// /// Given: /// \code @@ -4936,7 +5133,19 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL(hasValueType, getValue, /// matches "auto n" and "auto i" extern const AstTypeMatcher<AutoType> autoType; -/// \brief Matches \c AutoType nodes where the deduced type is a specific type. +/// Matches types nodes representing C++11 decltype(<expr>) types. +/// +/// Given: +/// \code +/// short i = 1; +/// int j = 42; +/// decltype(i + j) result = i + j; +/// \endcode +/// decltypeType() +/// matches "decltype(i + j)" +extern const AstTypeMatcher<DecltypeType> decltypeType; + +/// Matches \c AutoType nodes where the deduced type is a specific type. /// /// Note: There is no \c TypeLoc for the deduced type and thus no /// \c getDeducedLoc() matcher. @@ -4953,7 +5162,21 @@ extern const AstTypeMatcher<AutoType> autoType; AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, AST_POLYMORPHIC_SUPPORTED_TYPES(AutoType)); -/// \brief Matches \c FunctionType nodes. +/// Matches \c DecltypeType nodes to find out the underlying type. +/// +/// Given +/// \code +/// decltype(1) a = 1; +/// decltype(2.0) b = 2.0; +/// \endcode +/// decltypeType(hasUnderlyingType(isInteger())) +/// matches "auto a" +/// +/// Usable as: Matcher<DecltypeType> +AST_TYPE_TRAVERSE_MATCHER(hasUnderlyingType, getUnderlyingType, + AST_POLYMORPHIC_SUPPORTED_TYPES(DecltypeType)); + +/// Matches \c FunctionType nodes. /// /// Given /// \code @@ -4964,7 +5187,7 @@ AST_TYPE_TRAVERSE_MATCHER(hasDeducedType, getDeducedType, /// matches "int (*f)(int)" and the type of "g". extern const AstTypeMatcher<FunctionType> functionType; -/// \brief Matches \c FunctionProtoType nodes. +/// Matches \c FunctionProtoType nodes. /// /// Given /// \code @@ -4976,7 +5199,7 @@ extern const AstTypeMatcher<FunctionType> functionType; /// In C mode, "g" is not matched because it does not contain a prototype. extern const AstTypeMatcher<FunctionProtoType> functionProtoType; -/// \brief Matches \c ParenType nodes. +/// Matches \c ParenType nodes. /// /// Given /// \code @@ -4988,7 +5211,7 @@ extern const AstTypeMatcher<FunctionProtoType> functionProtoType; /// \c array_of_ptrs. extern const AstTypeMatcher<ParenType> parenType; -/// \brief Matches \c ParenType nodes where the inner type is a specific type. +/// Matches \c ParenType nodes where the inner type is a specific type. /// /// Given /// \code @@ -5003,13 +5226,13 @@ extern const AstTypeMatcher<ParenType> parenType; AST_TYPE_TRAVERSE_MATCHER(innerType, getInnerType, AST_POLYMORPHIC_SUPPORTED_TYPES(ParenType)); -/// \brief Matches block pointer types, i.e. types syntactically represented as +/// Matches block pointer types, i.e. types syntactically represented as /// "void (^)(int)". /// /// The \c pointee is always required to be a \c FunctionType. extern const AstTypeMatcher<BlockPointerType> blockPointerType; -/// \brief Matches member pointer types. +/// Matches member pointer types. /// Given /// \code /// struct A { int i; } @@ -5019,7 +5242,7 @@ extern const AstTypeMatcher<BlockPointerType> blockPointerType; /// matches "A::* ptr" extern const AstTypeMatcher<MemberPointerType> memberPointerType; -/// \brief Matches pointer types, but does not match Objective-C object pointer +/// Matches pointer types, but does not match Objective-C object pointer /// types. /// /// Given @@ -5036,7 +5259,7 @@ extern const AstTypeMatcher<MemberPointerType> memberPointerType; /// matches "int *a", but does not match "Foo *f". extern const AstTypeMatcher<PointerType> pointerType; -/// \brief Matches an Objective-C object pointer type, which is different from +/// Matches an Objective-C object pointer type, which is different from /// a pointer type, despite being syntactically similar. /// /// Given @@ -5051,7 +5274,7 @@ extern const AstTypeMatcher<PointerType> pointerType; /// matches "Foo *f", but does not match "int *a". extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType; -/// \brief Matches both lvalue and rvalue reference types. +/// Matches both lvalue and rvalue reference types. /// /// Given /// \code @@ -5067,7 +5290,7 @@ extern const AstTypeMatcher<ObjCObjectPointerType> objcObjectPointerType; /// \c referenceType() matches the types of \c b, \c c, \c d, \c e, and \c f. extern const AstTypeMatcher<ReferenceType> referenceType; -/// \brief Matches lvalue reference types. +/// Matches lvalue reference types. /// /// Given: /// \code @@ -5084,7 +5307,7 @@ extern const AstTypeMatcher<ReferenceType> referenceType; /// matched since the type is deduced as int& by reference collapsing rules. extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType; -/// \brief Matches rvalue reference types. +/// Matches rvalue reference types. /// /// Given: /// \code @@ -5101,7 +5324,7 @@ extern const AstTypeMatcher<LValueReferenceType> lValueReferenceType; /// matched as it is deduced to int& by reference collapsing rules. extern const AstTypeMatcher<RValueReferenceType> rValueReferenceType; -/// \brief Narrows PointerType (and similar) matchers to those where the +/// Narrows PointerType (and similar) matchers to those where the /// \c pointee matches a given matcher. /// /// Given @@ -5120,7 +5343,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL( AST_POLYMORPHIC_SUPPORTED_TYPES(BlockPointerType, MemberPointerType, PointerType, ReferenceType)); -/// \brief Matches typedef types. +/// Matches typedef types. /// /// Given /// \code @@ -5130,7 +5353,7 @@ AST_TYPELOC_TRAVERSE_MATCHER_DECL( /// matches "typedef int X" extern const AstTypeMatcher<TypedefType> typedefType; -/// \brief Matches enum types. +/// Matches enum types. /// /// Given /// \code @@ -5145,7 +5368,7 @@ extern const AstTypeMatcher<TypedefType> typedefType; /// \c s. extern const AstTypeMatcher<EnumType> enumType; -/// \brief Matches template specialization types. +/// Matches template specialization types. /// /// Given /// \code @@ -5161,7 +5384,7 @@ extern const AstTypeMatcher<EnumType> enumType; extern const AstTypeMatcher<TemplateSpecializationType> templateSpecializationType; -/// \brief Matches types nodes representing unary type transformations. +/// Matches types nodes representing unary type transformations. /// /// Given: /// \code @@ -5171,7 +5394,7 @@ extern const AstTypeMatcher<TemplateSpecializationType> /// matches "__underlying_type(T)" extern const AstTypeMatcher<UnaryTransformType> unaryTransformType; -/// \brief Matches record types (e.g. structs, classes). +/// Matches record types (e.g. structs, classes). /// /// Given /// \code @@ -5186,7 +5409,7 @@ extern const AstTypeMatcher<UnaryTransformType> unaryTransformType; /// and \c s. extern const AstTypeMatcher<RecordType> recordType; -/// \brief Matches tag types (record and enum types). +/// Matches tag types (record and enum types). /// /// Given /// \code @@ -5201,7 +5424,7 @@ extern const AstTypeMatcher<RecordType> recordType; /// and \c c. extern const AstTypeMatcher<TagType> tagType; -/// \brief Matches types specified with an elaborated type keyword or with a +/// Matches types specified with an elaborated type keyword or with a /// qualified name. /// /// Given @@ -5221,7 +5444,7 @@ extern const AstTypeMatcher<TagType> tagType; /// \c c and \c d. extern const AstTypeMatcher<ElaboratedType> elaboratedType; -/// \brief Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier, +/// Matches ElaboratedTypes whose qualifier, a NestedNameSpecifier, /// matches \c InnerMatcher if the qualifier exists. /// /// Given @@ -5244,7 +5467,7 @@ AST_MATCHER_P(ElaboratedType, hasQualifier, return false; } -/// \brief Matches ElaboratedTypes whose named type matches \c InnerMatcher. +/// Matches ElaboratedTypes whose named type matches \c InnerMatcher. /// /// Given /// \code @@ -5264,7 +5487,7 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>, return InnerMatcher.matches(Node.getNamedType(), Finder, Builder); } -/// \brief Matches types that represent the result of substituting a type for a +/// Matches types that represent the result of substituting a type for a /// template type parameter. /// /// Given @@ -5279,7 +5502,7 @@ AST_MATCHER_P(ElaboratedType, namesType, internal::Matcher<QualType>, extern const AstTypeMatcher<SubstTemplateTypeParmType> substTemplateTypeParmType; -/// \brief Matches template type parameter substitutions that have a replacement +/// Matches template type parameter substitutions that have a replacement /// type that matches the provided matcher. /// /// Given @@ -5295,7 +5518,7 @@ AST_TYPE_TRAVERSE_MATCHER( hasReplacementType, getReplacementType, AST_POLYMORPHIC_SUPPORTED_TYPES(SubstTemplateTypeParmType)); -/// \brief Matches template type parameter types. +/// Matches template type parameter types. /// /// Example matches T, but not int. /// (matcher = templateTypeParmType()) @@ -5304,7 +5527,7 @@ AST_TYPE_TRAVERSE_MATCHER( /// \endcode extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType; -/// \brief Matches injected class name types. +/// Matches injected class name types. /// /// Example matches S s, but not S<T> s. /// (matcher = parmVarDecl(hasType(injectedClassNameType()))) @@ -5316,7 +5539,7 @@ extern const AstTypeMatcher<TemplateTypeParmType> templateTypeParmType; /// \endcode extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType; -/// \brief Matches decayed type +/// Matches decayed type /// Example matches i[] in declaration of f. /// (matcher = valueDecl(hasType(decayedType(hasDecayedType(pointerType()))))) /// Example matches i[1]. @@ -5328,13 +5551,13 @@ extern const AstTypeMatcher<InjectedClassNameType> injectedClassNameType; /// \endcode extern const AstTypeMatcher<DecayedType> decayedType; -/// \brief Matches the decayed type, whos decayed type matches \c InnerMatcher +/// Matches the decayed type, whos decayed type matches \c InnerMatcher AST_MATCHER_P(DecayedType, hasDecayedType, internal::Matcher<QualType>, InnerType) { return InnerType.matches(Node.getDecayedType(), Finder, Builder); } -/// \brief Matches declarations whose declaration context, interpreted as a +/// Matches declarations whose declaration context, interpreted as a /// Decl, matches \c InnerMatcher. /// /// Given @@ -5354,7 +5577,7 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) { return InnerMatcher.matches(*Decl::castFromDeclContext(DC), Finder, Builder); } -/// \brief Matches nested name specifiers. +/// Matches nested name specifiers. /// /// Given /// \code @@ -5370,11 +5593,11 @@ AST_MATCHER_P(Decl, hasDeclContext, internal::Matcher<Decl>, InnerMatcher) { extern const internal::VariadicAllOfMatcher<NestedNameSpecifier> nestedNameSpecifier; -/// \brief Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. +/// Same as \c nestedNameSpecifier but matches \c NestedNameSpecifierLoc. extern const internal::VariadicAllOfMatcher<NestedNameSpecifierLoc> nestedNameSpecifierLoc; -/// \brief Matches \c NestedNameSpecifierLocs for which the given inner +/// Matches \c NestedNameSpecifierLocs for which the given inner /// NestedNameSpecifier-matcher matches. AST_MATCHER_FUNCTION_P_OVERLOAD( internal::BindableMatcher<NestedNameSpecifierLoc>, loc, @@ -5384,7 +5607,7 @@ AST_MATCHER_FUNCTION_P_OVERLOAD( InnerMatcher)); } -/// \brief Matches nested name specifiers that specify a type matching the +/// Matches nested name specifiers that specify a type matching the /// given \c QualType matcher without qualifiers. /// /// Given @@ -5403,7 +5626,7 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType, return InnerMatcher.matches(QualType(Node.getAsType(), 0), Finder, Builder); } -/// \brief Matches nested name specifier locs that specify a type matching the +/// Matches nested name specifier locs that specify a type matching the /// given \c TypeLoc. /// /// Given @@ -5416,10 +5639,11 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesType, /// matches "A::" AST_MATCHER_P(NestedNameSpecifierLoc, specifiesTypeLoc, internal::Matcher<TypeLoc>, InnerMatcher) { - return Node && InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); + return Node && Node.getNestedNameSpecifier()->getAsType() && + InnerMatcher.matches(Node.getTypeLoc(), Finder, Builder); } -/// \brief Matches on the prefix of a \c NestedNameSpecifier. +/// Matches on the prefix of a \c NestedNameSpecifier. /// /// Given /// \code @@ -5437,7 +5661,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifier, hasPrefix, return InnerMatcher.matches(*NextNode, Finder, Builder); } -/// \brief Matches on the prefix of a \c NestedNameSpecifierLoc. +/// Matches on the prefix of a \c NestedNameSpecifierLoc. /// /// Given /// \code @@ -5455,7 +5679,7 @@ AST_MATCHER_P_OVERLOAD(NestedNameSpecifierLoc, hasPrefix, return InnerMatcher.matches(NextNode, Finder, Builder); } -/// \brief Matches nested name specifiers that specify a namespace matching the +/// Matches nested name specifiers that specify a namespace matching the /// given namespace matcher. /// /// Given @@ -5472,23 +5696,23 @@ AST_MATCHER_P(NestedNameSpecifier, specifiesNamespace, return InnerMatcher.matches(*Node.getAsNamespace(), Finder, Builder); } -/// \brief Overloads for the \c equalsNode matcher. +/// Overloads for the \c equalsNode matcher. /// FIXME: Implement for other node types. /// @{ -/// \brief Matches if a node equals another node. +/// Matches if a node equals another node. /// /// \c Decl has pointer identity in the AST. AST_MATCHER_P_OVERLOAD(Decl, equalsNode, const Decl*, Other, 0) { return &Node == Other; } -/// \brief Matches if a node equals another node. +/// Matches if a node equals another node. /// /// \c Stmt has pointer identity in the AST. AST_MATCHER_P_OVERLOAD(Stmt, equalsNode, const Stmt*, Other, 1) { return &Node == Other; } -/// \brief Matches if a node equals another node. +/// Matches if a node equals another node. /// /// \c Type has pointer identity in the AST. AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) { @@ -5497,7 +5721,7 @@ AST_MATCHER_P_OVERLOAD(Type, equalsNode, const Type*, Other, 2) { /// @} -/// \brief Matches each case or default statement belonging to the given switch +/// Matches each case or default statement belonging to the given switch /// statement. This matcher may produce multiple matches. /// /// Given @@ -5529,7 +5753,7 @@ AST_MATCHER_P(SwitchStmt, forEachSwitchCase, internal::Matcher<SwitchCase>, return Matched; } -/// \brief Matches each constructor initializer in a constructor definition. +/// Matches each constructor initializer in a constructor definition. /// /// Given /// \code @@ -5554,7 +5778,7 @@ AST_MATCHER_P(CXXConstructorDecl, forEachConstructorInitializer, return Matched; } -/// \brief Matches constructor declarations that are copy constructors. +/// Matches constructor declarations that are copy constructors. /// /// Given /// \code @@ -5569,7 +5793,7 @@ AST_MATCHER(CXXConstructorDecl, isCopyConstructor) { return Node.isCopyConstructor(); } -/// \brief Matches constructor declarations that are move constructors. +/// Matches constructor declarations that are move constructors. /// /// Given /// \code @@ -5584,7 +5808,7 @@ AST_MATCHER(CXXConstructorDecl, isMoveConstructor) { return Node.isMoveConstructor(); } -/// \brief Matches constructor declarations that are default constructors. +/// Matches constructor declarations that are default constructors. /// /// Given /// \code @@ -5599,7 +5823,7 @@ AST_MATCHER(CXXConstructorDecl, isDefaultConstructor) { return Node.isDefaultConstructor(); } -/// \brief Matches constructors that delegate to another constructor. +/// Matches constructors that delegate to another constructor. /// /// Given /// \code @@ -5616,7 +5840,7 @@ AST_MATCHER(CXXConstructorDecl, isDelegatingConstructor) { return Node.isDelegatingConstructor(); } -/// \brief Matches constructor and conversion declarations that are marked with +/// Matches constructor and conversion declarations that are marked with /// the explicit keyword. /// /// Given @@ -5636,7 +5860,7 @@ AST_POLYMORPHIC_MATCHER(isExplicit, return Node.isExplicit(); } -/// \brief Matches function and namespace declarations that are marked with +/// Matches function and namespace declarations that are marked with /// the inline keyword. /// /// Given @@ -5661,7 +5885,7 @@ AST_POLYMORPHIC_MATCHER(isInline, llvm_unreachable("Not a valid polymorphic type"); } -/// \brief Matches anonymous namespace declarations. +/// Matches anonymous namespace declarations. /// /// Given /// \code @@ -5674,7 +5898,7 @@ AST_MATCHER(NamespaceDecl, isAnonymous) { return Node.isAnonymousNamespace(); } -/// \brief If the given case statement does not use the GNU case range +/// If the given case statement does not use the GNU case range /// extension, matches the constant given in the statement. /// /// Given @@ -5691,7 +5915,7 @@ AST_MATCHER_P(CaseStmt, hasCaseConstant, internal::Matcher<Expr>, return InnerMatcher.matches(*Node.getLHS(), Finder, Builder); } -/// \brief Matches declaration that has a given attribute. +/// Matches declaration that has a given attribute. /// /// Given /// \code @@ -5708,7 +5932,7 @@ AST_MATCHER_P(Decl, hasAttr, attr::Kind, AttrKind) { return false; } -/// \brief Matches the return value expression of a return statement +/// Matches the return value expression of a return statement /// /// Given /// \code @@ -5725,7 +5949,7 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>, return false; } -/// \brief Matches CUDA kernel call expression. +/// Matches CUDA kernel call expression. /// /// Example matches, /// \code @@ -5734,7 +5958,7 @@ AST_MATCHER_P(ReturnStmt, hasReturnValue, internal::Matcher<Expr>, extern const internal::VariadicDynCastAllOfMatcher<Stmt, CUDAKernelCallExpr> cudaKernelCallExpr; -/// \brief Matches expressions that resolve to a null pointer constant, such as +/// Matches expressions that resolve to a null pointer constant, such as /// GNU's __null, C++11's nullptr, or C's NULL macro. /// /// Given: @@ -5755,7 +5979,7 @@ AST_MATCHER_FUNCTION(internal::Matcher<Expr>, nullPointerConstant) { integerLiteral(equals(0), hasParent(expr(hasType(pointerType()))))); } -/// \brief Matches declaration of the function the statement belongs to +/// Matches declaration of the function the statement belongs to /// /// Given: /// \code @@ -5793,7 +6017,7 @@ AST_MATCHER_P(Stmt, forFunction, internal::Matcher<FunctionDecl>, return false; } -/// \brief Matches a declaration that has external formal linkage. +/// Matches a declaration that has external formal linkage. /// /// Example matches only z (matcher = varDecl(hasExternalFormalLinkage())) /// \code @@ -5817,7 +6041,7 @@ AST_MATCHER(NamedDecl, hasExternalFormalLinkage) { return Node.hasExternalFormalLinkage(); } -/// \brief Matches a declaration that has default arguments. +/// Matches a declaration that has default arguments. /// /// Example matches y (matcher = parmVarDecl(hasDefaultArgument())) /// \code @@ -5828,7 +6052,7 @@ AST_MATCHER(ParmVarDecl, hasDefaultArgument) { return Node.hasDefaultArg(); } -/// \brief Matches array new expressions. +/// Matches array new expressions. /// /// Given: /// \code @@ -5840,7 +6064,7 @@ AST_MATCHER(CXXNewExpr, isArray) { return Node.isArray(); } -/// \brief Matches array new expressions with a given array size. +/// Matches array new expressions with a given array size. /// /// Given: /// \code @@ -5853,7 +6077,7 @@ AST_MATCHER_P(CXXNewExpr, hasArraySize, internal::Matcher<Expr>, InnerMatcher) { InnerMatcher.matches(*Node.getArraySize(), Finder, Builder); } -/// \brief Matches a class declaration that is defined. +/// Matches a class declaration that is defined. /// /// Example matches x (matcher = cxxRecordDecl(hasDefinition())) /// \code @@ -5864,6 +6088,30 @@ AST_MATCHER(CXXRecordDecl, hasDefinition) { return Node.hasDefinition(); } +/// Matches C++11 scoped enum declaration. +/// +/// Example matches Y (matcher = enumDecl(isScoped())) +/// \code +/// enum X {}; +/// enum class Y {}; +/// \endcode +AST_MATCHER(EnumDecl, isScoped) { + return Node.isScoped(); +} + +/// Matches a function declared with a trailing return type. +/// +/// Example matches Y (matcher = functionDecl(hasTrailingReturn())) +/// \code +/// int X() {} +/// auto Y() -> int {} +/// \endcode +AST_MATCHER(FunctionDecl, hasTrailingReturn) { + if (const auto *F = Node.getType()->getAs<FunctionProtoType>()) + return F->hasTrailingReturn(); + return false; +} + } // namespace ast_matchers } // namespace clang diff --git a/include/clang/ASTMatchers/ASTMatchersInternal.h b/include/clang/ASTMatchers/ASTMatchersInternal.h index 8bd61a76e1852..9d9f867d053ad 100644 --- a/include/clang/ASTMatchers/ASTMatchersInternal.h +++ b/include/clang/ASTMatchers/ASTMatchersInternal.h @@ -38,9 +38,12 @@ #include "clang/AST/ASTTypeTraits.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclFriend.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/ExprCXX.h" +#include "clang/AST/ExprObjC.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Stmt.h" #include "clang/AST/TemplateName.h" @@ -80,7 +83,7 @@ class BoundNodes; namespace internal { -/// \brief Variadic function object. +/// Variadic function object. /// /// Most of the functions below that use VariadicFunction could be implemented /// using plain C++11 variadic functions, but the function object allows us to @@ -113,19 +116,23 @@ private: } }; -/// \brief Unifies obtaining the underlying type of a regular node through +/// Unifies obtaining the underlying type of a regular node through /// `getType` and a TypedefNameDecl node through `getUnderlyingType`. inline QualType getUnderlyingType(const Expr &Node) { return Node.getType(); } inline QualType getUnderlyingType(const ValueDecl &Node) { return Node.getType(); } - inline QualType getUnderlyingType(const TypedefNameDecl &Node) { return Node.getUnderlyingType(); } +inline QualType getUnderlyingType(const FriendDecl &Node) { + if (const TypeSourceInfo *TSI = Node.getFriendType()) + return TSI->getType(); + return QualType(); +} -/// \brief Unifies obtaining the FunctionProtoType pointer from both +/// Unifies obtaining the FunctionProtoType pointer from both /// FunctionProtoType and FunctionDecl nodes.. inline const FunctionProtoType * getFunctionProtoType(const FunctionProtoType &Node) { @@ -136,17 +143,17 @@ inline const FunctionProtoType *getFunctionProtoType(const FunctionDecl &Node) { return Node.getType()->getAs<FunctionProtoType>(); } -/// \brief Internal version of BoundNodes. Holds all the bound nodes. +/// Internal version of BoundNodes. Holds all the bound nodes. class BoundNodesMap { public: - /// \brief Adds \c Node to the map with key \c ID. + /// Adds \c Node to the map with key \c ID. /// /// The node's base type should be in NodeBaseType or it will be unaccessible. void addNode(StringRef ID, const ast_type_traits::DynTypedNode& DynNode) { NodeMap[ID] = DynNode; } - /// \brief Returns the AST node bound to \c ID. + /// Returns the AST node bound to \c ID. /// /// Returns NULL if there was no node bound to \c ID or if there is a node but /// it cannot be converted to the specified type. @@ -167,12 +174,12 @@ public: return It->second; } - /// \brief Imposes an order on BoundNodesMaps. + /// Imposes an order on BoundNodesMaps. bool operator<(const BoundNodesMap &Other) const { return NodeMap < Other.NodeMap; } - /// \brief A map from IDs to the bound nodes. + /// A map from IDs to the bound nodes. /// /// Note that we're using std::map here, as for memoization: /// - we need a comparison operator @@ -183,7 +190,7 @@ public: return NodeMap; } - /// \brief Returns \c true if this \c BoundNodesMap can be compared, i.e. all + /// 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) { @@ -197,25 +204,25 @@ private: IDToNodeMap NodeMap; }; -/// \brief Creates BoundNodesTree objects. +/// Creates BoundNodesTree objects. /// /// The tree builder is used during the matching process to insert the bound /// nodes from the Id matcher. class BoundNodesTreeBuilder { public: - /// \brief A visitor interface to visit all BoundNodes results for a + /// A visitor interface to visit all BoundNodes results for a /// BoundNodesTree. class Visitor { public: virtual ~Visitor() = default; - /// \brief Called multiple times during a single call to VisitMatches(...). + /// Called multiple times during a single call to VisitMatches(...). /// /// 'BoundNodesView' contains the bound nodes for a single match. virtual void visitMatch(const BoundNodes& BoundNodesView) = 0; }; - /// \brief Add a binding from an id to a node. + /// Add a binding from an id to a node. void setBinding(StringRef Id, const ast_type_traits::DynTypedNode &DynNode) { if (Bindings.empty()) Bindings.emplace_back(); @@ -223,10 +230,10 @@ public: Binding.addNode(Id, DynNode); } - /// \brief Adds a branch in the tree. + /// Adds a branch in the tree. void addMatch(const BoundNodesTreeBuilder &Bindings); - /// \brief Visits all matches that this BoundNodesTree represents. + /// Visits all matches that this BoundNodesTree represents. /// /// The ownership of 'ResultVisitor' remains at the caller. void visitMatches(Visitor* ResultVisitor); @@ -238,12 +245,12 @@ public: return !Bindings.empty(); } - /// \brief Imposes an order on BoundNodesTreeBuilders. + /// Imposes an order on BoundNodesTreeBuilders. bool operator<(const BoundNodesTreeBuilder &Other) const { return Bindings < Other.Bindings; } - /// \brief Returns \c true if this \c BoundNodesTreeBuilder can be compared, + /// 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) { @@ -259,7 +266,7 @@ private: class ASTMatchFinder; -/// \brief Generic interface for all matchers. +/// Generic interface for all matchers. /// /// Used by the implementation of Matcher<T> and DynTypedMatcher. /// In general, implement MatcherInterface<T> or SingleNodeMatcherInterface<T> @@ -269,7 +276,7 @@ class DynMatcherInterface public: virtual ~DynMatcherInterface() = default; - /// \brief Returns true if \p DynNode can be matched. + /// 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. @@ -278,7 +285,7 @@ public: BoundNodesTreeBuilder *Builder) const = 0; }; -/// \brief Generic interface for matchers on an AST node of type T. +/// Generic interface for matchers on an AST node of type T. /// /// Implement this if your matcher may need to inspect the children or /// descendants of the node or bind matched nodes to names. If you are @@ -288,7 +295,7 @@ public: template <typename T> class MatcherInterface : public DynMatcherInterface { public: - /// \brief Returns true if 'Node' can be matched. + /// Returns true if 'Node' can be matched. /// /// May bind 'Node' to an ID via 'Builder', or recurse into /// the AST via 'Finder'. @@ -303,12 +310,12 @@ public: } }; -/// \brief Interface for matchers that only evaluate properties on a single +/// Interface for matchers that only evaluate properties on a single /// node. template <typename T> class SingleNodeMatcherInterface : public MatcherInterface<T> { public: - /// \brief Returns true if the matcher matches the provided node. + /// Returns true if the matcher matches the provided node. /// /// A subclass must implement this instead of Matches(). virtual bool matchesNode(const T &Node) const = 0; @@ -324,7 +331,7 @@ private: template <typename> class Matcher; -/// \brief Matcher that works on a \c DynTypedNode. +/// Matcher that works on a \c DynTypedNode. /// /// It is constructed from a \c Matcher<T> object and redirects most calls to /// underlying matcher. @@ -333,26 +340,26 @@ template <typename> class Matcher; /// return false if it is not convertible. class DynTypedMatcher { public: - /// \brief Takes ownership of the provided implementation pointer. + /// Takes ownership of the provided implementation pointer. template <typename T> DynTypedMatcher(MatcherInterface<T> *Implementation) : SupportedKind(ast_type_traits::ASTNodeKind::getFromNodeKind<T>()), RestrictKind(SupportedKind), Implementation(Implementation) {} - /// \brief Construct from a variadic function. + /// Construct from a variadic function. enum VariadicOperator { - /// \brief Matches nodes for which all provided matchers match. + /// Matches nodes for which all provided matchers match. VO_AllOf, - /// \brief Matches nodes for which at least one of the provided matchers + /// 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 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. + /// Matches nodes that do not match the provided matcher. /// /// Uses the variadic matcher interface, but fails if /// InnerMatchers.size() != 1. @@ -364,27 +371,27 @@ public: ast_type_traits::ASTNodeKind SupportedKind, std::vector<DynTypedMatcher> InnerMatchers); - /// \brief Get a "true" matcher for \p NodeKind. + /// 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. + /// 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 + /// 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. + /// 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. + /// 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. @@ -392,12 +399,12 @@ public: ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const; - /// \brief Bind the specified \p ID to the matcher. + /// 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. + /// 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 @@ -412,7 +419,7 @@ public: reinterpret_cast<uint64_t>(Implementation.get())); } - /// \brief Returns the type this matcher works on. + /// Returns the type this matcher works on. /// /// \c matches() will always return false unless the node passed is of this /// or a derived type. @@ -420,7 +427,7 @@ public: return SupportedKind; } - /// \brief Returns \c true if the passed \c DynTypedMatcher can be converted + /// 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 @@ -430,7 +437,7 @@ public: } bool canConvertTo(ast_type_traits::ASTNodeKind To) const; - /// \brief Construct a \c Matcher<T> interface around the dynamic matcher. + /// 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 @@ -440,7 +447,7 @@ public: return unconditionalConvertTo<T>(); } - /// \brief Same as \c convertTo(), but does not check that the underlying + /// 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. @@ -456,7 +463,7 @@ private: bool AllowBind = false; ast_type_traits::ASTNodeKind SupportedKind; - /// \brief A potentially stricter node kind. + /// A potentially stricter node kind. /// /// It allows to perform implicit and dynamic cast of matchers without /// needing to change \c Implementation. @@ -464,7 +471,7 @@ private: IntrusiveRefCntPtr<DynMatcherInterface> Implementation; }; -/// \brief Wrapper base class for a wrapping matcher. +/// Wrapper base class for a wrapping matcher. /// /// This is just a container for a DynTypedMatcher that can be used as a base /// class for another matcher. @@ -477,7 +484,7 @@ protected: const DynTypedMatcher InnerMatcher; }; -/// \brief Wrapper of a MatcherInterface<T> *that allows copying. +/// Wrapper of a MatcherInterface<T> *that allows copying. /// /// A Matcher<Base> can be used anywhere a Matcher<Derived> is /// required. This establishes an is-a relationship which is reverse @@ -488,11 +495,11 @@ protected: template <typename T> class Matcher { public: - /// \brief Takes ownership of the provided implementation pointer. + /// Takes ownership of the provided implementation pointer. explicit Matcher(MatcherInterface<T> *Implementation) : Implementation(Implementation) {} - /// \brief Implicitly converts \c Other to a Matcher<T>. + /// Implicitly converts \c Other to a Matcher<T>. /// /// Requires \c T to be derived from \c From. template <typename From> @@ -504,7 +511,7 @@ public: ast_type_traits::ASTNodeKind::getFromNodeKind<T>())); } - /// \brief Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. + /// Implicitly converts \c Matcher<Type> to \c Matcher<QualType>. /// /// The resulting matcher is not strict, i.e. ignores qualifiers. template <typename TypeT> @@ -514,7 +521,7 @@ public: std::is_same<TypeT, Type>::value>::type* = nullptr) : Implementation(new TypeToQualType<TypeT>(Other)) {} - /// \brief Convert \c this into a \c Matcher<T> by applying dyn_cast<> to the + /// 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> @@ -523,7 +530,7 @@ public: return Matcher<To>(Implementation); } - /// \brief Forwards the call to the underlying MatcherInterface<T> pointer. + /// Forwards the call to the underlying MatcherInterface<T> pointer. bool matches(const T &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { @@ -531,18 +538,18 @@ public: Finder, Builder); } - /// \brief Returns an ID that uniquely identifies the matcher. + /// Returns an ID that uniquely identifies the matcher. DynTypedMatcher::MatcherIDType getID() const { return Implementation.getID(); } - /// \brief Extract the dynamic matcher. + /// 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 + /// Allows the conversion of a \c Matcher<Type> to a \c /// Matcher<QualType>. /// /// Depending on the constructor argument, the matcher is either strict, i.e. @@ -583,14 +590,14 @@ private: DynTypedMatcher Implementation; }; // class Matcher -/// \brief A convenient helper for creating a Matcher<T> without specifying +/// A convenient helper for creating a Matcher<T> without specifying /// the template type argument. template <typename T> inline Matcher<T> makeMatcher(MatcherInterface<T> *Implementation) { return Matcher<T>(Implementation); } -/// \brief Specialization of the conversion functions for QualType. +/// Specialization of the conversion functions for QualType. /// /// This specialization provides the Matcher<Type>->Matcher<QualType> /// conversion that the static API does. @@ -606,7 +613,7 @@ inline Matcher<QualType> DynTypedMatcher::convertTo<QualType>() const { return unconditionalConvertTo<QualType>(); } -/// \brief Finds the first node in a range that matches the given matcher. +/// Finds the first node in a range that matches the given matcher. template <typename MatcherT, typename IteratorT> bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start, IteratorT End, ASTMatchFinder *Finder, @@ -621,7 +628,7 @@ bool matchesFirstInRange(const MatcherT &Matcher, IteratorT Start, return false; } -/// \brief Finds the first node in a pointer range that matches the given +/// Finds the first node in a pointer range that matches the given /// matcher. template <typename MatcherT, typename IteratorT> bool matchesFirstInPointerRange(const MatcherT &Matcher, IteratorT Start, @@ -653,7 +660,7 @@ public: static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes); }; -/// \brief Matches overloaded operators with a specific name. +/// Matches overloaded operators with a specific name. /// /// The type argument ArgT is not used by this matcher but is used by /// PolymorphicMatcherWithParam1 and should be StringRef. @@ -675,14 +682,14 @@ public: private: - /// \brief CXXOperatorCallExpr exist only for calls to overloaded operators + /// CXXOperatorCallExpr exist only for calls to overloaded operators /// so this function returns true if the call is to an operator of the given /// name. bool matchesSpecialized(const CXXOperatorCallExpr &Node) const { return getOperatorSpelling(Node.getOperator()) == Name; } - /// \brief Returns true only if CXXMethodDecl represents an overloaded + /// Returns true only if CXXMethodDecl represents an overloaded /// operator and has the given operator name. bool matchesSpecialized(const FunctionDecl &Node) const { return Node.isOverloadedOperator() && @@ -692,7 +699,7 @@ private: std::string Name; }; -/// \brief Matches named declarations with a specific name. +/// Matches named declarations with a specific name. /// /// See \c hasName() and \c hasAnyName() in ASTMatchers.h for details. class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> { @@ -702,13 +709,13 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> { bool matchesNode(const NamedDecl &Node) const override; private: - /// \brief Unqualified match routine. + /// 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 + /// Full match routine /// /// Fast implementation for the simple case of a named declaration at /// namespace or RecordDecl scope. @@ -716,7 +723,7 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> { /// matchesNodeFullSlow. bool matchesNodeFullFast(const NamedDecl &Node) const; - /// \brief Full match routine + /// Full match routine /// /// It generates the fully qualified name of the declaration (which is /// expensive) before trying to match. @@ -727,11 +734,16 @@ class HasNameMatcher : public SingleNodeMatcherInterface<NamedDecl> { const std::vector<std::string> Names; }; -/// \brief Trampoline function to use VariadicFunction<> to construct a +/// Trampoline function to use VariadicFunction<> to construct a /// HasNameMatcher. Matcher<NamedDecl> hasAnyNameFunc(ArrayRef<const StringRef *> NameRefs); -/// \brief Matches declarations for QualType and CallExpr. +/// Trampoline function to use VariadicFunction<> to construct a +/// hasAnySelector matcher. +Matcher<ObjCMessageExpr> hasAnySelectorFunc( + ArrayRef<const StringRef *> NameRefs); + +/// Matches declarations for QualType and CallExpr. /// /// Type argument DeclMatcherT is required by PolymorphicMatcherWithParam1 but /// not actually used. @@ -750,7 +762,7 @@ public: } private: - /// \brief Forwards to matching on the underlying type of the QualType. + /// Forwards to matching on the underlying type of the QualType. bool matchesSpecialized(const QualType &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { if (Node.isNull()) @@ -759,7 +771,7 @@ private: return matchesSpecialized(*Node, Finder, Builder); } - /// \brief Finds the best declaration for a type and returns whether the inner + /// Finds the best declaration for a type and returns whether the inner /// matcher matches on it. bool matchesSpecialized(const Type &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { @@ -833,21 +845,21 @@ private: return false; } - /// \brief Extracts the Decl the DeclRefExpr references and returns whether + /// Extracts the Decl the DeclRefExpr references and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const DeclRefExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getDecl(), Finder, Builder); } - /// \brief Extracts the Decl of the callee of a CallExpr and returns whether + /// Extracts the Decl of the callee of a CallExpr and returns whether /// the inner matcher matches on it. bool matchesSpecialized(const CallExpr &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getCalleeDecl(), Finder, Builder); } - /// \brief Extracts the Decl of the constructor call and returns whether the + /// Extracts the Decl of the constructor call and returns whether the /// inner matcher matches on it. bool matchesSpecialized(const CXXConstructExpr &Node, ASTMatchFinder *Finder, @@ -855,7 +867,13 @@ private: return matchesDecl(Node.getConstructor(), Finder, Builder); } - /// \brief Extracts the operator new of the new call and returns whether the + bool matchesSpecialized(const ObjCIvarRefExpr &Node, + ASTMatchFinder *Finder, + BoundNodesTreeBuilder *Builder) const { + return matchesDecl(Node.getDecl(), Finder, Builder); + } + + /// Extracts the operator new of the new call and returns whether the /// inner matcher matches on it. bool matchesSpecialized(const CXXNewExpr &Node, ASTMatchFinder *Finder, @@ -863,7 +881,7 @@ private: return matchesDecl(Node.getOperatorNew(), Finder, Builder); } - /// \brief Extracts the \c ValueDecl a \c MemberExpr refers to and returns + /// Extracts the \c ValueDecl a \c MemberExpr refers to and returns /// whether the inner matcher matches on it. bool matchesSpecialized(const MemberExpr &Node, ASTMatchFinder *Finder, @@ -871,7 +889,7 @@ private: return matchesDecl(Node.getMemberDecl(), Finder, Builder); } - /// \brief Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns + /// Extracts the \c LabelDecl a \c AddrLabelExpr refers to and returns /// whether the inner matcher matches on it. bool matchesSpecialized(const AddrLabelExpr &Node, ASTMatchFinder *Finder, @@ -879,14 +897,14 @@ private: return matchesDecl(Node.getLabel(), Finder, Builder); } - /// \brief Extracts the declaration of a LabelStmt and returns whether the + /// Extracts the declaration of a LabelStmt and returns whether the /// inner matcher matches on it. bool matchesSpecialized(const LabelStmt &Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { return matchesDecl(Node.getDecl(), Finder, Builder); } - /// \brief Returns whether the inner matcher \c Node. Returns false if \c Node + /// Returns whether the inner matcher \c Node. Returns false if \c Node /// is \c NULL. bool matchesDecl(const Decl *Node, ASTMatchFinder *Finder, BoundNodesTreeBuilder *Builder) const { @@ -896,7 +914,7 @@ private: } }; -/// \brief IsBaseType<T>::value is true if T is a "base" type in the AST +/// IsBaseType<T>::value is true if T is a "base" type in the AST /// node class hierarchies. template <typename T> struct IsBaseType { @@ -913,7 +931,7 @@ struct IsBaseType { template <typename T> const bool IsBaseType<T>::value; -/// \brief Interface that allows matchers to traverse the AST. +/// Interface that allows matchers to traverse the AST. /// FIXME: Find a better name. /// /// This provides three entry methods for each base node type in the AST: @@ -933,7 +951,7 @@ const bool IsBaseType<T>::value; /// all nodes, as all nodes have ancestors. class ASTMatchFinder { public: - /// \brief Defines how we descend a level in the AST when we pass + /// Defines how we descend a level in the AST when we pass /// through expressions. enum TraversalKind { /// Will traverse any child nodes. @@ -943,7 +961,7 @@ public: TK_IgnoreImplicitCastsAndParentheses }; - /// \brief Defines how bindings are processed on recursive matches. + /// Defines how bindings are processed on recursive matches. enum BindKind { /// Stop at the first match and only bind the first match. BK_First, @@ -952,7 +970,7 @@ public: BK_All }; - /// \brief Defines which ancestors are considered for a match. + /// Defines which ancestors are considered for a match. enum AncestorMatchMode { /// All ancestors. AMM_All, @@ -963,7 +981,7 @@ public: virtual ~ASTMatchFinder() = default; - /// \brief Returns true if the given class is directly or indirectly derived + /// Returns true if the given class is directly or indirectly derived /// from a base type matching \c base. /// /// A class is considered to be also derived from itself. @@ -1039,27 +1057,27 @@ protected: AncestorMatchMode MatchMode) = 0; }; -/// \brief A type-list implementation. +/// A type-list implementation. /// /// A "linked list" of types, accessible by using the ::head and ::tail /// typedefs. template <typename... Ts> struct TypeList {}; // Empty sentinel type list. template <typename T1, typename... Ts> struct TypeList<T1, Ts...> { - /// \brief The first type on the list. + /// The first type on the list. using head = T1; - /// \brief A sublist with the tail. ie everything but the head. + /// A sublist with the tail. ie everything but the head. /// /// This type is used to do recursion. TypeList<>/EmptyTypeList indicates the /// end of the list. using tail = TypeList<Ts...>; }; -/// \brief The empty type list. +/// The empty type list. using EmptyTypeList = TypeList<>; -/// \brief Helper meta-function to determine if some type \c T is present or +/// Helper meta-function to determine if some type \c T is present or /// a parent type in the list. template <typename AnyTypeList, typename T> struct TypeListContainsSuperOf { @@ -1072,14 +1090,14 @@ struct TypeListContainsSuperOf<EmptyTypeList, T> { static const bool value = false; }; -/// \brief A "type list" that contains all types. +/// A "type list" that contains all types. /// /// Useful for matchers like \c anything and \c unless. using AllNodeBaseTypes = TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, QualType, Type, TypeLoc, CXXCtorInitializer>; -/// \brief Helper meta-function to extract the argument out of a function of +/// Helper meta-function to extract the argument out of a function of /// type void(Arg). /// /// See AST_POLYMORPHIC_SUPPORTED_TYPES for details. @@ -1088,21 +1106,21 @@ template <class T> struct ExtractFunctionArgMeta<void(T)> { using type = T; }; -/// \brief Default type lists for ArgumentAdaptingMatcher matchers. +/// Default type lists for ArgumentAdaptingMatcher matchers. using AdaptativeDefaultFromTypes = AllNodeBaseTypes; using AdaptativeDefaultToTypes = TypeList<Decl, Stmt, NestedNameSpecifier, NestedNameSpecifierLoc, TypeLoc, QualType>; -/// \brief All types that are supported by HasDeclarationMatcher above. +/// All types that are supported by HasDeclarationMatcher above. using HasDeclarationSupportedTypes = TypeList<CallExpr, CXXConstructExpr, CXXNewExpr, DeclRefExpr, EnumType, ElaboratedType, InjectedClassNameType, LabelStmt, AddrLabelExpr, MemberExpr, QualType, RecordType, TagType, TemplateSpecializationType, TemplateTypeParmType, TypedefType, - UnresolvedUsingType>; + UnresolvedUsingType, ObjCIvarRefExpr>; -/// \brief Converts a \c Matcher<T> to a matcher of desired type \c To by +/// Converts a \c Matcher<T> to a matcher of desired type \c To by /// "adapting" a \c To into a \c T. /// /// The \c ArgumentAdapterT argument specifies how the adaptation is done. @@ -1145,7 +1163,7 @@ struct ArgumentAdaptingMatcherFunc { } }; -/// \brief A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be +/// A PolymorphicMatcherWithParamN<MatcherT, P1, ..., PN> object can be /// created from N parameters p1, ..., pN (of type P1, ..., PN) and /// used as a Matcher<T> where a MatcherT<T, P1, ..., PN>(p1, ..., pN) /// can be constructed. @@ -1214,7 +1232,7 @@ private: const P2 Param2; }; -/// \brief Matches any instance of the given NodeType. +/// Matches any instance of the given NodeType. /// /// This is useful when a matcher syntactically requires a child matcher, /// but the context doesn't care. See for example: anything(). @@ -1230,7 +1248,7 @@ public: } }; -/// \brief A Matcher that allows binding the node it matches to an id. +/// A Matcher that allows binding the node it matches to an id. /// /// BindableMatcher provides a \a bind() method that allows binding the /// matched node to an id if the match was successful. @@ -1241,7 +1259,7 @@ public: explicit BindableMatcher(MatcherInterface<T> *Implementation) : Matcher<T>(Implementation) {} - /// \brief Returns a matcher that will bind the matched node on a match. + /// Returns a matcher that will bind the matched node on a match. /// /// The returned matcher is equivalent to this matcher, but will /// bind the matched node on a match. @@ -1251,7 +1269,7 @@ public: ->template unconditionalConvertTo<T>(); } - /// \brief Same as Matcher<T>'s conversion operator, but enables binding on + /// 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); @@ -1260,7 +1278,7 @@ public: } }; -/// \brief Matches nodes of type T that have child nodes of type ChildT for +/// Matches nodes of type T that have child nodes of type ChildT for /// which a specified child matcher matches. /// /// ChildT must be an AST base type. @@ -1278,7 +1296,7 @@ public: } }; -/// \brief Matches nodes of type T that have child nodes of type ChildT for +/// Matches nodes of type T that have child nodes of type ChildT for /// which a specified child matcher matches. ChildT must be an AST base /// type. /// As opposed to the HasMatcher, the ForEachMatcher will produce a match @@ -1301,10 +1319,10 @@ class ForEachMatcher : public WrapperMatcherInterface<T> { } }; -/// \brief VariadicOperatorMatcher related types. +/// VariadicOperatorMatcher related types. /// @{ -/// \brief Polymorphic matcher object that uses a \c +/// Polymorphic matcher object that uses a \c /// DynTypedMatcher::VariadicOperator operator. /// /// Input matchers can have any type (including other polymorphic matcher @@ -1333,7 +1351,7 @@ private: std::tuple<Ps...> Params; }; -/// \brief Overloaded function object to generate VariadicOperatorMatcher +/// Overloaded function object to generate VariadicOperatorMatcher /// objects from arbitrary matchers. template <unsigned MinCount, unsigned MaxCount> struct VariadicOperatorMatcherFunc { @@ -1354,7 +1372,7 @@ inline Matcher<T> DynTypedMatcher::unconditionalConvertTo() const { return Matcher<T>(*this); } -/// \brief Creates a Matcher<T> that matches if all inner matchers match. +/// Creates a Matcher<T> that matches if all inner matchers match. template<typename T> BindableMatcher<T> makeAllOfComposite( ArrayRef<const Matcher<T> *> InnerMatchers) { @@ -1380,7 +1398,7 @@ BindableMatcher<T> makeAllOfComposite( .template unconditionalConvertTo<T>()); } -/// \brief Creates a Matcher<T> that matches if +/// Creates a Matcher<T> that matches if /// T is dyn_cast'able into InnerT and all inner matchers match. /// /// Returns BindableMatcher, as matchers that use dyn_cast have @@ -1393,7 +1411,7 @@ BindableMatcher<T> makeDynCastAllOfComposite( makeAllOfComposite(InnerMatchers).template dynCastTo<T>()); } -/// \brief Matches nodes of type T that have at least one descendant node of +/// Matches nodes of type T that have at least one descendant node of /// type DescendantT for which the given inner matcher matches. /// /// DescendantT must be an AST base type. @@ -1413,7 +1431,7 @@ public: } }; -/// \brief Matches nodes of type \c T that have a parent node of type \c ParentT +/// Matches nodes of type \c T that have a parent node of type \c ParentT /// for which the given inner matcher matches. /// /// \c ParentT must be an AST base type. @@ -1433,7 +1451,7 @@ public: } }; -/// \brief Matches nodes of type \c T that have at least one ancestor node of +/// Matches nodes of type \c T that have at least one ancestor node of /// type \c AncestorT for which the given inner matcher matches. /// /// \c AncestorT must be an AST base type. @@ -1453,7 +1471,7 @@ public: } }; -/// \brief Matches nodes of type T that have at least one descendant node of +/// Matches nodes of type T that have at least one descendant node of /// type DescendantT for which the given inner matcher matches. /// /// DescendantT must be an AST base type. @@ -1476,7 +1494,7 @@ public: } }; -/// \brief Matches on nodes that have a getValue() method if getValue() equals +/// Matches on nodes that have a getValue() method if getValue() equals /// the value the ValueEqualsMatcher was constructed with. template <typename T, typename ValueT> class ValueEqualsMatcher : public SingleNodeMatcherInterface<T> { @@ -1498,7 +1516,7 @@ private: const ValueT ExpectedValue; }; -/// \brief Template specializations to easily write matchers for floating point +/// Template specializations to easily write matchers for floating point /// literals. template <> inline bool ValueEqualsMatcher<FloatingLiteral, double>::matchesNode( @@ -1524,7 +1542,7 @@ inline bool ValueEqualsMatcher<FloatingLiteral, llvm::APFloat>::matchesNode( return ExpectedValue.compare(Node.getValue()) == llvm::APFloat::cmpEqual; } -/// \brief A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a +/// A VariadicDynCastAllOfMatcher<SourceT, TargetT> object is a /// variadic functor that takes a number of Matcher<TargetT> and returns a /// Matcher<SourceT> that matches TargetT nodes that are matched by all of the /// given matchers, if SourceT can be dynamically casted into TargetT. @@ -1544,7 +1562,7 @@ public: VariadicDynCastAllOfMatcher() {} }; -/// \brief A \c VariadicAllOfMatcher<T> object is a variadic functor that takes +/// A \c VariadicAllOfMatcher<T> object is a variadic functor that takes /// a number of \c Matcher<T> and returns a \c Matcher<T> that matches \c T /// nodes that are matched by all of the given matchers. /// @@ -1562,7 +1580,7 @@ public: VariadicAllOfMatcher() {} }; -/// \brief Matches nodes of type \c TLoc for which the inner +/// Matches nodes of type \c TLoc for which the inner /// \c Matcher<T> matches. template <typename TLoc, typename T> class LocMatcher : public WrapperMatcherInterface<TLoc> { @@ -1584,7 +1602,7 @@ private: } }; -/// \brief Matches \c TypeLocs based on an inner matcher matching a certain +/// Matches \c TypeLocs based on an inner matcher matching a certain /// \c QualType. /// /// Used to implement the \c loc() matcher. @@ -1602,7 +1620,7 @@ public: } }; -/// \brief Matches nodes of type \c T for which the inner matcher matches on a +/// Matches nodes of type \c T for which the inner matcher matches on a /// another node of type \c T that can be reached using a given traverse /// function. template <typename T> @@ -1626,7 +1644,7 @@ private: QualType (T::*TraverseFunction)() const; }; -/// \brief Matches nodes of type \c T in a ..Loc hierarchy, for which the inner +/// Matches nodes of type \c T in a ..Loc hierarchy, for which the inner /// matcher matches on a another node of type \c T that can be reached using a /// given traverse function. template <typename T> @@ -1650,7 +1668,7 @@ private: TypeLoc (T::*TraverseFunction)() const; }; -/// \brief Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where +/// Converts a \c Matcher<InnerT> to a \c Matcher<OuterT>, where /// \c OuterT is any type that is supported by \c Getter. /// /// \code Getter<OuterT>::value() \endcode returns a @@ -1688,7 +1706,7 @@ private: const Matcher<InnerTBase> InnerMatcher; }; -/// \brief A simple memoizer of T(*)() functions. +/// A simple memoizer of T(*)() functions. /// /// It will call the passed 'Func' template parameter at most once. /// Used to support AST_MATCHER_FUNCTION() macro. diff --git a/include/clang/ASTMatchers/ASTMatchersMacros.h b/include/clang/ASTMatchers/ASTMatchersMacros.h index 6a48da821a53e..3080f86699b56 100644 --- a/include/clang/ASTMatchers/ASTMatchersMacros.h +++ b/include/clang/ASTMatchers/ASTMatchersMacros.h @@ -50,7 +50,7 @@ #ifndef LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H #define LLVM_CLANG_ASTMATCHERS_ASTMATCHERSMACROS_H -/// \brief AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... } +/// AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) { ... } /// defines a zero parameter function named DefineMatcher() that returns a /// ReturnType object. #define AST_MATCHER_FUNCTION(ReturnType, DefineMatcher) \ @@ -61,7 +61,7 @@ } \ inline ReturnType DefineMatcher##_getInstance() -/// \brief AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { +/// AST_MATCHER_FUNCTION_P(ReturnType, DefineMatcher, ParamType, Param) { /// ... } /// defines a single-parameter function named DefineMatcher() that returns a /// ReturnType object. @@ -81,7 +81,7 @@ typedef ReturnType (&DefineMatcher##_Type##OverloadId)(ParamType const &); \ inline ReturnType DefineMatcher(ParamType const &Param) -/// \brief AST_MATCHER(Type, DefineMatcher) { ... } +/// AST_MATCHER(Type, DefineMatcher) { ... } /// defines a zero parameter function named DefineMatcher() that returns a /// Matcher<Type> object. /// @@ -113,7 +113,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const -/// \brief AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } +/// AST_MATCHER_P(Type, DefineMatcher, ParamType, Param) { ... } /// defines a single-parameter function named DefineMatcher() that returns a /// Matcher<Type> object. /// @@ -159,7 +159,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const -/// \brief AST_MATCHER_P2( +/// AST_MATCHER_P2( /// Type, DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } /// defines a two-parameter function named DefineMatcher() that returns a /// Matcher<Type> object. @@ -211,7 +211,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const -/// \brief Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER* +/// Construct a type-list to be passed to the AST_POLYMORPHIC_MATCHER* /// macros. /// /// You can't pass something like \c TypeList<Foo, Bar> to a macro, because it @@ -222,7 +222,7 @@ #define AST_POLYMORPHIC_SUPPORTED_TYPES(...) \ void(::clang::ast_matchers::internal::TypeList<__VA_ARGS__>) -/// \brief AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... } +/// AST_POLYMORPHIC_MATCHER(DefineMatcher) { ... } /// defines a single-parameter function named DefineMatcher() that is /// polymorphic in the return type. /// @@ -252,7 +252,7 @@ ::clang::ast_matchers::internal::ASTMatchFinder *Finder, \ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) const -/// \brief AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } +/// AST_POLYMORPHIC_MATCHER_P(DefineMatcher, ParamType, Param) { ... } /// defines a single-parameter function named DefineMatcher() that is /// polymorphic in the return type. /// @@ -305,7 +305,7 @@ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \ const -/// \brief AST_POLYMORPHIC_MATCHER_P2( +/// AST_POLYMORPHIC_MATCHER_P2( /// DefineMatcher, ParamType1, Param1, ParamType2, Param2) { ... } /// defines a two-parameter function named matcher() that is polymorphic in /// the return type. @@ -359,11 +359,6 @@ ::clang::ast_matchers::internal::BoundNodesTreeBuilder *Builder) \ const -/// \brief Creates a variadic matcher for both a specific \c Type as well as -/// the corresponding \c TypeLoc. -#define AST_TYPE_MATCHER(NodeType, MatcherName) \ - const ::clang::ast_matchers::internal::VariadicDynCastAllOfMatcher< \ - Type, NodeType> MatcherName // FIXME: add a matcher for TypeLoc derived classes using its custom casting // API (no longer dyn_cast) if/when we need such matching @@ -388,7 +383,7 @@ ::clang::ast_matchers::internal::TypeTraverseMatcher, \ ReturnTypesF>::Func MatcherName -/// \brief AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines +/// AST_TYPE_TRAVERSE_MATCHER(MatcherName, FunctionName) defines /// the matcher \c MatcherName that can be used to traverse from one \c Type /// to another. /// @@ -431,7 +426,7 @@ ReturnTypesF>::Func MatcherName##Loc; \ AST_TYPE_TRAVERSE_MATCHER_DEF(MatcherName, ReturnTypesF) -/// \brief AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works +/// AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName) works /// identical to \c AST_TYPE_TRAVERSE_MATCHER but operates on \c TypeLocs. #define AST_TYPELOC_TRAVERSE_MATCHER(MatcherName, FunctionName, ReturnTypesF) \ namespace internal { \ diff --git a/include/clang/ASTMatchers/Dynamic/Diagnostics.h b/include/clang/ASTMatchers/Dynamic/Diagnostics.h index 908fa0db622d0..ccd9590f4bb4a 100644 --- a/include/clang/ASTMatchers/Dynamic/Diagnostics.h +++ b/include/clang/ASTMatchers/Dynamic/Diagnostics.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Diagnostics class to manage error messages. +/// Diagnostics class to manage error messages. /// //===----------------------------------------------------------------------===// @@ -39,7 +39,7 @@ struct SourceRange { SourceLocation End; }; -/// \brief A VariantValue instance annotated with its parser context. +/// A VariantValue instance annotated with its parser context. struct ParserValue { ParserValue() : Text(), Range(), Value() {} StringRef Text; @@ -47,16 +47,16 @@ struct ParserValue { VariantValue Value; }; -/// \brief Helper class to manage error messages. +/// Helper class to manage error messages. class Diagnostics { public: - /// \brief Parser context types. + /// Parser context types. enum ContextType { CT_MatcherArg = 0, CT_MatcherConstruct = 1 }; - /// \brief All errors from the system. + /// All errors from the system. enum ErrorType { ET_None = 0, @@ -80,7 +80,7 @@ public: ET_ParserOverloadedType = 110 }; - /// \brief Helper stream class. + /// Helper stream class. class ArgStream { public: ArgStream(std::vector<std::string> *Out) : Out(Out) {} @@ -93,7 +93,7 @@ public: std::vector<std::string> *Out; }; - /// \brief Class defining a parser context. + /// Class defining a parser context. /// /// Used by the parser to specify (possibly recursive) contexts where the /// parsing/construction can fail. Any error triggered within a context will @@ -101,11 +101,11 @@ public: /// This class should be used as a RAII instance in the stack. struct Context { public: - /// \brief About to call the constructor for a matcher. + /// About to call the constructor for a matcher. enum ConstructMatcherEnum { ConstructMatcher }; Context(ConstructMatcherEnum, Diagnostics *Error, StringRef MatcherName, SourceRange MatcherRange); - /// \brief About to recurse into parsing one argument for a matcher. + /// About to recurse into parsing one argument for a matcher. enum MatcherArgEnum { MatcherArg }; Context(MatcherArgEnum, Diagnostics *Error, StringRef MatcherName, SourceRange MatcherRange, unsigned ArgNumber); @@ -115,7 +115,7 @@ public: Diagnostics *const Error; }; - /// \brief Context for overloaded matcher construction. + /// Context for overloaded matcher construction. /// /// This context will take care of merging all errors that happen within it /// as "candidate" overloads for the same matcher. @@ -124,7 +124,7 @@ public: OverloadContext(Diagnostics* Error); ~OverloadContext(); - /// \brief Revert all errors that happened within this context. + /// Revert all errors that happened within this context. void revertErrors(); private: @@ -132,21 +132,21 @@ public: unsigned BeginIndex; }; - /// \brief Add an error to the diagnostics. + /// Add an error to the diagnostics. /// /// All the context information will be kept on the error message. /// \return a helper class to allow the caller to pass the arguments for the /// error message, using the << operator. ArgStream addError(SourceRange Range, ErrorType Error); - /// \brief Information stored for one frame of the context. + /// Information stored for one frame of the context. struct ContextFrame { ContextType Type; SourceRange Range; std::vector<std::string> Args; }; - /// \brief Information stored for each error found. + /// Information stored for each error found. struct ErrorContent { std::vector<ContextFrame> ContextStack; struct Message { @@ -158,20 +158,20 @@ public: }; ArrayRef<ErrorContent> errors() const { return Errors; } - /// \brief Returns a simple string representation of each error. + /// Returns a simple string representation of each error. /// /// Each error only shows the error message without any context. void printToStream(llvm::raw_ostream &OS) const; std::string toString() const; - /// \brief Returns the full string representation of each error. + /// Returns the full string representation of each error. /// /// Each error message contains the full context. void printToStreamFull(llvm::raw_ostream &OS) const; std::string toStringFull() const; private: - /// \brief Helper function used by the constructors of ContextFrame. + /// Helper function used by the constructors of ContextFrame. ArgStream pushContextFrame(ContextType Type, SourceRange Range); std::vector<ContextFrame> ContextStack; diff --git a/include/clang/ASTMatchers/Dynamic/Parser.h b/include/clang/ASTMatchers/Dynamic/Parser.h index e8fcf0a9d6ccd..907db69529d28 100644 --- a/include/clang/ASTMatchers/Dynamic/Parser.h +++ b/include/clang/ASTMatchers/Dynamic/Parser.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Simple matcher expression parser. +/// Simple matcher expression parser. /// /// The parser understands matcher expressions of the form: /// MatcherName(Arg0, Arg1, ..., ArgN) @@ -52,10 +52,10 @@ namespace dynamic { class Diagnostics; -/// \brief Matcher expression parser. +/// Matcher expression parser. class Parser { public: - /// \brief Interface to connect the parser with the registry and more. + /// Interface to connect the parser with the registry and more. /// /// The parser uses the Sema instance passed into /// parseMatcherExpression() to handle all matcher tokens. The simplest @@ -69,7 +69,7 @@ public: public: virtual ~Sema(); - /// \brief Process a matcher expression. + /// Process a matcher expression. /// /// All the arguments passed here have already been processed. /// @@ -92,7 +92,7 @@ public: ArrayRef<ParserValue> Args, Diagnostics *Error) = 0; - /// \brief Look up a matcher by name. + /// Look up a matcher by name. /// /// \param MatcherName The matcher name found by the parser. /// @@ -101,7 +101,7 @@ public: virtual llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName) = 0; - /// \brief Compute the list of completion types for \p Context. + /// 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 @@ -112,7 +112,7 @@ public: virtual std::vector<ArgKind> getAcceptedCompletionTypes( llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); - /// \brief Compute the list of completions that match any of + /// Compute the list of completions that match any of /// \p AcceptedTypes. /// /// \param AcceptedTypes All types accepted for this completion. @@ -125,7 +125,7 @@ public: getMatcherCompletions(llvm::ArrayRef<ArgKind> AcceptedTypes); }; - /// \brief Sema implementation that uses the matcher registry to process the + /// Sema implementation that uses the matcher registry to process the /// tokens. class RegistrySema : public Parser::Sema { public: @@ -149,7 +149,7 @@ public: using NamedValueMap = llvm::StringMap<VariantValue>; - /// \brief Parse a matcher expression. + /// Parse a matcher expression. /// /// \param MatcherCode The matcher expression to parse. /// @@ -178,7 +178,7 @@ public: return parseMatcherExpression(MatcherCode, nullptr, Error); } - /// \brief Parse an expression. + /// Parse an expression. /// /// Parses any expression supported by this parser. In general, the /// \c parseMatcherExpression function is a better approach to get a matcher @@ -202,7 +202,7 @@ public: return parseExpression(Code, nullptr, Value, Error); } - /// \brief Complete an expression at the given offset. + /// 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. diff --git a/include/clang/ASTMatchers/Dynamic/Registry.h b/include/clang/ASTMatchers/Dynamic/Registry.h index 277491250db8f..ad8628b4b0d97 100644 --- a/include/clang/ASTMatchers/Dynamic/Registry.h +++ b/include/clang/ASTMatchers/Dynamic/Registry.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Registry of all known matchers. +/// Registry of all known matchers. /// /// The registry provides a generic interface to construct any matcher by name. // @@ -49,13 +49,13 @@ struct MatcherCompletion { return TypedText == Other.TypedText && MatcherDecl == Other.MatcherDecl; } - /// \brief The text to type to select this matcher. + /// The text to type to select this matcher. std::string TypedText; - /// \brief The "declaration" of the matcher, with type information. + /// The "declaration" of the matcher, with type information. std::string MatcherDecl; - /// \brief Value corresponding to the "specificity" of the converted matcher. + /// 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. @@ -67,13 +67,13 @@ class Registry { public: Registry() = delete; - /// \brief Look up a matcher in the registry by name, + /// Look up a matcher in the registry by name, /// /// \return An opaque value which may be used to refer to the matcher /// constructor, or Optional<MatcherCtor>() if not found. static llvm::Optional<MatcherCtor> lookupMatcherCtor(StringRef MatcherName); - /// \brief Compute the list of completion types for \p Context. + /// 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 @@ -84,7 +84,7 @@ public: static std::vector<ArgKind> getAcceptedCompletionTypes( llvm::ArrayRef<std::pair<MatcherCtor, unsigned>> Context); - /// \brief Compute the list of completions that match any of + /// Compute the list of completions that match any of /// \p AcceptedTypes. /// /// \param AcceptedTypes All types accepted for this completion. @@ -96,7 +96,7 @@ public: static std::vector<MatcherCompletion> getMatcherCompletions(ArrayRef<ArgKind> AcceptedTypes); - /// \brief Construct a matcher from the registry. + /// Construct a matcher from the registry. /// /// \param Ctor The matcher constructor to instantiate. /// @@ -116,7 +116,7 @@ public: ArrayRef<ParserValue> Args, Diagnostics *Error); - /// \brief Construct a matcher from the registry and bind it. + /// Construct a matcher from the registry and bind it. /// /// Similar the \c constructMatcher() above, but it then tries to bind the /// matcher to the specified \c BindID. diff --git a/include/clang/ASTMatchers/Dynamic/VariantValue.h b/include/clang/ASTMatchers/Dynamic/VariantValue.h index f9efe0f16f437..45ac3cadf6857 100644 --- a/include/clang/ASTMatchers/Dynamic/VariantValue.h +++ b/include/clang/ASTMatchers/Dynamic/VariantValue.h @@ -7,7 +7,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Polymorphic value type. +/// Polymorphic value type. /// /// Supports all the types required for dynamic Matcher construction. /// Used by the registry to construct matchers in a generic way. @@ -28,7 +28,7 @@ namespace clang { namespace ast_matchers { namespace dynamic { -/// \brief Kind identifier. +/// Kind identifier. /// /// It supports all types that VariantValue can contain. class ArgKind { @@ -40,10 +40,10 @@ class ArgKind { AK_Unsigned, AK_String }; - /// \brief Constructor for non-matcher types. + /// Constructor for non-matcher types. ArgKind(Kind K) : K(K) { assert(K != AK_Matcher); } - /// \brief Constructor for matcher types. + /// Constructor for matcher types. ArgKind(ast_type_traits::ASTNodeKind MatcherKind) : K(AK_Matcher), MatcherKind(MatcherKind) {} @@ -53,7 +53,7 @@ class ArgKind { return MatcherKind; } - /// \brief Determines if this type can be converted to \p To. + /// Determines if this type can be converted to \p To. /// /// \param To the requested destination type. /// @@ -67,7 +67,7 @@ class ArgKind { return K < Other.K; } - /// \brief String representation of the type. + /// String representation of the type. std::string asString() const; private: @@ -77,7 +77,7 @@ private: using ast_matchers::internal::DynTypedMatcher; -/// \brief A variant matcher object. +/// A variant matcher object. /// /// The purpose of this object is to abstract simple and polymorphic matchers /// into a single object type. @@ -91,7 +91,7 @@ using ast_matchers::internal::DynTypedMatcher; /// - hasTypedMatcher<T>()/getTypedMatcher<T>(): These calls will determine if /// the underlying matcher(s) can unambiguously return a Matcher<T>. class VariantMatcher { - /// \brief Methods that depend on T from hasTypedMatcher/getTypedMatcher. + /// Methods that depend on T from hasTypedMatcher/getTypedMatcher. class MatcherOps { public: MatcherOps(ast_type_traits::ASTNodeKind NodeKind) : NodeKind(NodeKind) {} @@ -99,12 +99,12 @@ class VariantMatcher { bool canConstructFrom(const DynTypedMatcher &Matcher, bool &IsExactMatch) const; - /// \brief Convert \p Matcher the destination type and return it as a new + /// 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. + /// 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> @@ -118,7 +118,7 @@ class VariantMatcher { ast_type_traits::ASTNodeKind NodeKind; }; - /// \brief Payload interface to be specialized by each matcher type. + /// Payload interface to be specialized by each matcher type. /// /// It follows a similar interface as VariantMatcher itself. class Payload { @@ -133,39 +133,39 @@ class VariantMatcher { }; public: - /// \brief A null matcher. + /// A null matcher. VariantMatcher(); - /// \brief Clones the provided matcher. + /// Clones the provided matcher. static VariantMatcher SingleMatcher(const DynTypedMatcher &Matcher); - /// \brief Clones the provided matchers. + /// Clones the provided matchers. /// /// They should be the result of a polymorphic matcher. static VariantMatcher PolymorphicMatcher(std::vector<DynTypedMatcher> Matchers); - /// \brief Creates a 'variadic' operator matcher. + /// Creates a 'variadic' operator matcher. /// /// It will bind to the appropriate type on getTypedMatcher<T>(). static VariantMatcher VariadicOperatorMatcher(DynTypedMatcher::VariadicOperator Op, std::vector<VariantMatcher> Args); - /// \brief Makes the matcher the "null" matcher. + /// Makes the matcher the "null" matcher. void reset(); - /// \brief Whether the matcher is null. + /// Whether the matcher is null. bool isNull() const { return !Value; } - /// \brief Return a single matcher, if there is no ambiguity. + /// Return a single matcher, if there is no ambiguity. /// /// \returns the matcher, if there is only one matcher. An empty Optional, if /// the underlying matcher is a polymorphic matcher with more than one /// representation. llvm::Optional<DynTypedMatcher> getSingleMatcher() const; - /// \brief Determines if the contained matcher can be converted to + /// Determines if the contained matcher can be converted to /// \c Matcher<T>. /// /// For the Single case, it returns true if it can be converted to @@ -179,7 +179,7 @@ public: return Value->getTypedMatcher(TypedMatcherOps<T>()).hasValue(); } - /// \brief Determines if the contained matcher can be converted to \p Kind. + /// Determines if the contained matcher can be converted to \p Kind. /// /// \param Kind the requested destination type. /// @@ -192,7 +192,7 @@ public: return false; } - /// \brief Return this matcher as a \c Matcher<T>. + /// Return this matcher as a \c Matcher<T>. /// /// Handles the different types (Single, Polymorphic) accordingly. /// Asserts that \c hasTypedMatcher<T>() is true. @@ -203,7 +203,7 @@ public: ->template convertTo<T>(); } - /// \brief String representation of the type of the value. + /// String representation of the type of the value. /// /// If the underlying matcher is a polymorphic one, the string will show all /// the types. @@ -234,7 +234,7 @@ struct VariantMatcher::TypedMatcherOps final : VariantMatcher::MatcherOps { } }; -/// \brief Variant value class. +/// Variant value class. /// /// Basically, a tagged union with value type semantics. /// It is used by the registry as the return value and argument type for the @@ -256,46 +256,46 @@ public: ~VariantValue(); VariantValue &operator=(const VariantValue &Other); - /// \brief Specific constructors for each supported type. + /// Specific constructors for each supported type. VariantValue(bool Boolean); VariantValue(double Double); VariantValue(unsigned Unsigned); VariantValue(StringRef String); VariantValue(const VariantMatcher &Matchers); - /// \brief Constructs an \c unsigned value (disambiguation from bool). + /// Constructs an \c unsigned value (disambiguation from bool). VariantValue(int Signed) : VariantValue(static_cast<unsigned>(Signed)) {} - /// \brief Returns true iff this is not an empty value. + /// Returns true iff this is not an empty value. explicit operator bool() const { return hasValue(); } bool hasValue() const { return Type != VT_Nothing; } - /// \brief Boolean value functions. + /// Boolean value functions. bool isBoolean() const; bool getBoolean() const; void setBoolean(bool Boolean); - /// \brief Double value functions. + /// Double value functions. bool isDouble() const; double getDouble() const; void setDouble(double Double); - /// \brief Unsigned value functions. + /// Unsigned value functions. bool isUnsigned() const; unsigned getUnsigned() const; void setUnsigned(unsigned Unsigned); - /// \brief String value functions. + /// String value functions. bool isString() const; const std::string &getString() const; void setString(StringRef String); - /// \brief Matcher value functions. + /// Matcher value functions. bool isMatcher() const; const VariantMatcher &getMatcher() const; void setMatcher(const VariantMatcher &Matcher); - /// \brief Determines if the contained value can be converted to \p Kind. + /// Determines if the contained value can be converted to \p Kind. /// /// \param Kind the requested destination type. /// @@ -303,7 +303,7 @@ public: /// conversion. bool isConvertibleTo(ArgKind Kind, unsigned* Specificity) const; - /// \brief Determines if the contained value can be converted to any kind + /// Determines if the contained value can be converted to any kind /// in \p Kinds. /// /// \param Kinds the requested destination types. @@ -313,13 +313,13 @@ public: /// conversions. bool isConvertibleTo(ArrayRef<ArgKind> Kinds, unsigned *Specificity) const; - /// \brief String representation of the type of the value. + /// String representation of the type of the value. std::string getTypeAsString() const; private: void reset(); - /// \brief All supported value types. + /// All supported value types. enum ValueType { VT_Nothing, VT_Boolean, @@ -329,7 +329,7 @@ private: VT_Matcher }; - /// \brief All supported value types. + /// All supported value types. union AllValues { unsigned Unsigned; double Double; diff --git a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h index cc14c7bd33dbc..da59514c4fa6e 100644 --- a/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h +++ b/include/clang/Analysis/Analyses/CFGReachabilityAnalysis.h @@ -1,4 +1,4 @@ -//==- CFGReachabilityAnalysis.h - Basic reachability analysis ----*- C++ -*-==// +//===- CFGReachabilityAnalysis.h - Basic reachability analysis --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -30,10 +30,12 @@ class CFGBlock; // from the destination node and cache the results to prevent work // duplication. class CFGReverseBlockReachabilityAnalysis { - typedef llvm::BitVector ReachableSet; - typedef llvm::DenseMap<unsigned, ReachableSet> ReachableMap; + using ReachableSet = llvm::BitVector; + using ReachableMap = llvm::DenseMap<unsigned, ReachableSet>; + ReachableSet analyzed; ReachableMap reachable; + public: CFGReverseBlockReachabilityAnalysis(const CFG &cfg); @@ -44,6 +46,6 @@ private: void mapReachability(const CFGBlock *Dst); }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CFGREACHABILITYANALYSIS_H diff --git a/include/clang/Analysis/Analyses/Consumed.h b/include/clang/Analysis/Analyses/Consumed.h index 5ba42b475c830..6003d665fd88b 100644 --- a/include/clang/Analysis/Analyses/Consumed.h +++ b/include/clang/Analysis/Analyses/Consumed.h @@ -1,4 +1,4 @@ -//===- Consumed.h ----------------------------------------------*- C++ --*-===// +//===- Consumed.h -----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,32 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H #define LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H -#include "clang/AST/DeclCXX.h" -#include "clang/AST/ExprCXX.h" -#include "clang/AST/StmtCXX.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" -#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/PartialDiagnostic.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include <list> +#include <memory> +#include <utility> +#include <vector> namespace clang { + +class AnalysisDeclContext; +class CXXBindTemporaryExpr; +class FunctionDecl; +class PostOrderCFGView; +class Stmt; +class VarDecl; + namespace consumed { + class ConsumedStmtVisitor; + enum ConsumedState { // No state information for the given variable. CS_None, @@ -34,22 +50,18 @@ namespace consumed { CS_Consumed }; - class ConsumedStmtVisitor; - - typedef SmallVector<PartialDiagnosticAt, 1> OptionalNotes; - typedef std::pair<PartialDiagnosticAt, OptionalNotes> DelayedDiag; - typedef std::list<DelayedDiag> DiagList; + using OptionalNotes = SmallVector<PartialDiagnosticAt, 1>; + using DelayedDiag = std::pair<PartialDiagnosticAt, OptionalNotes>; + using DiagList = std::list<DelayedDiag>; class ConsumedWarningsHandlerBase { - public: - virtual ~ConsumedWarningsHandlerBase(); - /// \brief Emit the warnings and notes left by the analysis. + /// Emit the warnings and notes left by the analysis. virtual void emitDiagnostics() {} - /// \brief Warn that a variable's state doesn't match at the entry and exit + /// Warn that a variable's state doesn't match at the entry and exit /// of a loop. /// /// \param Loc -- The location of the end of the loop. @@ -59,7 +71,7 @@ namespace consumed { virtual void warnLoopStateMismatch(SourceLocation Loc, StringRef VariableName) {} - /// \brief Warn about parameter typestate mismatches upon return. + /// Warn about parameter typestate mismatches upon return. /// /// \param Loc -- The SourceLocation of the return statement. /// @@ -80,7 +92,7 @@ namespace consumed { // FIXME: This can be removed when the attr propagation fix for templated // classes lands. - /// \brief Warn about return typestates set for unconsumable types. + /// Warn about return typestates set for unconsumable types. /// /// \param Loc -- The location of the attributes. /// @@ -88,7 +100,7 @@ namespace consumed { virtual void warnReturnTypestateForUnconsumableType(SourceLocation Loc, StringRef TypeName) {} - /// \brief Warn about return typestate mismatches. + /// Warn about return typestate mismatches. /// /// \param Loc -- The SourceLocation of the return statement. /// @@ -101,7 +113,7 @@ namespace consumed { StringRef ExpectedState, StringRef ObservedState) {} - /// \brief Warn about use-while-consumed errors. + /// Warn about use-while-consumed errors. /// \param MethodName -- The name of the method that was incorrectly /// invoked. /// @@ -112,7 +124,7 @@ namespace consumed { StringRef State, SourceLocation Loc) {} - /// \brief Warn about use-while-consumed errors. + /// Warn about use-while-consumed errors. /// \param MethodName -- The name of the method that was incorrectly /// invoked. /// @@ -129,66 +141,64 @@ namespace consumed { }; class ConsumedStateMap { - - typedef llvm::DenseMap<const VarDecl *, ConsumedState> VarMapType; - typedef llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState> - TmpMapType; + using VarMapType = llvm::DenseMap<const VarDecl *, ConsumedState>; + using TmpMapType = + llvm::DenseMap<const CXXBindTemporaryExpr *, ConsumedState>; protected: - - bool Reachable; - const Stmt *From; + bool Reachable = true; + const Stmt *From = nullptr; VarMapType VarMap; TmpMapType TmpMap; public: - ConsumedStateMap() : Reachable(true), From(nullptr) {} + ConsumedStateMap() = default; ConsumedStateMap(const ConsumedStateMap &Other) - : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap), - TmpMap() {} + : Reachable(Other.Reachable), From(Other.From), VarMap(Other.VarMap), + TmpMap() {} - /// \brief Warn if any of the parameters being tracked are not in the state + /// Warn if any of the parameters being tracked are not in the state /// they were declared to be in upon return from a function. void checkParamsForReturnTypestate(SourceLocation BlameLoc, ConsumedWarningsHandlerBase &WarningsHandler) const; - /// \brief Clear the TmpMap. + /// Clear the TmpMap. void clearTemporaries(); - /// \brief Get the consumed state of a given variable. + /// Get the consumed state of a given variable. ConsumedState getState(const VarDecl *Var) const; - /// \brief Get the consumed state of a given temporary value. + /// Get the consumed state of a given temporary value. ConsumedState getState(const CXXBindTemporaryExpr *Tmp) const; - /// \brief Merge this state map with another map. + /// Merge this state map with another map. void intersect(const ConsumedStateMap &Other); void intersectAtLoopHead(const CFGBlock *LoopHead, const CFGBlock *LoopBack, const ConsumedStateMap *LoopBackStates, ConsumedWarningsHandlerBase &WarningsHandler); - /// \brief Return true if this block is reachable. + /// Return true if this block is reachable. bool isReachable() const { return Reachable; } - /// \brief Mark the block as unreachable. + /// Mark the block as unreachable. void markUnreachable(); - /// \brief Set the source for a decision about the branching of states. + /// Set the source for a decision about the branching of states. /// \param Source -- The statement that was the origin of a branching /// decision. void setSource(const Stmt *Source) { this->From = Source; } - /// \brief Set the consumed state of a given variable. + /// Set the consumed state of a given variable. void setState(const VarDecl *Var, ConsumedState State); - /// \brief Set the consumed state of a given temporary value. + /// Set the consumed state of a given temporary value. void setState(const CXXBindTemporaryExpr *Tmp, ConsumedState State); - /// \brief Remove the temporary value from our state map. + /// Remove the temporary value from our state map. void remove(const CXXBindTemporaryExpr *Tmp); - /// \brief Tests to see if there is a mismatch in the states stored in two + /// Tests to see if there is a mismatch in the states stored in two /// maps. /// /// \param Other -- The second map to compare against. @@ -205,10 +215,8 @@ namespace consumed { ConsumedBlockInfo(unsigned int NumBlocks, PostOrderCFGView *SortedGraph) : StateMapsArray(NumBlocks), VisitOrder(NumBlocks, 0) { unsigned int VisitOrderCounter = 0; - for (PostOrderCFGView::iterator BI = SortedGraph->begin(), - BE = SortedGraph->end(); BI != BE; ++BI) { - VisitOrder[(*BI)->getBlockID()] = VisitOrderCounter++; - } + for (const auto BI : *SortedGraph) + VisitOrder[BI->getBlockID()] = VisitOrderCounter++; } bool allBackEdgesVisited(const CFGBlock *CurrBlock, @@ -231,7 +239,6 @@ namespace consumed { /// A class that handles the analysis of uniqueness violations. class ConsumedAnalyzer { - ConsumedBlockInfo BlockInfo; std::unique_ptr<ConsumedStateMap> CurrStates; @@ -243,7 +250,6 @@ namespace consumed { const ConsumedStmtVisitor &Visitor); public: - ConsumedWarningsHandlerBase &WarningsHandler; ConsumedAnalyzer(ConsumedWarningsHandlerBase &WarningsHandler) @@ -251,7 +257,7 @@ namespace consumed { ConsumedState getExpectedReturnState() const { return ExpectedReturnState; } - /// \brief Check a function's CFG for consumed violations. + /// Check a function's CFG for consumed violations. /// /// We traverse the blocks in the CFG, keeping track of the state of each /// value who's type has uniquness annotations. If methods are invoked in @@ -259,6 +265,9 @@ namespace consumed { /// exactly once. void run(AnalysisDeclContext &AC); }; -}} // end namespace clang::consumed -#endif +} // namespace consumed + +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_CONSUMED_H diff --git a/include/clang/Analysis/Analyses/Dominators.h b/include/clang/Analysis/Analyses/Dominators.h index 6cb161ab37c8a..a9cdc5560bc07 100644 --- a/include/clang/Analysis/Analyses/Dominators.h +++ b/include/clang/Analysis/Analyses/Dominators.h @@ -1,4 +1,4 @@ -//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==// +//- Dominators.h - Implementation of dominators tree for Clang CFG -*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -16,29 +16,35 @@ #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/iterator.h" #include "llvm/Support/GenericDomTree.h" -#include "llvm/Support/GenericDomTreeConstruction.h" +#include "llvm/Support/GenericDomTreeConstruction.h" +#include "llvm/Support/raw_ostream.h" // FIXME: There is no good reason for the domtree to require a print method // which accepts an LLVM Module, so remove this (and the method's argument that // needs it) when that is fixed. + namespace llvm { + class Module; -} + +} // namespace llvm namespace clang { -class CFGBlock; -typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode; +using DomTreeNode = llvm::DomTreeNodeBase<CFGBlock>; -/// \brief Concrete subclass of DominatorTreeBase for Clang +/// Concrete subclass of DominatorTreeBase for Clang /// This class implements the dominators tree functionality given a Clang CFG. /// class DominatorTree : public ManagedAnalysis { virtual void anchor(); + public: - llvm::DomTreeBase<CFGBlock>* DT; + llvm::DomTreeBase<CFGBlock> *DT; DominatorTree() { DT = new llvm::DomTreeBase<CFGBlock>(); @@ -48,23 +54,21 @@ public: llvm::DomTreeBase<CFGBlock>& getBase() { return *DT; } - /// \brief This method returns the root CFGBlock of the dominators tree. - /// - inline CFGBlock *getRoot() const { + /// This method returns the root CFGBlock of the dominators tree. + CFGBlock *getRoot() const { return DT->getRoot(); } - /// \brief This method returns the root DomTreeNode, which is the wrapper + /// This method returns the root DomTreeNode, which is the wrapper /// for CFGBlock. - inline DomTreeNode *getRootNode() const { + DomTreeNode *getRootNode() const { return DT->getRootNode(); } - /// \brief This method compares two dominator trees. + /// This method compares two dominator trees. /// The method returns false if the other dominator tree matches this /// dominator tree, otherwise returns true. - /// - inline bool compare(DominatorTree &Other) const { + bool compare(DominatorTree &Other) const { DomTreeNode *R = getRootNode(); DomTreeNode *OtherR = Other.getRootNode(); @@ -77,17 +81,15 @@ public: return false; } - /// \brief This method builds the dominator tree for a given CFG + /// This method builds the dominator tree for a given CFG /// The CFG information is passed via AnalysisDeclContext - /// void buildDominatorTree(AnalysisDeclContext &AC) { cfg = AC.getCFG(); DT->recalculate(*cfg); } - /// \brief This method dumps immediate dominators for each block, + /// This method dumps immediate dominators for each block, /// mainly used for debug purposes. - /// void dump() { llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n"; for (CFG::const_iterator I = cfg->begin(), @@ -102,55 +104,48 @@ public: } } - /// \brief This method tests if one CFGBlock dominates the other. + /// This method tests if one CFGBlock dominates the other. /// The method return true if A dominates B, false otherwise. /// Note a block always dominates itself. - /// - inline bool dominates(const CFGBlock* A, const CFGBlock* B) const { + bool dominates(const CFGBlock *A, const CFGBlock *B) const { return DT->dominates(A, B); } - /// \brief This method tests if one CFGBlock properly dominates the other. + /// This method tests if one CFGBlock properly dominates the other. /// The method return true if A properly dominates B, false otherwise. - /// - bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const { + bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const { return DT->properlyDominates(A, B); } - /// \brief This method finds the nearest common dominator CFG block + /// This method finds the nearest common dominator CFG block /// for CFG block A and B. If there is no such block then return NULL. - /// - inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) { + CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) { return DT->findNearestCommonDominator(A, B); } - inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A, - const CFGBlock *B) { + const CFGBlock *findNearestCommonDominator(const CFGBlock *A, + const CFGBlock *B) { return DT->findNearestCommonDominator(A, B); } - /// \brief This method is used to update the dominator + /// This method is used to update the dominator /// tree information when a node's immediate dominator changes. - /// - inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) { + void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) { DT->changeImmediateDominator(N, NewIDom); } - /// \brief This method tests if the given CFGBlock can be reachable from root. + /// This method tests if the given CFGBlock can be reachable from root. /// Returns true if reachable, false otherwise. - /// bool isReachableFromEntry(const CFGBlock *A) { return DT->isReachableFromEntry(A); } - /// \brief This method releases the memory held by the dominator tree. - /// + /// This method releases the memory held by the dominator tree. virtual void releaseMemory() { DT->releaseMemory(); } - /// \brief This method converts the dominator tree to human readable form. - /// + /// This method converts the dominator tree to human readable form. virtual void print(raw_ostream &OS, const llvm::Module* M= nullptr) const { DT->print(OS); } @@ -159,23 +154,24 @@ private: CFG *cfg; }; -} // end namespace clang +} // namespace clang //===------------------------------------- /// DominatorTree GraphTraits specialization so the DominatorTree can be /// iterable by generic graph iterators. /// namespace llvm { + template <> struct GraphTraits< ::clang::DomTreeNode* > { - typedef ::clang::DomTreeNode *NodeRef; - typedef ::clang::DomTreeNode::iterator ChildIteratorType; + using NodeRef = ::clang::DomTreeNode *; + using ChildIteratorType = ::clang::DomTreeNode::iterator; static NodeRef getEntryNode(NodeRef N) { return N; } static ChildIteratorType child_begin(NodeRef N) { return N->begin(); } static ChildIteratorType child_end(NodeRef N) { return N->end(); } - typedef llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>> - nodes_iterator; + using nodes_iterator = + llvm::pointer_iterator<df_iterator<::clang::DomTreeNode *>>; static nodes_iterator nodes_begin(::clang::DomTreeNode *N) { return nodes_iterator(df_begin(getEntryNode(N))); @@ -187,7 +183,7 @@ template <> struct GraphTraits< ::clang::DomTreeNode* > { }; template <> struct GraphTraits< ::clang::DominatorTree* > - : public GraphTraits< ::clang::DomTreeNode* > { + : public GraphTraits< ::clang::DomTreeNode* > { static NodeRef getEntryNode(::clang::DominatorTree *DT) { return DT->getRootNode(); } @@ -200,6 +196,7 @@ template <> struct GraphTraits< ::clang::DominatorTree* > return nodes_iterator(df_end(getEntryNode(N))); } }; -} // end namespace llvm -#endif +} // namespace llvm + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_DOMINATORS_H diff --git a/include/clang/Analysis/Analyses/FormatString.h b/include/clang/Analysis/Analyses/FormatString.h index 8c531d638cc22..6f8bb9b4095fa 100644 --- a/include/clang/Analysis/Analyses/FormatString.h +++ b/include/clang/Analysis/Analyses/FormatString.h @@ -256,18 +256,26 @@ public: private: const Kind K; QualType T; - const char *Name; - bool Ptr; + const char *Name = nullptr; + bool Ptr = false; + + /// The TypeKind identifies certain well-known types like size_t and + /// ptrdiff_t. + enum class TypeKind { DontCare, SizeT, PtrdiffT }; + TypeKind TK = TypeKind::DontCare; + public: - ArgType(Kind k = UnknownTy, const char *n = nullptr) - : K(k), Name(n), Ptr(false) {} - ArgType(QualType t, const char *n = nullptr) - : K(SpecificTy), T(t), Name(n), Ptr(false) {} - ArgType(CanQualType t) : K(SpecificTy), T(t), Name(nullptr), Ptr(false) {} + ArgType(Kind K = UnknownTy, const char *N = nullptr) : K(K), Name(N) {} + ArgType(QualType T, const char *N = nullptr) : K(SpecificTy), T(T), Name(N) {} + ArgType(CanQualType T) : K(SpecificTy), T(T) {} static ArgType Invalid() { return ArgType(InvalidTy); } bool isValid() const { return K != InvalidTy; } + bool isSizeT() const { return TK == TypeKind::SizeT; } + + bool isPtrdiffT() const { return TK == TypeKind::PtrdiffT; } + /// Create an ArgType which corresponds to the type pointer to A. static ArgType PtrTo(const ArgType& A) { assert(A.K >= InvalidTy && "ArgType cannot be pointer to invalid/unknown"); @@ -276,6 +284,21 @@ public: return Res; } + /// Create an ArgType which corresponds to the size_t/ssize_t type. + static ArgType makeSizeT(const ArgType &A) { + ArgType Res = A; + Res.TK = TypeKind::SizeT; + return Res; + } + + /// Create an ArgType which corresponds to the ptrdiff_t/unsigned ptrdiff_t + /// type. + static ArgType makePtrdiffT(const ArgType &A) { + ArgType Res = A; + Res.TK = TypeKind::PtrdiffT; + return Res; + } + MatchKind matchesType(ASTContext &C, QualType argTy) const; QualType getRepresentativeType(ASTContext &C) const; @@ -510,7 +533,7 @@ public: return getConversionSpecifier().consumesDataArgument(); } - /// \brief Returns the builtin type that a data argument + /// Returns the builtin type that a data argument /// paired with this format specifier should have. This method /// will return null if the format specifier does not have /// a matching data argument or the matching argument matches diff --git a/include/clang/Analysis/Analyses/LiveVariables.h b/include/clang/Analysis/Analyses/LiveVariables.h index 6a1222386bae1..21c3ba255c366 100644 --- a/include/clang/Analysis/Analyses/LiveVariables.h +++ b/include/clang/Analysis/Analyses/LiveVariables.h @@ -33,15 +33,18 @@ public: llvm::ImmutableSet<const Stmt *> liveStmts; llvm::ImmutableSet<const VarDecl *> liveDecls; + llvm::ImmutableSet<const BindingDecl *> liveBindings; bool equals(const LivenessValues &V) const; LivenessValues() - : liveStmts(nullptr), liveDecls(nullptr) {} + : liveStmts(nullptr), liveDecls(nullptr), liveBindings(nullptr) {} LivenessValues(llvm::ImmutableSet<const Stmt *> LiveStmts, - llvm::ImmutableSet<const VarDecl *> LiveDecls) - : liveStmts(LiveStmts), liveDecls(LiveDecls) {} + llvm::ImmutableSet<const VarDecl *> LiveDecls, + llvm::ImmutableSet<const BindingDecl *> LiveBindings) + : liveStmts(LiveStmts), liveDecls(LiveDecls), + liveBindings(LiveBindings) {} bool isLive(const Stmt *S) const; bool isLive(const VarDecl *D) const; diff --git a/include/clang/Analysis/Analyses/PostOrderCFGView.h b/include/clang/Analysis/Analyses/PostOrderCFGView.h index c0a93528373e2..7df3dc66c3112 100644 --- a/include/clang/Analysis/Analyses/PostOrderCFGView.h +++ b/include/clang/Analysis/Analyses/PostOrderCFGView.h @@ -1,4 +1,4 @@ -//===- PostOrderCFGView.h - Post order view of CFG blocks ---------*- C++ --*-// +//===- PostOrderCFGView.h - Post order view of CFG blocks -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,22 +14,23 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H #define LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H -#include <vector> -//#include <algorithm> - -#include "llvm/ADT/PostOrderIterator.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/BitVector.h" - #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/BitVector.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/PostOrderIterator.h" +#include <utility> +#include <vector> namespace clang { class PostOrderCFGView : public ManagedAnalysis { virtual void anchor(); + public: - /// \brief Implements a set of CFGBlocks using a BitVector. + /// Implements a set of CFGBlocks using a BitVector. /// /// This class contains a minimal interface, primarily dictated by the SetType /// template parameter of the llvm::po_iterator template, as used with @@ -37,15 +38,16 @@ public: /// visit during the analysis. class CFGBlockSet { llvm::BitVector VisitedBlockIDs; + public: // po_iterator requires this iterator, but the only interface needed is the - // value_type typedef. - struct iterator { typedef const CFGBlock *value_type; }; + // value_type type. + struct iterator { using value_type = const CFGBlock *; }; - CFGBlockSet() {} + CFGBlockSet() = default; CFGBlockSet(const CFG *G) : VisitedBlockIDs(G->getNumBlockIDs(), false) {} - /// \brief Set the bit associated with a particular CFGBlock. + /// Set the bit associated with a particular CFGBlock. /// This is the important method for the SetType template parameter. std::pair<llvm::NoneType, bool> insert(const CFGBlock *Block) { // Note that insert() is called by po_iterator, which doesn't check to @@ -60,7 +62,7 @@ public: return std::make_pair(None, true); } - /// \brief Check if the bit for a CFGBlock has been already set. + /// Check if the bit for a CFGBlock has been already set. /// This method is for tracking visited blocks in the main threadsafety /// loop. Block must not be null. bool alreadySet(const CFGBlock *Block) { @@ -69,33 +71,34 @@ public: }; private: - typedef llvm::po_iterator<const CFG*, CFGBlockSet, true> po_iterator; - std::vector<const CFGBlock*> Blocks; + using po_iterator = llvm::po_iterator<const CFG *, CFGBlockSet, true>; + std::vector<const CFGBlock *> Blocks; - typedef llvm::DenseMap<const CFGBlock *, unsigned> BlockOrderTy; + using BlockOrderTy = llvm::DenseMap<const CFGBlock *, unsigned>; BlockOrderTy BlockOrder; public: - typedef std::vector<const CFGBlock *>::reverse_iterator iterator; - typedef std::vector<const CFGBlock *>::const_reverse_iterator const_iterator; + friend struct BlockOrderCompare; + + using iterator = std::vector<const CFGBlock *>::reverse_iterator; + using const_iterator = std::vector<const CFGBlock *>::const_reverse_iterator; PostOrderCFGView(const CFG *cfg); iterator begin() { return Blocks.rbegin(); } - iterator end() { return Blocks.rend(); } + iterator end() { return Blocks.rend(); } const_iterator begin() const { return Blocks.rbegin(); } const_iterator end() const { return Blocks.rend(); } bool empty() const { return begin() == end(); } - struct BlockOrderCompare; - friend struct BlockOrderCompare; - struct BlockOrderCompare { const PostOrderCFGView &POV; + public: BlockOrderCompare(const PostOrderCFGView &pov) : POV(pov) {} + bool operator()(const CFGBlock *b1, const CFGBlock *b2) const; }; @@ -109,7 +112,6 @@ public: static PostOrderCFGView *create(AnalysisDeclContext &analysisContext); }; -} // end clang namespace - -#endif +} // namespace clang +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_POSTORDERCFGVIEW_H diff --git a/include/clang/Analysis/Analyses/ThreadSafety.h b/include/clang/Analysis/Analyses/ThreadSafety.h index 7e403b1f40906..c72db6f2b24bb 100644 --- a/include/clang/Analysis/Analyses/ThreadSafety.h +++ b/include/clang/Analysis/Analyses/ThreadSafety.h @@ -1,4 +1,4 @@ -//===- ThreadSafety.h ------------------------------------------*- C++ --*-===// +//===- ThreadSafety.h -------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,11 +19,15 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H -#include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/StringRef.h" namespace clang { + +class AnalysisDeclContext; +class FunctionDecl; +class NamedDecl; + namespace threadSafety { class BeforeSet; @@ -31,27 +35,44 @@ class BeforeSet; /// 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_PassByRef, ///< Passing a guarded variable by reference. - POK_PtPassByRef, ///< Passing a pt-guarded variable by reference. + /// Dereferencing a variable (e.g. p in *p = 5;) + POK_VarDereference, + + /// Reading or writing a variable (e.g. x in x = 5;) + POK_VarAccess, + + /// Making a function call (e.g. fool()) + POK_FunctionCall, + + /// Passing a guarded variable by reference. + POK_PassByRef, + + /// Passing a pt-guarded variable by reference. + POK_PtPassByRef }; /// 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_Exclusive, ///< Exclusive/writer lock of a mutex. - LK_Generic ///< Can be either Shared or Exclusive + /// Shared/reader lock of a mutex. + LK_Shared, + + /// Exclusive/writer lock of a mutex. + LK_Exclusive, + + /// Can be either Shared or Exclusive. + LK_Generic }; /// This enum distinguishes between different ways to access (read or write) a /// variable. enum AccessKind { - AK_Read, ///< Reading a variable. - AK_Written ///< Writing a variable. + /// Reading a variable. + AK_Read, + + /// Writing a variable. + AK_Written }; /// This enum distinguishes between different situations where we warn due to @@ -72,8 +93,9 @@ enum LockErrorKind { /// Handler class for thread safety warnings. class ThreadSafetyHandler { public: - typedef StringRef Name; - ThreadSafetyHandler() : IssueBetaWarnings(false) { } + using Name = StringRef; + + ThreadSafetyHandler() = default; virtual ~ThreadSafetyHandler(); /// Warn about lock expressions which fail to resolve to lockable objects. @@ -185,7 +207,6 @@ public: virtual void handleFunExcludesLock(StringRef Kind, Name FunName, Name LockName, SourceLocation Loc) {} - /// Warn that L1 cannot be acquired before L2. virtual void handleLockAcquiredBefore(StringRef Kind, Name L1Name, Name L2Name, SourceLocation Loc) {} @@ -204,10 +225,10 @@ public: void setIssueBetaWarnings(bool b) { IssueBetaWarnings = b; } private: - bool IssueBetaWarnings; + bool IssueBetaWarnings = false; }; -/// \brief Check a function's CFG for thread-safety violations. +/// Check a function's CFG for thread-safety violations. /// /// We traverse the blocks in the CFG, compute the set of mutexes that are held /// at the end of each block, and issue warnings for thread safety violations. @@ -218,9 +239,11 @@ void runThreadSafetyAnalysis(AnalysisDeclContext &AC, void threadSafetyCleanup(BeforeSet *Cache); -/// \brief Helper function that returns a LockKind required for the given level +/// Helper function that returns a LockKind required for the given level /// of access. LockKind getLockKindFromAccessKind(AccessKind AK); -}} // end namespace clang::threadSafety -#endif +} // namespace threadSafety +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETY_H diff --git a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h index 414645b7231bd..580872e17ef46 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyCommon.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyCommon.h @@ -1,4 +1,4 @@ -//===- ThreadSafetyCommon.h ------------------------------------*- C++ --*-===// +//===- ThreadSafetyCommon.h -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -22,20 +22,41 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYCOMMON_H +#include "clang/AST/Decl.h" #include "clang/Analysis/Analyses/PostOrderCFGView.h" #include "clang/Analysis/Analyses/ThreadSafetyTIL.h" #include "clang/Analysis/Analyses/ThreadSafetyTraverse.h" +#include "clang/Analysis/Analyses/ThreadSafetyUtil.h" #include "clang/Analysis/AnalysisDeclContext.h" -#include "clang/Basic/OperatorKinds.h" -#include <memory> -#include <ostream> +#include "clang/Analysis/CFG.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" #include <sstream> +#include <string> +#include <utility> #include <vector> - namespace clang { -namespace threadSafety { +class AbstractConditionalOperator; +class ArraySubscriptExpr; +class BinaryOperator; +class CallExpr; +class CastExpr; +class CXXDestructorDecl; +class CXXMemberCallExpr; +class CXXOperatorCallExpr; +class CXXThisExpr; +class DeclRefExpr; +class DeclStmt; +class Expr; +class MemberExpr; +class Stmt; +class UnaryOperator; + +namespace threadSafety { // Various helper functions on til::SExpr namespace sx { @@ -72,9 +93,7 @@ inline std::string toString(const til::SExpr *E) { return ss.str(); } -} // end namespace sx - - +} // namespace sx // This class defines the interface of a clang CFG Visitor. // CFGWalker will invoke the following methods. @@ -123,11 +142,10 @@ class CFGVisitor { void exitCFG(const CFGBlock *Last) {} }; - // Walks the clang CFG, and invokes methods on a given CFGVisitor. class CFGWalker { public: - CFGWalker() : CFGraph(nullptr), ACtx(nullptr), SortedGraph(nullptr) {} + CFGWalker() = default; // Initialize the CFGWalker. This setup only needs to be done once, even // if there are multiple passes over the CFG. @@ -186,15 +204,15 @@ public: // Process statements for (const auto &BI : *CurrBlock) { switch (BI.getKind()) { - case CFGElement::Statement: { + case CFGElement::Statement: V.handleStatement(BI.castAs<CFGStmt>().getStmt()); break; - } + case CFGElement::AutomaticObjectDtor: { CFGAutomaticObjDtor AD = BI.castAs<CFGAutomaticObjDtor>(); - CXXDestructorDecl *DD = const_cast<CXXDestructorDecl*>( + auto *DD = const_cast<CXXDestructorDecl *>( AD.getDestructorDecl(ACtx->getASTContext())); - VarDecl *VD = const_cast<VarDecl*>(AD.getVarDecl()); + auto *VD = const_cast<VarDecl *>(AD.getVarDecl()); V.handleDestructorCall(VD, DD); break; } @@ -242,28 +260,27 @@ public: const PostOrderCFGView *getSortedGraph() const { return SortedGraph; } private: - CFG *CFGraph; - AnalysisDeclContext *ACtx; - PostOrderCFGView *SortedGraph; + CFG *CFGraph = nullptr; + AnalysisDeclContext *ACtx = nullptr; + PostOrderCFGView *SortedGraph = nullptr; }; - - - +// 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. 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 + /// The capability expression. + const til::SExpr* CapExpr; + + /// True if this is a negative capability. + bool Negated; public: CapabilityExpr(const til::SExpr *E, bool Neg) : CapExpr(E), Negated(Neg) {} - const til::SExpr* sexpr() const { return CapExpr; } - bool negative() const { return Negated; } + const til::SExpr* sexpr() const { return CapExpr; } + bool negative() const { return Negated; } CapabilityExpr operator!() const { return CapabilityExpr(CapExpr, !Negated); @@ -289,9 +306,9 @@ public: const ValueDecl* valueDecl() const { if (Negated || CapExpr == nullptr) return nullptr; - if (auto *P = dyn_cast<til::Project>(CapExpr)) + if (const auto *P = dyn_cast<til::Project>(CapExpr)) return P->clangDecl(); - if (auto *P = dyn_cast<til::LiteralPtr>(CapExpr)) + if (const auto *P = dyn_cast<til::LiteralPtr>(CapExpr)) return P->clangDecl(); return nullptr; } @@ -309,12 +326,10 @@ public: bool isUniversal() const { return sexpr() && isa<til::Wildcard>(sexpr()); } }; - - // Translate clang::Expr to til::SExpr. class SExprBuilder { public: - /// \brief Encapsulates the lexical context of a function call. The lexical + /// Encapsulates the lexical context of a function call. The lexical /// context includes the arguments to the call, including the implicit object /// argument. When an attribute containing a mutex expression is attached to /// a method, the expression may refer to formal parameters of the method. @@ -324,22 +339,29 @@ 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 - bool SelfArrow; // is Self referred to with -> or .? + // The previous context; or 0 if none. + CallingContext *Prev; + + // The decl to which the attr is attached. + const NamedDecl *AttrDecl; + + // Implicit object argument -- e.g. 'this' + const Expr *SelfArg = nullptr; + + // Number of funArgs + unsigned NumArgs = 0; + + // Function arguments + const Expr *const *FunArgs = nullptr; + + // is Self referred to with -> or .? + bool SelfArrow = false; CallingContext(CallingContext *P, const NamedDecl *D = nullptr) - : Prev(P), AttrDecl(D), SelfArg(nullptr), - NumArgs(0), FunArgs(nullptr), SelfArrow(false) - {} + : Prev(P), AttrDecl(D) {} }; - SExprBuilder(til::MemRegionRef A) - : Arena(A), SelfVar(nullptr), Scfg(nullptr), CurrentBB(nullptr), - CurrentBlockInfo(nullptr) { + SExprBuilder(til::MemRegionRef A) : Arena(A) { // FIXME: we don't always have a self-variable. SelfVar = new (Arena) til::Variable(nullptr); SelfVar->setKind(til::Variable::VK_SFun); @@ -368,6 +390,9 @@ public: til::SCFG *getCFG() { return Scfg; } private: + // We implement the CFGVisitor API + friend class CFGWalker; + til::SExpr *translateDeclRefExpr(const DeclRefExpr *DRE, CallingContext *Ctx) ; til::SExpr *translateCXXThisExpr(const CXXThisExpr *TE, CallingContext *Ctx); @@ -397,31 +422,30 @@ private: til::SExpr *translateDeclStmt(const DeclStmt *S, CallingContext *Ctx); // Map from statements in the clang CFG to SExprs in the til::SCFG. - typedef llvm::DenseMap<const Stmt*, til::SExpr*> StatementMap; + using StatementMap = llvm::DenseMap<const Stmt *, til::SExpr *>; // Map from clang local variables to indices in a LVarDefinitionMap. - typedef llvm::DenseMap<const ValueDecl *, unsigned> LVarIndexMap; + using LVarIndexMap = llvm::DenseMap<const ValueDecl *, unsigned>; // Map from local variable indices to SSA variables (or constants). - typedef std::pair<const ValueDecl *, til::SExpr *> NameVarPair; - typedef CopyOnWriteVector<NameVarPair> LVarDefinitionMap; + using NameVarPair = std::pair<const ValueDecl *, til::SExpr *>; + using LVarDefinitionMap = CopyOnWriteVector<NameVarPair>; struct BlockInfo { LVarDefinitionMap ExitMap; - bool HasBackEdges; - unsigned UnprocessedSuccessors; // Successors yet to be processed - unsigned ProcessedPredecessors; // Predecessors already processed + bool HasBackEdges = false; - BlockInfo() - : HasBackEdges(false), UnprocessedSuccessors(0), - ProcessedPredecessors(0) {} + // Successors yet to be processed + unsigned UnprocessedSuccessors = 0; + + // Predecessors already processed + unsigned ProcessedPredecessors = 0; + + BlockInfo() = default; BlockInfo(BlockInfo &&) = default; BlockInfo &operator=(BlockInfo &&) = default; }; - // We implement the CFGVisitor API - friend class CFGWalker; - void enterCFG(CFG *Cfg, const NamedDecl *D, const CFGBlock *First); void enterCFGBlock(const CFGBlock *B); bool visitPredecessors() { return true; } @@ -440,6 +464,7 @@ private: void insertStmt(const Stmt *S, til::SExpr *E) { SMap.insert(std::make_pair(S, E)); } + til::SExpr *getCurrentLVarDefinition(const ValueDecl *VD); til::SExpr *addStatement(til::SExpr *E, const Stmt *S, @@ -459,30 +484,36 @@ private: static const bool CapabilityExprMode = true; til::MemRegionRef Arena; - til::Variable *SelfVar; // Variable to use for 'this'. May be null. - 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. + // Variable to use for 'this'. May be null. + til::Variable *SelfVar = nullptr; + + til::SCFG *Scfg = nullptr; + + // Map from Stmt to TIL Variables + StatementMap SMap; + + // Indices of clang local vars. + LVarIndexMap LVarIdxMap; + + // Map from clang to til BBs. + std::vector<til::BasicBlock *> BlockMap; + + // Extra information per BB. Indexed by clang BlockID. + std::vector<BlockInfo> BBInfo; LVarDefinitionMap CurrentLVarMap; - std::vector<til::Phi*> CurrentArguments; - std::vector<til::SExpr*> CurrentInstructions; - std::vector<til::Phi*> IncompleteArgs; - til::BasicBlock *CurrentBB; - BlockInfo *CurrentBlockInfo; + std::vector<til::Phi *> CurrentArguments; + std::vector<til::SExpr *> CurrentInstructions; + std::vector<til::Phi *> IncompleteArgs; + til::BasicBlock *CurrentBB = nullptr; + BlockInfo *CurrentBlockInfo = nullptr; }; - // Dump an SCFG to llvm::errs(). void printSCFG(CFGWalker &Walker); +} // namespace threadSafety +} // namespace clang -} // end namespace threadSafety - -} // end namespace clang - -#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H +#endif // LLVM_CLANG_THREAD_SAFETY_COMMON_H diff --git a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h index bc78021343a45..2508af1af1079 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyLogical.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyLogical.h @@ -29,7 +29,7 @@ public: }; Opcode kind() const { return Kind; } - /// \brief Logical implication. Returns true if the LExpr implies RHS, i.e. if + /// Logical implication. Returns true if the LExpr implies RHS, i.e. if /// the LExpr holds, then RHS must hold. For example, (A & B) implies A. inline bool implies(const LExpr *RHS) const; @@ -92,7 +92,7 @@ public: static bool classof(const LExpr *E) { return E->kind() == LExpr::Not; } }; -/// \brief Logical implication. Returns true if LHS implies RHS, i.e. if LHS +/// Logical implication. Returns true if LHS implies RHS, i.e. if LHS /// holds, then RHS must hold. For example, (A & B) implies A. bool implies(const LExpr *LHS, const LExpr *RHS); diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h index 0a58d2a80250a..810f2052b7a5c 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTIL.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTIL.h @@ -1,4 +1,4 @@ -//===- ThreadSafetyTIL.h ---------------------------------------*- C++ --*-===// +//===- ThreadSafetyTIL.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -47,20 +47,33 @@ #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 "clang/AST/Decl.h" +#include "clang/Analysis/Analyses/ThreadSafetyUtil.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/raw_ostream.h" #include <algorithm> #include <cassert> #include <cstddef> -#include <stdint.h> +#include <cstdint> +#include <iterator> +#include <string> #include <utility> - namespace clang { + +class CallExpr; +class Expr; +class Stmt; + namespace threadSafety { namespace til { +class BasicBlock; /// Enum for the different distinct classes of SExpr enum TIL_Opcode { @@ -100,11 +113,21 @@ enum TIL_BinaryOpcode : unsigned char { /// 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) + + // Extend precision of numeric type + CAST_extendNum, + + // Truncate precision of numeric type + CAST_truncNum, + + // Convert to floating point type + CAST_toFloat, + + // Convert to integer type + CAST_toInt, + + // Convert smart pointer to pointer (C++ only) + CAST_objToPtr }; const TIL_Opcode COP_Min = COP_Future; @@ -122,7 +145,6 @@ 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 value type. /// Pointer types are further subdivided into the various heap-allocated @@ -150,22 +172,22 @@ struct ValueType { ST_128 }; + ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS) + : Base(B), Size(Sz), Signed(S), VectSize(VS) {} + inline static SizeType getSizeType(unsigned nbytes); template <class T> inline static ValueType getValueType(); - ValueType(BaseType B, SizeType Sz, bool S, unsigned char VS) - : Base(B), Size(Sz), Signed(S), VectSize(VS) - { } + BaseType Base; + SizeType Size; + bool Signed; - BaseType Base; - SizeType Size; - bool Signed; - unsigned char VectSize; // 0 for scalar, otherwise num elements in vector + // 0 for scalar, otherwise num elements in vector + unsigned char VectSize; }; - inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) { switch (nbytes) { case 1: return ST_8; @@ -177,7 +199,6 @@ inline ValueType::SizeType ValueType::getSizeType(unsigned nbytes) { } } - template<> inline ValueType ValueType::getValueType<void>() { return ValueType(BT_Void, ST_0, false, 0); @@ -253,13 +274,11 @@ inline ValueType ValueType::getValueType<void*>() { return ValueType(BT_Pointer, getSizeType(sizeof(void*)), false, 0); } - -class BasicBlock; - - /// Base class for AST nodes in the typed intermediate language. class SExpr { public: + SExpr() = delete; + TIL_Opcode opcode() const { return static_cast<TIL_Opcode>(Opcode); } // Subclasses of SExpr must define the following: @@ -280,6 +299,9 @@ public: return ::operator new(S, R); } + /// SExpr objects must be created in an arena. + void *operator new(size_t) = delete; + /// SExpr objects cannot be deleted. // This declaration is public to workaround a gcc bug that breaks building // with REQUIRES_EH=1. @@ -291,45 +313,33 @@ public: /// Returns the block, if this is an instruction in a basic block, /// otherwise returns null. - BasicBlock* block() const { return Block; } + 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), SExprID(0), Block(nullptr) {} - SExpr(const SExpr &E) - : Opcode(E.Opcode), Reserved(0), Flags(E.Flags), SExprID(0), - Block(nullptr) {} + SExpr(TIL_Opcode Op) : Opcode(Op) {} + SExpr(const SExpr &E) : Opcode(E.Opcode), Flags(E.Flags) {} const unsigned char Opcode; - unsigned char Reserved; - unsigned short Flags; - unsigned SExprID; - BasicBlock* Block; - -private: - SExpr() = delete; - - /// SExpr objects must be created in an arena. - void *operator new(size_t) = delete; + unsigned char Reserved = 0; + unsigned short Flags = 0; + unsigned SExprID = 0; + BasicBlock *Block = nullptr; }; - // Contains various helper functions for SExprs. namespace ThreadSafetyTIL { - inline bool isTrivial(const SExpr *E) { - unsigned Op = E->opcode(); - return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr; - } + +inline bool isTrivial(const SExpr *E) { + unsigned Op = E->opcode(); + return Op == COP_Variable || Op == COP_Literal || Op == COP_LiteralPtr; } -// Nodes which declare variables -class Function; -class SFunction; -class Let; +} // namespace ThreadSafetyTIL +// Nodes which declare variables /// A named variable, e.g. "x". /// @@ -345,28 +355,35 @@ class Let; /// pointer to the original declaration. class Variable : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; } - enum VariableKind { - VK_Let, ///< Let-variable - VK_Fun, ///< Function parameter - VK_SFun ///< SFunction (self) parameter + /// Let-variable + VK_Let, + + /// Function parameter + VK_Fun, + + /// SFunction (self) parameter + VK_SFun }; Variable(StringRef s, SExpr *D = nullptr) - : SExpr(COP_Variable), Name(s), Definition(D), Cvdecl(nullptr) { + : SExpr(COP_Variable), Name(s), Definition(D) { Flags = VK_Let; } - Variable(SExpr *D, const clang::ValueDecl *Cvd = nullptr) + + Variable(SExpr *D, const 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(); } + static bool classof(const SExpr *E) { return E->opcode() == COP_Variable; } + /// Return the kind of variable (let, function param, or self) VariableKind kind() const { return static_cast<VariableKind>(Flags); } @@ -374,7 +391,7 @@ public: StringRef name() const { return Name; } /// Return the clang declaration for this variable, if any. - const clang::ValueDecl *clangDecl() const { return Cvdecl; } + const ValueDecl *clangDecl() const { return Cvdecl; } /// Return the definition of the variable. /// For let-vars, this is the setting expression. @@ -385,7 +402,7 @@ public: 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; } + void setClangDecl(const ValueDecl *VD) { Cvdecl = VD; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -399,42 +416,41 @@ public: } private: - friend class Function; - friend class SFunction; friend class BasicBlock; + friend class Function; friend class Let; + friend class SFunction; - StringRef Name; // The name of the variable. - SExpr* Definition; // The TIL type or definition - const clang::ValueDecl *Cvdecl; // The clang declaration for this variable. -}; + // The name of the variable. + StringRef Name; + + // The TIL type or definition. + SExpr *Definition; + // The clang declaration for this variable. + const ValueDecl *Cvdecl = nullptr; +}; /// 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; } - enum FutureStatus { FS_pending, FS_evaluating, FS_done }; - Future() : SExpr(COP_Future), Status(FS_pending), Result(nullptr) {} - -private: + Future() : SExpr(COP_Future) {} virtual ~Future() = delete; -public: + static bool classof(const SExpr *E) { return E->opcode() == COP_Future; } + // A lazy rewriting strategy should subclass Future and override this method. virtual SExpr *compute() { return nullptr; } // Return the result of this future if it exists, otherwise return null. - SExpr *maybeGetResult() const { - return Result; - } + SExpr *maybeGetResult() const { return Result; } // Return the result of this future; forcing it if necessary. SExpr *result() { @@ -464,19 +480,18 @@ public: private: SExpr* force(); - FutureStatus Status; - SExpr *Result; + FutureStatus Status = FS_pending; + SExpr *Result = nullptr; }; - /// 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; } - - Undefined(const clang::Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {} + Undefined(const Stmt *S = nullptr) : SExpr(COP_Undefined), Cstmt(S) {} Undefined(const Undefined &U) : SExpr(U), Cstmt(U.Cstmt) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Undefined; } + template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { return Vs.reduceUndefined(*this); @@ -488,17 +503,16 @@ public: } private: - const clang::Stmt *Cstmt; + const Stmt *Cstmt; }; - /// 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; } - Wildcard() : SExpr(COP_Wildcard) {} - Wildcard(const Wildcard &W) : SExpr(W) {} + Wildcard(const Wildcard &) = default; + + static bool classof(const SExpr *E) { return E->opcode() == COP_Wildcard; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { return Vs.reduceWildcard(*this); @@ -510,22 +524,20 @@ public: } }; - template <class T> class LiteralT; // Base class for literal values. class Literal : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; } + Literal(const Expr *C) + : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C) {} + Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT) {} + Literal(const Literal &) = default; - Literal(const clang::Expr *C) - : SExpr(COP_Literal), ValType(ValueType::getValueType<void>()), Cexpr(C) - { } - Literal(ValueType VT) : SExpr(COP_Literal), ValType(VT), Cexpr(nullptr) {} - Literal(const Literal &L) : SExpr(L), ValType(L.ValType), Cexpr(L.Cexpr) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Literal; } // The clang expression for this literal. - const clang::Expr *clangExpr() const { return Cexpr; } + const Expr *clangExpr() const { return Cexpr; } ValueType valueType() const { return ValType; } @@ -546,26 +558,23 @@ public: private: const ValueType ValType; - const clang::Expr *Cexpr; + const Expr *Cexpr = nullptr; }; - // Derived class for literal values, which stores the actual value. template<class T> class LiteralT : public Literal { public: - LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) { } - LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) { } + LiteralT(T Dat) : Literal(ValueType::getValueType<T>()), Val(Dat) {} + LiteralT(const LiteralT<T> &L) : Literal(L), Val(L.Val) {} - T value() const { return Val;} + T value() const { return Val;} T& value() { return Val; } private: T Val; }; - - template <class V> typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) { if (Cexpr) @@ -622,18 +631,17 @@ typename V::R_SExpr Literal::traverse(V &Vs, typename V::R_Ctx Ctx) { return Vs.reduceLiteral(*this); } - /// 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; } + LiteralPtr(const ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {} + LiteralPtr(const LiteralPtr &) = default; - LiteralPtr(const clang::ValueDecl *D) : SExpr(COP_LiteralPtr), Cvdecl(D) {} - LiteralPtr(const LiteralPtr &R) : SExpr(R), Cvdecl(R.Cvdecl) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_LiteralPtr; } // The clang declaration for the value that this pointer points to. - const clang::ValueDecl *clangDecl() const { return Cvdecl; } + const ValueDecl *clangDecl() const { return Cvdecl; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -646,26 +654,26 @@ public: } private: - const clang::ValueDecl *Cvdecl; + const ValueDecl *Cvdecl; }; - /// 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; } - Function(Variable *Vd, SExpr *Bd) : SExpr(COP_Function), VarDecl(Vd), Body(Bd) { Vd->setKind(Variable::VK_Fun); } + Function(const Function &F, Variable *Vd, SExpr *Bd) // rewrite constructor : SExpr(F), VarDecl(Vd), Body(Bd) { Vd->setKind(Variable::VK_Fun); } + static bool classof(const SExpr *E) { return E->opcode() == COP_Function; } + Variable *variableDecl() { return VarDecl; } const Variable *variableDecl() const { return VarDecl; } @@ -700,20 +708,18 @@ private: SExpr* Body; }; - /// 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; } - SFunction(Variable *Vd, SExpr *B) : SExpr(COP_SFunction), VarDecl(Vd), Body(B) { assert(Vd->Definition == nullptr); Vd->setKind(Variable::VK_SFun); Vd->Definition = this; } + SFunction(const SFunction &F, Variable *Vd, SExpr *B) // rewrite constructor : SExpr(F), VarDecl(Vd), Body(B) { assert(Vd->Definition == nullptr); @@ -721,6 +727,8 @@ public: Vd->Definition = this; } + static bool classof(const SExpr *E) { return E->opcode() == COP_SFunction; } + Variable *variableDecl() { return VarDecl; } const Variable *variableDecl() const { return VarDecl; } @@ -752,16 +760,15 @@ private: SExpr* Body; }; - /// 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; } - Code(SExpr *T, SExpr *B) : SExpr(COP_Code), ReturnType(T), Body(B) {} Code(const Code &C, SExpr *T, SExpr *B) // rewrite constructor : SExpr(C), ReturnType(T), Body(B) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Code; } + SExpr *returnType() { return ReturnType; } const SExpr *returnType() const { return ReturnType; } @@ -788,16 +795,15 @@ private: SExpr* Body; }; - /// A typed, writable location in memory class Field : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Field; } - Field(SExpr *R, SExpr *B) : SExpr(COP_Field), Range(R), Body(B) {} Field(const Field &C, SExpr *R, SExpr *B) // rewrite constructor : SExpr(C), Range(R), Body(B) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Field; } + SExpr *range() { return Range; } const SExpr *range() const { return Range; } @@ -824,7 +830,6 @@ private: SExpr* Body; }; - /// 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. @@ -832,12 +837,11 @@ private: /// function. class Apply : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; } - Apply(SExpr *F, SExpr *A) : SExpr(COP_Apply), Fun(F), Arg(A) {} Apply(const Apply &A, SExpr *F, SExpr *Ar) // rewrite constructor - : SExpr(A), Fun(F), Arg(Ar) - {} + : SExpr(A), Fun(F), Arg(Ar) {} + + static bool classof(const SExpr *E) { return E->opcode() == COP_Apply; } SExpr *fun() { return Fun; } const SExpr *fun() const { return Fun; } @@ -865,16 +869,15 @@ private: SExpr* Arg; }; - /// 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; } - SApply(SExpr *Sf, SExpr *A = nullptr) : SExpr(COP_SApply), Sfun(Sf), Arg(A) {} SApply(SApply &A, SExpr *Sf, SExpr *Ar = nullptr) // rewrite constructor : SExpr(A), Sfun(Sf), Arg(Ar) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_SApply; } + SExpr *sfun() { return Sfun; } const SExpr *sfun() const { return Sfun; } @@ -904,23 +907,23 @@ private: SExpr* Arg; }; - /// 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; } - - Project(SExpr *R, const clang::ValueDecl *Cvd) + Project(SExpr *R, const ValueDecl *Cvd) : SExpr(COP_Project), Rec(R), Cvdecl(Cvd) { assert(Cvd && "ValueDecl must not be null"); } + static bool classof(const SExpr *E) { return E->opcode() == COP_Project; } + SExpr *record() { return Rec; } const SExpr *record() const { return Rec; } - const clang::ValueDecl *clangDecl() const { return Cvdecl; } + const ValueDecl *clangDecl() const { return Cvdecl; } bool isArrow() const { return (Flags & 0x01) != 0; } + void setArrow(bool b) { if (b) Flags |= 0x01; else Flags &= 0xFFFE; @@ -954,23 +957,22 @@ public: private: SExpr* Rec; mutable llvm::Optional<std::string> SlotName; - const clang::ValueDecl *Cvdecl; + const ValueDecl *Cvdecl; }; - /// 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; } - - Call(SExpr *T, const clang::CallExpr *Ce = nullptr) + Call(SExpr *T, const CallExpr *Ce = nullptr) : SExpr(COP_Call), Target(T), Cexpr(Ce) {} Call(const Call &C, SExpr *T) : SExpr(C), Target(T), Cexpr(C.Cexpr) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Call; } + SExpr *target() { return Target; } const SExpr *target() const { return Target; } - const clang::CallExpr *clangCallExpr() const { return Cexpr; } + const CallExpr *clangCallExpr() const { return Cexpr; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -985,15 +987,12 @@ public: private: SExpr* Target; - const clang::CallExpr *Cexpr; + const CallExpr *Cexpr; }; - /// 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; } - enum AllocKind { AK_Stack, AK_Heap @@ -1002,6 +1001,8 @@ public: Alloc(SExpr *D, AllocKind K) : SExpr(COP_Alloc), Dtype(D) { Flags = K; } Alloc(const Alloc &A, SExpr *Dt) : SExpr(A), Dtype(Dt) { Flags = A.kind(); } + static bool classof(const SExpr *E) { return E->opcode() == COP_Call; } + AllocKind kind() const { return static_cast<AllocKind>(Flags); } SExpr *dataType() { return Dtype; } @@ -1025,15 +1026,14 @@ private: SExpr* Dtype; }; - /// Load a value from memory. class Load : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Load; } - Load(SExpr *P) : SExpr(COP_Load), Ptr(P) {} Load(const Load &L, SExpr *P) : SExpr(L), Ptr(P) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Load; } + SExpr *pointer() { return Ptr; } const SExpr *pointer() const { return Ptr; } @@ -1052,16 +1052,15 @@ private: SExpr* Ptr; }; - /// 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; } - 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) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Store; } + SExpr *destination() { return Dest; } // Address to store to const SExpr *destination() const { return Dest; } @@ -1088,16 +1087,15 @@ private: SExpr* Source; }; - /// 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; } - ArrayIndex(SExpr *A, SExpr *N) : SExpr(COP_ArrayIndex), Array(A), Index(N) {} ArrayIndex(const ArrayIndex &E, SExpr *A, SExpr *N) - : SExpr(E), Array(A), Index(N) {} + : SExpr(E), Array(A), Index(N) {} + + static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayIndex; } SExpr *array() { return Array; } const SExpr *array() const { return Array; } @@ -1125,17 +1123,16 @@ private: 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. class ArrayAdd : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; } - ArrayAdd(SExpr *A, SExpr *N) : SExpr(COP_ArrayAdd), Array(A), Index(N) {} ArrayAdd(const ArrayAdd &E, SExpr *A, SExpr *N) - : SExpr(E), Array(A), Index(N) {} + : SExpr(E), Array(A), Index(N) {} + + static bool classof(const SExpr *E) { return E->opcode() == COP_ArrayAdd; } SExpr *array() { return Array; } const SExpr *array() const { return Array; } @@ -1163,18 +1160,18 @@ private: SExpr* Index; }; - /// 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; } - UnaryOp(TIL_UnaryOpcode Op, SExpr *E) : SExpr(COP_UnaryOp), Expr0(E) { Flags = Op; } + UnaryOp(const UnaryOp &U, SExpr *E) : SExpr(U), Expr0(E) { Flags = U.Flags; } + static bool classof(const SExpr *E) { return E->opcode() == COP_UnaryOp; } + TIL_UnaryOpcode unaryOpcode() const { return static_cast<TIL_UnaryOpcode>(Flags); } @@ -1201,22 +1198,22 @@ private: SExpr* Expr0; }; - /// 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; } - BinaryOp(TIL_BinaryOpcode Op, SExpr *E0, SExpr *E1) : SExpr(COP_BinaryOp), Expr0(E0), Expr1(E1) { Flags = Op; } + BinaryOp(const BinaryOp &B, SExpr *E0, SExpr *E1) : SExpr(B), Expr0(E0), Expr1(E1) { Flags = B.Flags; } + static bool classof(const SExpr *E) { return E->opcode() == COP_BinaryOp; } + TIL_BinaryOpcode binaryOpcode() const { return static_cast<TIL_BinaryOpcode>(Flags); } @@ -1251,17 +1248,16 @@ private: SExpr* Expr1; }; - /// 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; } - Cast(TIL_CastOpcode Op, SExpr *E) : SExpr(COP_Cast), Expr0(E) { Flags = Op; } Cast(const Cast &C, SExpr *E) : SExpr(C), Expr0(E) { Flags = C.Flags; } + static bool classof(const SExpr *E) { return E->opcode() == COP_Cast; } + TIL_CastOpcode castOpcode() const { return static_cast<TIL_CastOpcode>(Flags); } @@ -1288,16 +1284,14 @@ private: 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: - typedef SimpleArray<SExpr *> ValArray; + using ValArray = SimpleArray<SExpr *>; // In minimal SSA form, all Phi nodes are MultiVal. // During conversion to SSA, incomplete Phi nodes may be introduced, which @@ -1308,14 +1302,11 @@ public: PH_Incomplete // Phi node is incomplete }; - 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) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Phi; } const ValArray &values() const { return Values; } ValArray &values() { return Values; } @@ -1324,19 +1315,18 @@ public: 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; } + const ValueDecl *clangDecl() const { return Cvdecl; } /// Set the clang variable associated with this Phi node. - void setClangDecl(const clang::ValueDecl *Cvd) { Cvdecl = Cvd; } + void setClangDecl(const 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> Nvs(Vs, Values.size()); - for (auto *Val : Values) { + for (const auto *Val : Values) Nvs.push_back( Vs.traverse(Val, Vs.subExprCtx(Ctx)) ); - } return Vs.reducePhi(*this, Nvs); } @@ -1348,31 +1338,28 @@ public: private: ValArray Values; - const clang::ValueDecl* Cvdecl; + const ValueDecl* Cvdecl = nullptr; }; - /// Base class for basic block terminators: Branch, Goto, and Return. class Terminator : public SExpr { +protected: + Terminator(TIL_Opcode Op) : SExpr(Op) {} + Terminator(const SExpr &E) : SExpr(E) {} + 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(); - ArrayRef<BasicBlock*> successors() const { + ArrayRef<BasicBlock *> successors() const { return const_cast<Terminator*>(this)->successors(); } }; - /// 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 @@ -1380,13 +1367,13 @@ public: /// 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) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Goto; } + const BasicBlock *targetBlock() const { return TargetBlock; } BasicBlock *targetBlock() { return TargetBlock; } @@ -1394,9 +1381,7 @@ public: unsigned index() const { return Index; } /// Return the list of basic blocks that this terminator can branch to. - ArrayRef<BasicBlock*> successors() { - return TargetBlock; - } + ArrayRef<BasicBlock *> successors() { return TargetBlock; } template <class V> typename V::R_SExpr traverse(V &Vs, typename V::R_Ctx Ctx) { @@ -1415,25 +1400,25 @@ private: 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; } + static bool classof(const SExpr *E) { return E->opcode() == COP_Branch; } + const SExpr *condition() const { return Condition; } SExpr *condition() { return Condition; } @@ -1463,24 +1448,21 @@ public: } private: - SExpr* Condition; + 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) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_Return; } + /// Return an empty list. - ArrayRef<BasicBlock*> successors() { - return None; - } + ArrayRef<BasicBlock *> successors() { return None; } SExpr *returnValue() { return Retval; } const SExpr *returnValue() const { return Retval; } @@ -1500,7 +1482,6 @@ private: SExpr* Retval; }; - inline ArrayRef<BasicBlock*> Terminator::successors() { switch (opcode()) { case COP_Goto: return cast<Goto>(this)->successors(); @@ -1511,7 +1492,6 @@ inline ArrayRef<BasicBlock*> Terminator::successors() { } } - /// 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 @@ -1519,15 +1499,23 @@ inline ArrayRef<BasicBlock*> Terminator::successors() { /// another basic block in the same SCFG. class BasicBlock : public SExpr { public: - typedef SimpleArray<SExpr*> InstrArray; - typedef SimpleArray<BasicBlock*> BlockArray; + using InstrArray = SimpleArray<SExpr *>; + using BlockArray = SimpleArray<BasicBlock *>; // 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) {} + int NodeID = 0; + + // Includes this node, so must be > 1. + int SizeOfSubTree = 0; + + // Pointer to parent. + BasicBlock *Parent = nullptr; + + TopologyNode() = default; bool isParentOf(const TopologyNode& OtherNode) { return OtherNode.NodeID > NodeID && @@ -1538,22 +1526,17 @@ public: 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) - : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0), - Visited(0), TermInstr(nullptr) {} + : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false) {} BasicBlock(BasicBlock &B, MemRegionRef A, InstrArray &&As, InstrArray &&Is, Terminator *T) - : SExpr(COP_BasicBlock), Arena(A), CFGPtr(nullptr), BlockID(0),Visited(0), + : SExpr(COP_BasicBlock), Arena(A), BlockID(0), Visited(false), Args(std::move(As)), Instrs(std::move(Is)), TermInstr(T) {} + static bool classof(const SExpr *E) { return E->opcode() == COP_BasicBlock; } + /// Returns the block ID. Every block has a unique ID in the CFG. int blockID() const { return BlockID; } @@ -1600,11 +1583,13 @@ public: Args.reserveCheck(1, Arena); Args.push_back(V); } + /// Add a new instruction. void addInstruction(SExpr *V) { Instrs.reserveCheck(1, Arena); Instrs.push_back(V); } + // Add a new predecessor, and return the phi-node index for it. // Will add an argument to all phi-nodes, initialized to nullptr. unsigned addPredecessor(BasicBlock *Pred); @@ -1632,11 +1617,11 @@ public: // Entering the basic block should do any scope initialization. Vs.enterBasicBlock(*this); - for (auto *E : Args) { + for (const auto *E : Args) { auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx)); Nas.push_back(Ne); } - for (auto *E : Instrs) { + for (const auto *E : Instrs) { auto Ne = Vs.traverse(E, Vs.subExprCtx(Ctx)); Nis.push_back(Ne); } @@ -1657,43 +1642,56 @@ public: private: friend class SCFG; - int renumberInstrs(int id); // assign unique ids to all instructions - int topologicalSort(SimpleArray<BasicBlock*>& Blocks, int ID); - int topologicalFinalSort(SimpleArray<BasicBlock*>& Blocks, int ID); + // assign unique ids to all instructions + int renumberInstrs(int id); + + int topologicalSort(SimpleArray<BasicBlock *> &Blocks, int ID); + int topologicalFinalSort(SimpleArray<BasicBlock *> &Blocks, int ID); void computeDominator(); void computePostDominator(); -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 -}; + // The arena used to allocate this block. + MemRegionRef Arena; + + // The CFG that contains this block. + SCFG *CFGPtr = nullptr; + + // Unique ID for this BB in the containing CFG. IDs are in topological order. + int BlockID : 31; + // Bit to determine if a block has been visited during a traversal. + bool Visited : 1; + + // Predecessor blocks in the CFG. + BlockArray Predecessors; + + // Phi nodes. One argument per predecessor. + InstrArray Args; + + // Instructions. + InstrArray Instrs; + + // Terminating instruction. + Terminator *TermInstr = nullptr; + + // The dominator tree. + TopologyNode DominatorNode; + + // The post-dominator tree. + TopologyNode PostDominatorNode; +}; /// 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; - typedef BlockArray::iterator iterator; - typedef BlockArray::const_iterator const_iterator; - - static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; } + using BlockArray = SimpleArray<BasicBlock *>; + using iterator = BlockArray::iterator; + using const_iterator = BlockArray::const_iterator; SCFG(MemRegionRef A, unsigned Nblocks) - : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks), - Entry(nullptr), Exit(nullptr), NumInstructions(0), Normal(false) { + : SExpr(COP_SCFG), Arena(A), Blocks(A, Nblocks) { Entry = new (A) BasicBlock(A); Exit = new (A) BasicBlock(A); auto *V = new (A) Phi(); @@ -1702,12 +1700,14 @@ public: 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), NumInstructions(0), Normal(false) { + : SExpr(COP_SCFG), Arena(Cfg.Arena), Blocks(std::move(Ba)) { // TODO: set entry and exit! } + static bool classof(const SExpr *E) { return E->opcode() == COP_SCFG; } + /// Return true if this CFG is valid. bool valid() const { return Entry && Exit && Blocks.size() > 0; } @@ -1756,7 +1756,7 @@ public: Vs.enterCFG(*this); typename V::template Container<BasicBlock *> Bbs(Vs, Blocks.size()); - for (auto *B : Blocks) { + for (const auto *B : Blocks) { Bbs.push_back( B->traverse(Vs, Vs.subExprCtx(Ctx)) ); } Vs.exitCFG(*this); @@ -1770,27 +1770,25 @@ public: } private: - void renumberInstrs(); // assign unique ids to all instructions + // assign unique ids to all instructions + void renumberInstrs(); -private: MemRegionRef Arena; - BlockArray Blocks; - BasicBlock *Entry; - BasicBlock *Exit; - unsigned NumInstructions; - bool Normal; + BlockArray Blocks; + BasicBlock *Entry = nullptr; + BasicBlock *Exit = nullptr; + unsigned NumInstructions = 0; + bool Normal = false; }; - - /// 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; } + Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) {} + Identifier(const Identifier &) = default; - Identifier(StringRef Id): SExpr(COP_Identifier), Name(Id) { } - Identifier(const Identifier& I) : SExpr(I), Name(I.Name) { } + static bool classof(const SExpr *E) { return E->opcode() == COP_Identifier; } StringRef name() const { return Name; } @@ -1808,19 +1806,16 @@ private: StringRef Name; }; - /// 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; } - IfThenElse(SExpr *C, SExpr *T, SExpr *E) - : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) - { } + : SExpr(COP_IfThenElse), Condition(C), ThenExpr(T), ElseExpr(E) {} IfThenElse(const IfThenElse &I, SExpr *C, SExpr *T, SExpr *E) - : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) - { } + : SExpr(I), Condition(C), ThenExpr(T), ElseExpr(E) {} + + static bool classof(const SExpr *E) { return E->opcode() == COP_IfThenElse; } SExpr *condition() { return Condition; } // Address to store to const SExpr *condition() const { return Condition; } @@ -1856,20 +1851,20 @@ private: 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. class Let : public SExpr { public: - static bool classof(const SExpr *E) { return E->opcode() == COP_Let; } - Let(Variable *Vd, SExpr *Bd) : SExpr(COP_Let), VarDecl(Vd), Body(Bd) { Vd->setKind(Variable::VK_Let); } + Let(const Let &L, Variable *Vd, SExpr *Bd) : SExpr(L), VarDecl(Vd), Body(Bd) { Vd->setKind(Variable::VK_Let); } + static bool classof(const SExpr *E) { return E->opcode() == COP_Let; } + Variable *variableDecl() { return VarDecl; } const Variable *variableDecl() const { return VarDecl; } @@ -1904,15 +1899,13 @@ private: SExpr* Body; }; - - const SExpr *getCanonicalVal(const SExpr *E); SExpr* simplifyToCanonicalVal(SExpr *E); void simplifyIncompleteArg(til::Phi *Ph); +} // namespace til +} // namespace threadSafety -} // end namespace til -} // end namespace threadSafety -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTIL_H diff --git a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h index 705fe910d0923..49031010a75b6 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyTraverse.h @@ -1,4 +1,4 @@ -//===- ThreadSafetyTraverse.h ----------------------------------*- C++ --*-===// +//===- ThreadSafetyTraverse.h -----------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,7 +17,13 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H -#include "ThreadSafetyTIL.h" +#include "clang/AST/Decl.h" +#include "clang/Analysis/Analyses/ThreadSafetyTIL.h" +#include "clang/Analysis/Analyses/ThreadSafetyUtil.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include <cstdint> #include <ostream> namespace clang { @@ -26,7 +32,7 @@ namespace til { // Defines an interface used to traverse SExprs. Traversals have been made as // generic as possible, and are intended to handle any kind of pass over the -// AST, e.g. visiters, copying, non-destructive rewriting, destructive +// AST, e.g. visitors, copying, non-destructive rewriting, destructive // (in-place) rewriting, hashing, typing, etc. // // Traversals implement the functional notion of a "fold" operation on SExprs. @@ -92,21 +98,27 @@ public: #undef TIL_OPCODE_DEF }; - // Base class for simple reducers that don't much care about the context. class SimpleReducerBase { public: enum TraversalKind { - TRV_Normal, // ordinary subexpressions - TRV_Decl, // declarations (e.g. function bodies) - TRV_Lazy, // expressions that require lazy evaluation - TRV_Type // type expressions + // Ordinary subexpressions. + TRV_Normal, + + // Declarations (e.g. function bodies). + TRV_Decl, + + // Expressions that require lazy evaluation. + TRV_Lazy, + + // Type expressions. + TRV_Type }; // R_Ctx defines a "context" for the traversal, which encodes information // about where a term appears. This can be used to encoding the // "current continuation" for CPS transforms, or other information. - typedef TraversalKind R_Ctx; + using R_Ctx = TraversalKind; // Create context for an ordinary subexpression. R_Ctx subExprCtx(R_Ctx Ctx) { return TRV_Normal; } @@ -123,14 +135,13 @@ public: R_Ctx typeCtx(R_Ctx Ctx) { return TRV_Type; } }; - // Base class for traversals that rewrite an SExpr to another SExpr. class CopyReducerBase : public SimpleReducerBase { public: // R_SExpr is the result type for a traversal. // A copy or non-destructive rewrite returns a newly allocated term. - typedef SExpr *R_SExpr; - typedef BasicBlock *R_BasicBlock; + using R_SExpr = SExpr *; + using R_BasicBlock = BasicBlock *; // Container is a minimal interface used to store results when traversing // SExprs of variable arity, such as Phi, Goto, and SCFG. @@ -151,32 +162,31 @@ protected: MemRegionRef Arena; }; - // Base class for visit traversals. class VisitReducerBase : public SimpleReducerBase { public: // A visitor returns a bool, representing success or failure. - typedef bool R_SExpr; - typedef bool R_BasicBlock; + using R_SExpr = bool; + using R_BasicBlock = bool; // A visitor "container" is a single bool, which accumulates success. template <class T> class Container { public: - Container(VisitReducerBase &S, unsigned N) : Success(true) {} - void push_back(bool E) { Success = Success && E; } + bool Success = true; - bool Success; + Container(VisitReducerBase &S, unsigned N) {} + + void push_back(bool E) { Success = Success && E; } }; }; - // Implements a traversal that visits each subexpression, and returns either // true or false. template <class Self> class VisitReducer : public Traversal<Self, VisitReducerBase>, public VisitReducerBase { public: - VisitReducer() {} + VisitReducer() = default; public: R_SExpr reduceNull() { return true; } @@ -191,54 +201,70 @@ public: R_SExpr reduceFunction(Function &Orig, Variable *Nvd, R_SExpr E0) { return Nvd && E0; } + R_SExpr reduceSFunction(SFunction &Orig, Variable *Nvd, R_SExpr E0) { return Nvd && E0; } + R_SExpr reduceCode(Code &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceField(Field &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceApply(Apply &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceSApply(SApply &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceProject(Project &Orig, R_SExpr E0) { return E0; } R_SExpr reduceCall(Call &Orig, R_SExpr E0) { return E0; } R_SExpr reduceAlloc(Alloc &Orig, R_SExpr E0) { return E0; } R_SExpr reduceLoad(Load &Orig, R_SExpr E0) { return E0; } R_SExpr reduceStore(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceArrayIndex(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceArrayAdd(Store &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceUnaryOp(UnaryOp &Orig, R_SExpr E0) { return E0; } + R_SExpr reduceBinaryOp(BinaryOp &Orig, R_SExpr E0, R_SExpr E1) { return E0 && E1; } + R_SExpr reduceCast(Cast &Orig, R_SExpr E0) { return E0; } R_SExpr reduceSCFG(SCFG &Orig, Container<BasicBlock *> Bbs) { return Bbs.Success; } + 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) { return As.Success; } + R_SExpr reduceGoto(Goto &Orig, BasicBlock *B) { return true; } + R_SExpr reduceBranch(Branch &O, R_SExpr C, BasicBlock *B0, BasicBlock *B1) { return C; } + R_SExpr reduceReturn(Return &O, R_SExpr E) { return E; } @@ -246,9 +272,11 @@ public: R_SExpr reduceIdentifier(Identifier &Orig) { return true; } + R_SExpr reduceIfThenElse(IfThenElse &Orig, R_SExpr C, R_SExpr T, R_SExpr E) { return C && T && E; } + R_SExpr reduceLet(Let &Orig, Variable *Nvd, R_SExpr B) { return Nvd && B; } @@ -260,7 +288,7 @@ public: void enterBasicBlock(BasicBlock &BB) {} void exitBasicBlock(BasicBlock &BB) {} - Variable *reduceVariableRef (Variable *Ovd) { return Ovd; } + Variable *reduceVariableRef(Variable *Ovd) { return Ovd; } BasicBlock *reduceBasicBlockRef(BasicBlock *Obb) { return Obb; } public: @@ -278,7 +306,6 @@ private: bool Success; }; - // Basic class for comparison operations over expressions. template <typename Self> class Comparator { @@ -298,19 +325,18 @@ public: } }; - class EqualsComparator : public Comparator<EqualsComparator> { 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; + using CType = bool; 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 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) { @@ -320,10 +346,10 @@ public: } // TODO -- handle alpha-renaming of variables - void enterScope(const Variable* V1, const Variable* V2) { } - void leaveScope() { } + void enterScope(const Variable *V1, const Variable *V2) {} + void leaveScope() {} - bool compareVariableRefs(const Variable* V1, const Variable* V2) { + bool compareVariableRefs(const Variable *V1, const Variable *V2) { return V1 == V2; } @@ -333,23 +359,21 @@ public: } }; - - 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; + using CType = bool; 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 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) { + bool compare(const SExpr *E1, const SExpr *E2) { // Wildcards match anything. if (E1->opcode() == COP_Wildcard || E2->opcode() == COP_Wildcard) return true; @@ -360,8 +384,8 @@ public: } // TODO -- handle alpha-renaming of variables - void enterScope(const Variable* V1, const Variable* V2) { } - void leaveScope() { } + void enterScope(const Variable* V1, const Variable* V2) {} + void leaveScope() {} bool compareVariableRefs(const Variable* V1, const Variable* V2) { return V1 == V2; @@ -373,8 +397,6 @@ public: } }; - - // inline std::ostream& operator<<(std::ostream& SS, StringRef R) { // return SS.write(R.data(), R.size()); // } @@ -383,14 +405,18 @@ public: 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. + // Print out additional information. + bool Verbose; + + // Omit redundant decls. + bool Cleanup; + + // Print exprs in C-like syntax. + bool CStyle; public: PrettyPrinter(bool V = false, bool C = true, bool CS = true) - : Verbose(V), Cleanup(C), CStyle(CS) - {} + : Verbose(V), Cleanup(C), CStyle(CS) {} static void print(const SExpr *E, StreamType &SS) { Self printer; @@ -470,7 +496,6 @@ protected: } } - void printSExpr(const SExpr *E, StreamType &SS, unsigned P, bool Sub=true) { if (!E) { self()->printNull(SS); @@ -531,18 +556,16 @@ protected: else { ValueType VT = E->valueType(); switch (VT.Base) { - case ValueType::BT_Void: { + case ValueType::BT_Void: SS << "void"; return; - } - case ValueType::BT_Bool: { + case ValueType::BT_Bool: if (E->as<bool>().value()) SS << "true"; else SS << "false"; return; - } - case ValueType::BT_Int: { + case ValueType::BT_Int: switch (VT.Size) { case ValueType::ST_8: if (VT.Signed) @@ -572,8 +595,7 @@ protected: break; } break; - } - case ValueType::BT_Float: { + case ValueType::BT_Float: switch (VT.Size) { case ValueType::ST_32: printLiteralT(&E->as<float>(), SS); @@ -585,22 +607,18 @@ protected: break; } break; - } - case ValueType::BT_String: { + case ValueType::BT_String: SS << "\""; printLiteralT(&E->as<StringRef>(), SS); SS << "\""; return; - } - case ValueType::BT_Pointer: { + case ValueType::BT_Pointer: SS << "#ptr"; return; - } - case ValueType::BT_ValueRef: { + case ValueType::BT_ValueRef: SS << "#vref"; return; } - } } SS << "#lit"; } @@ -688,8 +706,8 @@ protected: 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 (const auto *SAP = dyn_cast<SApply>(E->record())) { + if (const auto *V = dyn_cast<Variable>(SAP->sfun())) { if (!SAP->isDelegation() && V->kind() == Variable::VK_SFun) { SS << E->slotName(); return; @@ -704,12 +722,10 @@ protected: } } self()->printSExpr(E->record(), SS, Prec_Postfix); - if (CStyle && E->isArrow()) { + if (CStyle && E->isArrow()) SS << "->"; - } - else { + else SS << "."; - } SS << E->slotName(); } @@ -780,18 +796,16 @@ protected: void printSCFG(const SCFG *E, StreamType &SS) { SS << "CFG {\n"; - for (auto BBI : *E) { + for (const auto *BBI : *E) printBasicBlock(BBI, SS); - } SS << "}"; newline(SS); } - void printBBInstr(const SExpr *E, StreamType &SS) { bool Sub = false; if (E->opcode() == COP_Variable) { - auto *V = cast<Variable>(E); + const auto *V = cast<Variable>(E); SS << "let " << V->name() << V->id() << " = "; E = V->definition(); Sub = true; @@ -810,10 +824,10 @@ protected: SS << " BB_" << E->parent()->blockID(); newline(SS); - for (auto *A : E->arguments()) + for (const auto *A : E->arguments()) printBBInstr(A, SS); - for (auto *I : E->instructions()) + for (const auto *I : E->instructions()) printBBInstr(I, SS); const SExpr *T = E->terminator(); @@ -831,7 +845,7 @@ protected: self()->printSExpr(E->values()[0], SS, Prec_MAX); else { unsigned i = 0; - for (auto V : E->values()) { + for (const auto *V : E->values()) { if (i++ > 0) SS << ", "; self()->printSExpr(V, SS, Prec_MAX); @@ -890,13 +904,10 @@ protected: } }; +class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> {}; -class StdPrinter : public PrettyPrinter<StdPrinter, std::ostream> { }; - - - -} // end namespace til -} // end namespace threadSafety -} // end namespace clang +} // namespace til +} // namespace threadSafety +} // namespace clang -#endif // LLVM_CLANG_THREAD_SAFETY_TRAVERSE_H +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYTRAVERSE_H diff --git a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h index cb80ce5da8d2f..16583939d5423 100644 --- a/include/clang/Analysis/Analyses/ThreadSafetyUtil.h +++ b/include/clang/Analysis/Analyses/ThreadSafetyUtil.h @@ -1,4 +1,4 @@ -//===- ThreadSafetyUtil.h --------------------------------------*- C++ --*-===// +//===- ThreadSafetyUtil.h ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,18 +14,23 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H #define LLVM_CLANG_ANALYSIS_ANALYSES_THREADSAFETYUTIL_H -#include "clang/AST/ExprCXX.h" +#include "clang/AST/Decl.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/AlignOf.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Compiler.h" #include <cassert> #include <cstddef> +#include <cstring> +#include <iterator> #include <ostream> -#include <utility> +#include <string> #include <vector> namespace clang { + +class Expr; + namespace threadSafety { namespace til { @@ -41,7 +46,7 @@ private: }; public: - MemRegionRef() : Allocator(nullptr) {} + MemRegionRef() = default; MemRegionRef(llvm::BumpPtrAllocator *A) : Allocator(A) {} void *allocate(size_t Sz) { @@ -55,12 +60,13 @@ public: } private: - llvm::BumpPtrAllocator *Allocator; + llvm::BumpPtrAllocator *Allocator = nullptr; }; -} // end namespace til -} // end namespace threadSafety -} // end namespace clang +} // namespace til +} // namespace threadSafety + +} // namespace clang inline void *operator new(size_t Sz, clang::threadSafety::til::MemRegionRef &R) { @@ -70,10 +76,7 @@ inline void *operator new(size_t Sz, namespace clang { namespace threadSafety { -std::string getSourceLiteralString(const clang::Expr *CE); - -using llvm::StringRef; -using clang::SourceLocation; +std::string getSourceLiteralString(const Expr *CE); namespace til { @@ -81,11 +84,13 @@ namespace til { // suitable for use with bump pointer allocation. template <class T> class SimpleArray { public: - SimpleArray() : Data(nullptr), Size(0), Capacity(0) {} + SimpleArray() = default; SimpleArray(T *Dat, size_t Cp, size_t Sz = 0) : Data(Dat), Size(Sz), Capacity(Cp) {} SimpleArray(MemRegionRef A, size_t Cp) - : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Size(0), Capacity(Cp) {} + : Data(Cp == 0 ? nullptr : A.allocateT<T>(Cp)), Capacity(Cp) {} + SimpleArray(const SimpleArray<T> &A) = delete; + SimpleArray(SimpleArray<T> &&A) : Data(A.Data), Size(A.Size), Capacity(A.Capacity) { A.Data = nullptr; @@ -123,10 +128,10 @@ public: reserve(u_max(Size + N, Capacity * 2), A); } - typedef T *iterator; - typedef const T *const_iterator; - typedef std::reverse_iterator<iterator> reverse_iterator; - typedef std::reverse_iterator<const_iterator> const_reverse_iterator; + using iterator = T *; + using const_iterator = const T *; + using reverse_iterator = std::reverse_iterator<iterator>; + using const_reverse_iterator = std::reverse_iterator<const_iterator>; size_t size() const { return Size; } size_t capacity() const { return Capacity; } @@ -135,27 +140,30 @@ public: assert(i < Size && "Array index out of bounds."); return Data[i]; } + const T &operator[](unsigned i) const { 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 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; } reverse_iterator rbegin() { return reverse_iterator(end()); } reverse_iterator rend() { return reverse_iterator(begin()); } @@ -163,6 +171,7 @@ public: const_reverse_iterator rbegin() const { return const_reverse_iterator(end()); } + const_reverse_iterator rend() const { return const_reverse_iterator(begin()); } @@ -198,6 +207,7 @@ public: llvm::iterator_range<reverse_iterator> reverse() { return llvm::make_range(rbegin(), rend()); } + llvm::iterator_range<const_reverse_iterator> reverse() const { return llvm::make_range(rbegin(), rend()); } @@ -209,14 +219,12 @@ private: static const size_t InitialCapacity = 4; - SimpleArray(const SimpleArray<T> &A) = delete; - - T *Data; - size_t Size; - size_t Capacity; + T *Data = nullptr; + size_t Size = 0; + size_t Capacity = 0; }; -} // end namespace til +} // namespace til // A copy on write vector. // The vector can be in one of three states: @@ -228,20 +236,28 @@ template<typename T> class CopyOnWriteVector { class VectorData { public: - VectorData() : NumRefs(1) { } - VectorData(const VectorData &VD) : NumRefs(1), Vect(VD.Vect) { } - - unsigned NumRefs; + unsigned NumRefs = 1; std::vector<T> Vect; - }; - // No copy constructor or copy assignment. Use clone() with move assignment. - CopyOnWriteVector(const CopyOnWriteVector &V) = delete; - void operator=(const CopyOnWriteVector &V) = delete; + VectorData() = default; + VectorData(const VectorData &VD) : Vect(VD.Vect) {} + }; public: - CopyOnWriteVector() : Data(nullptr) {} + CopyOnWriteVector() = default; CopyOnWriteVector(CopyOnWriteVector &&V) : Data(V.Data) { V.Data = nullptr; } + + CopyOnWriteVector &operator=(CopyOnWriteVector &&V) { + destroy(); + Data = V.Data; + V.Data = nullptr; + return *this; + } + + // No copy constructor or copy assignment. Use clone() with move assignment. + CopyOnWriteVector(const CopyOnWriteVector &) = delete; + CopyOnWriteVector &operator=(const CopyOnWriteVector &) = delete; + ~CopyOnWriteVector() { destroy(); } // Returns true if this holds a valid vector. @@ -283,14 +299,7 @@ public: // Create a lazy copy of this vector. CopyOnWriteVector clone() { return CopyOnWriteVector(Data); } - CopyOnWriteVector &operator=(CopyOnWriteVector &&V) { - destroy(); - Data = V.Data; - V.Data = nullptr; - return *this; - } - - typedef typename std::vector<T>::const_iterator const_iterator; + using const_iterator = typename std::vector<T>::const_iterator; const std::vector<T> &elements() const { return Data->Vect; } @@ -336,14 +345,14 @@ private: ++Data->NumRefs; } - VectorData *Data; + VectorData *Data = nullptr; }; inline std::ostream& operator<<(std::ostream& ss, const StringRef str) { return ss.write(str.data(), str.size()); } -} // end namespace threadSafety -} // end namespace clang +} // namespace threadSafety +} // namespace clang #endif // LLVM_CLANG_THREAD_SAFETY_UTIL_H diff --git a/include/clang/Analysis/Analyses/UninitializedValues.h b/include/clang/Analysis/Analyses/UninitializedValues.h index 53ff20c23560c..79d89e0633fd0 100644 --- a/include/clang/Analysis/Analyses/UninitializedValues.h +++ b/include/clang/Analysis/Analyses/UninitializedValues.h @@ -1,4 +1,4 @@ -//= UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-==// +//=- UninitializedValues.h - Finding uses of uninitialized values -*- C++ -*-=// // // The LLVM Compiler Infrastructure // @@ -15,7 +15,7 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H #define LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H -#include "clang/AST/Stmt.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" namespace clang { @@ -24,6 +24,7 @@ class AnalysisDeclContext; class CFG; class DeclContext; class Expr; +class Stmt; class VarDecl; /// A use of a variable, which might be uninitialized. @@ -39,10 +40,10 @@ private: const Expr *User; /// Is this use uninitialized whenever the function is called? - bool UninitAfterCall; + bool UninitAfterCall = false; /// Is this use uninitialized whenever the variable declaration is reached? - bool UninitAfterDecl; + bool UninitAfterDecl = false; /// Does this use always see an uninitialized value? bool AlwaysUninit; @@ -53,8 +54,7 @@ private: public: UninitUse(const Expr *User, bool AlwaysUninit) - : User(User), UninitAfterCall(false), UninitAfterDecl(false), - AlwaysUninit(AlwaysUninit) {} + : User(User), AlwaysUninit(AlwaysUninit) {} void addUninitBranch(Branch B) { UninitBranches.push_back(B); @@ -70,14 +70,18 @@ public: enum Kind { /// The use might be uninitialized. Maybe, + /// The use is uninitialized whenever a certain branch is taken. Sometimes, + /// The use is uninitialized the first time it is reached after we reach /// the variable's declaration. AfterDecl, + /// The use is uninitialized the first time it is reached after the function /// is called. AfterCall, + /// The use is always uninitialized. Always }; @@ -90,7 +94,8 @@ public: !branch_empty() ? Sometimes : Maybe; } - typedef SmallVectorImpl<Branch>::const_iterator branch_iterator; + using branch_iterator = SmallVectorImpl<Branch>::const_iterator; + /// Branches which inevitably result in the variable being used uninitialized. branch_iterator branch_begin() const { return UninitBranches.begin(); } branch_iterator branch_end() const { return UninitBranches.end(); } @@ -99,7 +104,7 @@ public: class UninitVariablesHandler { public: - UninitVariablesHandler() {} + UninitVariablesHandler() = default; virtual ~UninitVariablesHandler(); /// Called when the uninitialized variable is used at the given expression. @@ -122,5 +127,6 @@ void runUninitializedVariablesAnalysis(const DeclContext &dc, const CFG &cfg, UninitVariablesHandler &handler, UninitVariablesAnalysisStats &stats); -} -#endif +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSES_UNINITIALIZEDVALUES_H diff --git a/include/clang/Analysis/AnalysisDeclContext.h b/include/clang/Analysis/AnalysisDeclContext.h index 03ff4a9516da0..8c391b5ee1e5d 100644 --- a/include/clang/Analysis/AnalysisDeclContext.h +++ b/include/clang/Analysis/AnalysisDeclContext.h @@ -1,4 +1,4 @@ -//=== AnalysisDeclContext.h - Analysis context for Path Sens analysis --*- C++ -*-// +// AnalysisDeclContext.h - Analysis context for Path Sens analysis -*- C++ -*-// // // The LLVM Compiler Infrastructure // @@ -15,37 +15,42 @@ #ifndef LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H #define LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H -#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/Analysis/BodyFarm.h" #include "clang/Analysis/CFG.h" #include "clang/Analysis/CodeInjector.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include "llvm/Support/Allocator.h" +#include <functional> #include <memory> namespace clang { -class Stmt; +class AnalysisDeclContextManager; +class ASTContext; +class BlockDecl; +class BlockInvocationContext; class CFGReverseBlockReachabilityAnalysis; class CFGStmtMap; -class LiveVariables; -class ManagedAnalysis; +class ImplicitParamDecl; +class LocationContext; +class LocationContextManager; class ParentMap; class PseudoConstantAnalysis; -class LocationContextManager; class StackFrameContext; -class BlockInvocationContext; -class AnalysisDeclContextManager; -class LocationContext; - -namespace idx { class TranslationUnit; } +class Stmt; +class VarDecl; /// The base class of a hierarchy of objects representing analyses tied /// to AnalysisDeclContext. class ManagedAnalysis { protected: - ManagedAnalysis() {} + ManagedAnalysis() = default; + public: virtual ~ManagedAnalysis(); @@ -61,7 +66,6 @@ public: // which creates the analysis object given an AnalysisDeclContext. }; - /// AnalysisDeclContext contains the context data for the function or method /// under analysis. class AnalysisDeclContext { @@ -75,18 +79,19 @@ class AnalysisDeclContext { std::unique_ptr<CFGStmtMap> cfgStmtMap; CFG::BuildOptions cfgBuildOptions; - CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs; + CFG::BuildOptions::ForcedBlkExprs *forcedBlkExprs = nullptr; - bool builtCFG, builtCompleteCFG; + bool builtCFG = false; + bool builtCompleteCFG = false; std::unique_ptr<ParentMap> PM; std::unique_ptr<PseudoConstantAnalysis> PCA; std::unique_ptr<CFGReverseBlockReachabilityAnalysis> CFA; llvm::BumpPtrAllocator A; - llvm::DenseMap<const BlockDecl*,void*> *ReferencedBlockVars; + llvm::DenseMap<const BlockDecl *,void *> *ReferencedBlockVars = nullptr; - void *ManagedAnalyses; + void *ManagedAnalyses = nullptr; public: AnalysisDeclContext(AnalysisDeclContextManager *Mgr, @@ -130,22 +135,22 @@ public: void registerForcedBlockExpression(const Stmt *stmt); const CFGBlock *getBlockForRegisteredExpression(const Stmt *stmt); - /// \brief Get the body of the Declaration. + /// Get the body of the Declaration. Stmt *getBody() const; - /// \brief Get the body of the Declaration. + /// Get the body of the Declaration. /// \param[out] IsAutosynthesized Specifies if the body is auto-generated /// by the BodyFarm. Stmt *getBody(bool &IsAutosynthesized) const; - /// \brief Checks if the body of the Decl is generated by the BodyFarm. + /// Checks if the body of the Decl is generated by the BodyFarm. /// /// Note, the lookup is not free. We are going to call getBody behind /// the scenes. /// \sa getBody bool isBodyAutosynthesized() const; - /// \brief Checks if the body of the Decl is generated by the BodyFarm from a + /// 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 @@ -164,7 +169,7 @@ public: void dumpCFG(bool ShowColors); - /// \brief Returns true if we have built a CFG for this analysis context. + /// Returns true if we have built a CFG for this analysis context. /// Note that this doesn't correspond to whether or not a valid CFG exists, it /// corresponds to whether we *attempted* to build one. bool isCFGBuilt() const { return builtCFG; } @@ -172,7 +177,7 @@ public: ParentMap &getParentMap(); PseudoConstantAnalysis *getPseudoConstantAnalysis(); - typedef const VarDecl * const * referenced_decls_iterator; + using referenced_decls_iterator = const VarDecl * const *; llvm::iterator_range<referenced_decls_iterator> getReferencedBlockVars(const BlockDecl *BD); @@ -200,12 +205,13 @@ public: if (!data) { data = T::create(*this); } - return static_cast<T*>(data); + return static_cast<T *>(data); } /// Returns true if the root namespace of the given declaration is the 'std' /// C++ namespace. static bool isInStdNamespace(const Decl *D); + private: ManagedAnalysis *&getAnalysisImpl(const void* tag); @@ -228,7 +234,7 @@ private: protected: LocationContext(ContextKind k, AnalysisDeclContext *ctx, const LocationContext *parent) - : Kind(k), Ctx(ctx), Parent(parent) {} + : Kind(k), Ctx(ctx), Parent(parent) {} public: virtual ~LocationContext(); @@ -258,14 +264,18 @@ public: return Ctx->getSelfDecl(); } - const StackFrameContext *getCurrentStackFrame() const; + const StackFrameContext *getStackFrame() const; /// Return true if the current LocationContext has no caller context. virtual bool inTopFrame() const; virtual void Profile(llvm::FoldingSetNodeID &ID) = 0; - void dumpStack(raw_ostream &OS, StringRef Indent = "") const; + void dumpStack( + raw_ostream &OS, StringRef Indent = {}, const char *NL = "\n", + const char *Sep = "", + std::function<void(const LocationContext *)> printMoreInfoPerContext = + [](const LocationContext *) {}) const; void dumpStack() const; public: @@ -277,6 +287,8 @@ public: }; class StackFrameContext : public LocationContext { + friend class LocationContextManager; + // The callsite where this stack frame is established. const Stmt *CallSite; @@ -286,15 +298,14 @@ class StackFrameContext : public LocationContext { // The index of the callsite in the CFGBlock. unsigned Index; - friend class LocationContextManager; StackFrameContext(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s, const CFGBlock *blk, unsigned idx) - : LocationContext(StackFrame, ctx, parent), CallSite(s), - Block(blk), Index(idx) {} + : LocationContext(StackFrame, ctx, parent), CallSite(s), + Block(blk), Index(idx) {} public: - ~StackFrameContext() override {} + ~StackFrameContext() override = default; const Stmt *getCallSite() const { return CallSite; } @@ -321,15 +332,16 @@ public: }; class ScopeContext : public LocationContext { + friend class LocationContextManager; + const Stmt *Enter; - friend class LocationContextManager; ScopeContext(AnalysisDeclContext *ctx, const LocationContext *parent, const Stmt *s) - : LocationContext(Scope, ctx, parent), Enter(s) {} + : LocationContext(Scope, ctx, parent), Enter(s) {} public: - ~ScopeContext() override {} + ~ScopeContext() override = default; void Profile(llvm::FoldingSetNodeID &ID) override; @@ -344,20 +356,20 @@ public: }; class BlockInvocationContext : public LocationContext { + friend class LocationContextManager; + const BlockDecl *BD; // FIXME: Come up with a more type-safe way to model context-sensitivity. const void *ContextData; - friend class LocationContextManager; - BlockInvocationContext(AnalysisDeclContext *ctx, const LocationContext *parent, const BlockDecl *bd, const void *contextData) - : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {} + : LocationContext(Block, ctx, parent), BD(bd), ContextData(contextData) {} public: - ~BlockInvocationContext() override {} + ~BlockInvocationContext() override = default; const BlockDecl *getBlockDecl() const { return BD; } @@ -379,6 +391,7 @@ public: class LocationContextManager { llvm::FoldingSet<LocationContext> Contexts; + public: ~LocationContextManager(); @@ -407,8 +420,8 @@ private: }; class AnalysisDeclContextManager { - typedef llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>> - ContextMap; + using ContextMap = + llvm::DenseMap<const Decl *, std::unique_ptr<AnalysisDeclContext>>; ContextMap Contexts; LocationContextManager LocContexts; @@ -431,10 +444,14 @@ public: bool addImplicitDtors = false, bool addInitializers = false, bool addTemporaryDtors = false, - bool addLifetime = false, bool addLoopExit = false, + bool addLifetime = false, + bool addLoopExit = false, + bool addScopes = false, bool synthesizeBodies = false, bool addStaticInitBranches = false, bool addCXXNewAllocator = true, + bool addRichCXXConstructors = true, + bool markElidedCXXConstructors = true, CodeInjector *injector = nullptr); AnalysisDeclContext *getContext(const Decl *D); @@ -488,5 +505,6 @@ private: } }; -} // end clang namespace -#endif +} // namespace clang + +#endif // LLVM_CLANG_ANALYSIS_ANALYSISDECLCONTEXT_H diff --git a/include/clang/Analysis/CFG.h b/include/clang/Analysis/CFG.h index cfedb2aa8ed5d..f25789822d162 100644 --- a/include/clang/Analysis/CFG.h +++ b/include/clang/Analysis/CFG.h @@ -15,8 +15,9 @@ #ifndef LLVM_CLANG_ANALYSIS_CFG_H #define LLVM_CLANG_ANALYSIS_CFG_H -#include "clang/AST/Stmt.h" +#include "clang/AST/ExprCXX.h" #include "clang/Analysis/Support/BumpVector.h" +#include "clang/Analysis/ConstructionContext.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/GraphTraits.h" @@ -55,11 +56,18 @@ class CFGElement { public: enum Kind { // main kind - Statement, Initializer, + ScopeBegin, + ScopeEnd, NewAllocator, LifetimeEnds, LoopExit, + // stmt kind + Statement, + Constructor, + CXXRecordTypedCall, + STMT_BEGIN = Statement, + STMT_END = CXXRecordTypedCall, // dtor kind AutomaticObjectDtor, DeleteDtor, @@ -84,7 +92,7 @@ protected: CFGElement() = default; public: - /// \brief Convert to the specified CFGElement type, asserting that this + /// Convert to the specified CFGElement type, asserting that this /// CFGElement is of the desired type. template<typename T> T castAs() const { @@ -95,7 +103,7 @@ public: return t; } - /// \brief Convert to the specified CFGElement type, returning None if this + /// Convert to the specified CFGElement type, returning None if this /// CFGElement is not of the desired type. template<typename T> Optional<T> getAs() const { @@ -117,7 +125,9 @@ public: class CFGStmt : public CFGElement { public: - CFGStmt(Stmt *S) : CFGElement(Statement, S) {} + explicit CFGStmt(Stmt *S, Kind K = Statement) : CFGElement(K, S) { + assert(isKind(*this)); + } const Stmt *getStmt() const { return static_cast<const Stmt *>(Data1.getPointer()); @@ -126,10 +136,77 @@ public: private: friend class CFGElement; + static bool isKind(const CFGElement &E) { + return E.getKind() >= STMT_BEGIN && E.getKind() <= STMT_END; + } + +protected: CFGStmt() = default; +}; + +/// CFGConstructor - Represents C++ constructor call. Maintains information +/// necessary to figure out what memory is being initialized by the +/// constructor expression. For now this is only used by the analyzer's CFG. +class CFGConstructor : public CFGStmt { +public: + explicit CFGConstructor(CXXConstructExpr *CE, const ConstructionContext *C) + : CFGStmt(CE, Constructor) { + assert(C); + Data2.setPointer(const_cast<ConstructionContext *>(C)); + } + + const ConstructionContext *getConstructionContext() const { + return static_cast<ConstructionContext *>(Data2.getPointer()); + } + +private: + friend class CFGElement; + + CFGConstructor() = default; + + static bool isKind(const CFGElement &E) { + return E.getKind() == Constructor; + } +}; + +/// CFGCXXRecordTypedCall - Represents a function call that returns a C++ object +/// by value. This, like constructor, requires a construction context in order +/// to understand the storage of the returned object . In C such tracking is not +/// necessary because no additional effort is required for destroying the object +/// or modeling copy elision. Like CFGConstructor, this element is for now only +/// used by the analyzer's CFG. +class CFGCXXRecordTypedCall : public CFGStmt { +public: + /// Returns true when call expression \p CE needs to be represented + /// by CFGCXXRecordTypedCall, as opposed to a regular CFGStmt. + static bool isCXXRecordTypedCall(CallExpr *CE, const ASTContext &ACtx) { + return CE->getCallReturnType(ACtx).getCanonicalType()->getAsCXXRecordDecl(); + } + + explicit CFGCXXRecordTypedCall(CallExpr *CE, const ConstructionContext *C) + : CFGStmt(CE, CXXRecordTypedCall) { + // FIXME: This is not protected against squeezing a non-record-typed-call + // into the constructor. An assertion would require passing an ASTContext + // which would mean paying for something we don't use. + assert(C && (isa<TemporaryObjectConstructionContext>(C) || + // These are possible in C++17 due to mandatory copy elision. + isa<ReturnedValueConstructionContext>(C) || + isa<VariableConstructionContext>(C) || + isa<ConstructorInitializerConstructionContext>(C))); + Data2.setPointer(const_cast<ConstructionContext *>(C)); + } + + const ConstructionContext *getConstructionContext() const { + return static_cast<ConstructionContext *>(Data2.getPointer()); + } + +private: + friend class CFGElement; + + CFGCXXRecordTypedCall() = default; static bool isKind(const CFGElement &E) { - return E.getKind() == Statement; + return E.getKind() == CXXRecordTypedCall; } }; @@ -137,7 +214,7 @@ private: /// constructor's initialization list. class CFGInitializer : public CFGElement { public: - CFGInitializer(CXXCtorInitializer *initializer) + explicit CFGInitializer(CXXCtorInitializer *initializer) : CFGElement(Initializer, initializer) {} CXXCtorInitializer* getInitializer() const { @@ -223,6 +300,55 @@ private: } }; +/// Represents beginning of a scope implicitly generated +/// by the compiler on encountering a CompoundStmt +class CFGScopeBegin : public CFGElement { +public: + CFGScopeBegin() {} + CFGScopeBegin(const VarDecl *VD, const Stmt *S) + : CFGElement(ScopeBegin, VD, S) {} + + // Get statement that triggered a new scope. + const Stmt *getTriggerStmt() const { + return static_cast<Stmt*>(Data2.getPointer()); + } + + // Get VD that triggered a new scope. + const VarDecl *getVarDecl() const { + return static_cast<VarDecl *>(Data1.getPointer()); + } + +private: + friend class CFGElement; + static bool isKind(const CFGElement &E) { + Kind kind = E.getKind(); + return kind == ScopeBegin; + } +}; + +/// Represents end of a scope implicitly generated by +/// the compiler after the last Stmt in a CompoundStmt's body +class CFGScopeEnd : public CFGElement { +public: + CFGScopeEnd() {} + CFGScopeEnd(const VarDecl *VD, const Stmt *S) : CFGElement(ScopeEnd, VD, S) {} + + const VarDecl *getVarDecl() const { + return static_cast<VarDecl *>(Data1.getPointer()); + } + + const Stmt *getTriggerStmt() const { + return static_cast<Stmt *>(Data2.getPointer()); + } + +private: + friend class CFGElement; + static bool isKind(const CFGElement &E) { + Kind kind = E.getKind(); + return kind == ScopeEnd; + } +}; + /// CFGImplicitDtor - Represents C++ object destructor implicitly generated /// by compiler on various occasions. class CFGImplicitDtor : public CFGElement { @@ -747,6 +873,17 @@ public: Elements.push_back(CFGStmt(statement), C); } + void appendConstructor(CXXConstructExpr *CE, const ConstructionContext *CC, + BumpVectorContext &C) { + Elements.push_back(CFGConstructor(CE, CC), C); + } + + void appendCXXRecordTypedCall(CallExpr *CE, + const ConstructionContext *CC, + BumpVectorContext &C) { + Elements.push_back(CFGCXXRecordTypedCall(CE, CC), C); + } + void appendInitializer(CXXCtorInitializer *initializer, BumpVectorContext &C) { Elements.push_back(CFGInitializer(initializer), C); @@ -757,6 +894,24 @@ public: Elements.push_back(CFGNewAllocator(NE), C); } + void appendScopeBegin(const VarDecl *VD, const Stmt *S, + BumpVectorContext &C) { + Elements.push_back(CFGScopeBegin(VD, S), C); + } + + void prependScopeBegin(const VarDecl *VD, const Stmt *S, + BumpVectorContext &C) { + Elements.insert(Elements.rbegin(), 1, CFGScopeBegin(VD, S), C); + } + + void appendScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) { + Elements.push_back(CFGScopeEnd(VD, S), C); + } + + void prependScopeEnd(const VarDecl *VD, const Stmt *S, BumpVectorContext &C) { + Elements.insert(Elements.rbegin(), 1, CFGScopeEnd(VD, S), C); + } + void appendBaseDtor(const CXXBaseSpecifier *BS, BumpVectorContext &C) { Elements.push_back(CFGBaseDtor(BS), C); } @@ -810,9 +965,22 @@ public: *I = CFGLifetimeEnds(VD, S); return ++I; } + + // Scope leaving must be performed in reversed order. So insertion is in two + // steps. First we prepare space for some number of elements, then we insert + // the elements beginning at the last position in prepared space. + iterator beginScopeEndInsert(iterator I, size_t Cnt, BumpVectorContext &C) { + return iterator( + Elements.insert(I.base(), Cnt, CFGScopeEnd(nullptr, nullptr), C)); + } + iterator insertScopeEnd(iterator I, VarDecl *VD, Stmt *S) { + *I = CFGScopeEnd(VD, S); + return ++I; + } + }; -/// \brief CFGCallback defines methods that should be called when a logical +/// CFGCallback defines methods that should be called when a logical /// operator error is found when building the CFG. class CFGCallback { public: @@ -852,9 +1020,12 @@ public: bool AddLifetime = false; bool AddLoopExit = false; bool AddTemporaryDtors = false; + bool AddScopes = false; bool AddStaticInitBranches = false; bool AddCXXNewAllocator = false; bool AddCXXDefaultInitExprInCtors = false; + bool AddRichCXXConstructors = false; + bool MarkElidedCXXConstructors = false; BuildOptions() = default; diff --git a/include/clang/Analysis/CallGraph.h b/include/clang/Analysis/CallGraph.h index bdcdfecddc3eb..ae0f392ed9697 100644 --- a/include/clang/Analysis/CallGraph.h +++ b/include/clang/Analysis/CallGraph.h @@ -34,7 +34,7 @@ class Decl; class DeclContext; class Stmt; -/// \brief The AST-based call graph. +/// The AST-based call graph. /// /// The call graph extends itself with the given declarations by implementing /// the recursive AST visitor, which constructs the graph by visiting the given @@ -55,7 +55,7 @@ public: CallGraph(); ~CallGraph(); - /// \brief Populate the call graph with the functions in the given + /// Populate the call graph with the functions in the given /// declaration. /// /// Recursively walks the declaration to find all the dependent Decls as well. @@ -63,13 +63,13 @@ public: TraverseDecl(D); } - /// \brief Determine if a declaration should be included in the graph. + /// Determine if a declaration should be included in the graph. static bool includeInGraph(const Decl *D); - /// \brief Lookup the node for the given declaration. + /// Lookup the node for the given declaration. CallGraphNode *getNode(const Decl *) const; - /// \brief Lookup the node for the given declaration. If none found, insert + /// Lookup the node for the given declaration. If none found, insert /// one into the graph. CallGraphNode *getOrInsertNode(Decl *); @@ -83,7 +83,7 @@ public: const_iterator begin() const { return FunctionMap.begin(); } const_iterator end() const { return FunctionMap.end(); } - /// \brief Get the number of nodes in the graph. + /// Get the number of nodes in the graph. unsigned size() const { return FunctionMap.size(); } /// \ brief Get the virtual root of the graph, all the functions available @@ -133,10 +133,10 @@ public: bool shouldWalkTypesOfTypeLocs() const { return false; } private: - /// \brief Add the given declaration to the call graph. + /// Add the given declaration to the call graph. void addNodeForDecl(Decl *D, bool IsGlobal); - /// \brief Allocate a new node in the graph. + /// Allocate a new node in the graph. CallGraphNode *allocateNewNode(Decl *); }; @@ -145,10 +145,10 @@ public: using CallRecord = CallGraphNode *; private: - /// \brief The function/method declaration. + /// The function/method declaration. Decl *FD; - /// \brief The list of functions called from this node. + /// The list of functions called from this node. SmallVector<CallRecord, 5> CalledFunctions; public: diff --git a/include/clang/Analysis/CloneDetection.h b/include/clang/Analysis/CloneDetection.h index 051b9236658cf..955777a11a652 100644 --- a/include/clang/Analysis/CloneDetection.h +++ b/include/clang/Analysis/CloneDetection.h @@ -161,7 +161,7 @@ public: /// The result of findClones can be further constrained with the constrainClones /// method. /// -/// This class only searches for clones in exectuable source code +/// This class only searches for clones in executable source code /// (e.g. function bodies). Other clones (e.g. cloned comments or declarations) /// are not supported. class CloneDetector { @@ -351,7 +351,7 @@ struct FilenamePatternConstraint { /// Analyzes the pattern of the referenced variables in a statement. class VariablePattern { - /// Describes an occurence of a variable reference in a statement. + /// Describes an occurrence of a variable reference in a statement. struct VariableOccurence { /// The index of the associated VarDecl in the Variables vector. size_t KindID; @@ -362,7 +362,7 @@ class VariablePattern { : KindID(KindID), Mention(Mention) {} }; - /// All occurences of referenced variables in the order of appearance. + /// All occurrences of referenced variables in the order of appearance. std::vector<VariableOccurence> Occurences; /// List of referenced variables in the order of appearance. /// Every item in this list is unique. diff --git a/include/clang/Analysis/CodeInjector.h b/include/clang/Analysis/CodeInjector.h index 413a55b05b07a..2c87cde996f20 100644 --- a/include/clang/Analysis/CodeInjector.h +++ b/include/clang/Analysis/CodeInjector.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::CodeInjector interface which is responsible for +/// Defines the clang::CodeInjector interface which is responsible for /// injecting AST of function definitions that may not be available in the /// original source. /// @@ -23,7 +23,7 @@ class Stmt; class FunctionDecl; class ObjCMethodDecl; -/// \brief CodeInjector is an interface which is responsible for injecting AST +/// 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 diff --git a/include/clang/Analysis/ConstructionContext.h b/include/clang/Analysis/ConstructionContext.h new file mode 100644 index 0000000000000..40cb0e7e5ddaa --- /dev/null +++ b/include/clang/Analysis/ConstructionContext.h @@ -0,0 +1,474 @@ +//===- ConstructionContext.h - CFG constructor information ------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the ConstructionContext class and its sub-classes, +// which represent various different ways of constructing C++ objects +// with the additional information the users may want to know about +// the constructor. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H +#define LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H + +#include "clang/Analysis/Support/BumpVector.h" +#include "clang/AST/ExprCXX.h" + +namespace clang { + +/// Construction context is a linked list of multiple layers. Layers are +/// created gradually while traversing the AST, and layers that represent +/// the outmost AST nodes are built first, while the node that immediately +/// contains the constructor would be built last and capture the previous +/// layers as its parents. Construction context captures the last layer +/// (which has links to the previous layers) and classifies the seemingly +/// arbitrary chain of layers into one of the possible ways of constructing +/// an object in C++ for user-friendly experience. +class ConstructionContextLayer { +public: + typedef llvm::PointerUnion<Stmt *, CXXCtorInitializer *> TriggerTy; + +private: + /// The construction site - the statement that triggered the construction + /// for one of its parts. For instance, stack variable declaration statement + /// triggers construction of itself or its elements if it's an array, + /// new-expression triggers construction of the newly allocated object(s). + TriggerTy Trigger; + + /// Sometimes a single trigger is not enough to describe the construction + /// site. In this case we'd have a chain of "partial" construction context + /// layers. + /// Some examples: + /// - A constructor within in an aggregate initializer list within a variable + /// would have a construction context of the initializer list with + /// the parent construction context of a variable. + /// - A constructor for a temporary that needs to be both destroyed + /// and materialized into an elidable copy constructor would have a + /// construction context of a CXXBindTemporaryExpr with the parent + /// construction context of a MaterializeTemproraryExpr. + /// Not all of these are currently supported. + const ConstructionContextLayer *Parent = nullptr; + + ConstructionContextLayer(TriggerTy Trigger, + const ConstructionContextLayer *Parent) + : Trigger(Trigger), Parent(Parent) {} + +public: + static const ConstructionContextLayer * + create(BumpVectorContext &C, TriggerTy Trigger, + const ConstructionContextLayer *Parent = nullptr); + + const ConstructionContextLayer *getParent() const { return Parent; } + bool isLast() const { return !Parent; } + + const Stmt *getTriggerStmt() const { + return Trigger.dyn_cast<Stmt *>(); + } + + const CXXCtorInitializer *getTriggerInit() const { + return Trigger.dyn_cast<CXXCtorInitializer *>(); + } + + /// Returns true if these layers are equal as individual layers, even if + /// their parents are different. + bool isSameLayer(const ConstructionContextLayer *Other) const { + assert(Other); + return (Trigger == Other->Trigger); + } + + /// See if Other is a proper initial segment of this construction context + /// in terms of the parent chain - i.e. a few first parents coincide and + /// then the other context terminates but our context goes further - i.e., + /// we are providing the same context that the other context provides, + /// and a bit more above that. + bool isStrictlyMoreSpecificThan(const ConstructionContextLayer *Other) const; +}; + + +/// ConstructionContext's subclasses describe different ways of constructing +/// an object in C++. The context re-captures the essential parent AST nodes +/// of the CXXConstructExpr it is assigned to and presents these nodes +/// through easy-to-understand accessor methods. +class ConstructionContext { +public: + enum Kind { + SimpleVariableKind, + CXX17ElidedCopyVariableKind, + VARIABLE_BEGIN = SimpleVariableKind, + VARIABLE_END = CXX17ElidedCopyVariableKind, + SimpleConstructorInitializerKind, + CXX17ElidedCopyConstructorInitializerKind, + INITIALIZER_BEGIN = SimpleConstructorInitializerKind, + INITIALIZER_END = CXX17ElidedCopyConstructorInitializerKind, + NewAllocatedObjectKind, + SimpleTemporaryObjectKind, + ElidedTemporaryObjectKind, + TEMPORARY_BEGIN = SimpleTemporaryObjectKind, + TEMPORARY_END = ElidedTemporaryObjectKind, + SimpleReturnedValueKind, + CXX17ElidedCopyReturnedValueKind, + RETURNED_VALUE_BEGIN = SimpleReturnedValueKind, + RETURNED_VALUE_END = CXX17ElidedCopyReturnedValueKind + }; + +protected: + Kind K; + + // Do not make public! These need to only be constructed + // via createFromLayers(). + explicit ConstructionContext(Kind K) : K(K) {} + +private: + // A helper function for constructing an instance into a bump vector context. + template <typename T, typename... ArgTypes> + static T *create(BumpVectorContext &C, ArgTypes... Args) { + auto *CC = C.getAllocator().Allocate<T>(); + return new (CC) T(Args...); + } + +public: + /// Consume the construction context layer, together with its parent layers, + /// and wrap it up into a complete construction context. May return null + /// if layers do not form any supported construction context. + static const ConstructionContext * + createFromLayers(BumpVectorContext &C, + const ConstructionContextLayer *TopLayer); + + Kind getKind() const { return K; } +}; + +/// An abstract base class for local variable constructors. +class VariableConstructionContext : public ConstructionContext { + const DeclStmt *DS; + +protected: + VariableConstructionContext(ConstructionContext::Kind K, const DeclStmt *DS) + : ConstructionContext(K), DS(DS) { + assert(classof(this)); + assert(DS); + } + +public: + const DeclStmt *getDeclStmt() const { return DS; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() >= VARIABLE_BEGIN && + CC->getKind() <= VARIABLE_END; + } +}; + +/// Represents construction into a simple local variable, eg. T var(123);. +/// If a variable has an initializer, eg. T var = makeT();, then the final +/// elidable copy-constructor from makeT() into var would also be a simple +/// variable constructor handled by this class. +class SimpleVariableConstructionContext : public VariableConstructionContext { + friend class ConstructionContext; // Allows to create<>() itself. + + explicit SimpleVariableConstructionContext(const DeclStmt *DS) + : VariableConstructionContext(ConstructionContext::SimpleVariableKind, + DS) {} + +public: + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == SimpleVariableKind; + } +}; + +/// Represents construction into a simple variable with an initializer syntax, +/// with a single constructor, eg. T var = makeT();. Such construction context +/// may only appear in C++17 because previously it was split into a temporary +/// object constructor and an elidable simple variable copy-constructor and +/// we were producing separate construction contexts for these constructors. +/// In C++17 we have a single construction context that combines both. +/// Note that if the object has trivial destructor, then this code is +/// indistinguishable from a simple variable constructor on the AST level; +/// in this case we provide a simple variable construction context. +class CXX17ElidedCopyVariableConstructionContext + : public VariableConstructionContext { + const CXXBindTemporaryExpr *BTE; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit CXX17ElidedCopyVariableConstructionContext( + const DeclStmt *DS, const CXXBindTemporaryExpr *BTE) + : VariableConstructionContext(CXX17ElidedCopyVariableKind, DS), BTE(BTE) { + assert(BTE); + } + +public: + const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == CXX17ElidedCopyVariableKind; + } +}; + +// An abstract base class for constructor-initializer-based constructors. +class ConstructorInitializerConstructionContext : public ConstructionContext { + const CXXCtorInitializer *I; + +protected: + explicit ConstructorInitializerConstructionContext( + ConstructionContext::Kind K, const CXXCtorInitializer *I) + : ConstructionContext(K), I(I) { + assert(classof(this)); + assert(I); + } + +public: + const CXXCtorInitializer *getCXXCtorInitializer() const { return I; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() >= INITIALIZER_BEGIN && + CC->getKind() <= INITIALIZER_END; + } +}; + +/// Represents construction into a field or a base class within a bigger object +/// via a constructor initializer, eg. T(): field(123) { ... }. +class SimpleConstructorInitializerConstructionContext + : public ConstructorInitializerConstructionContext { + friend class ConstructionContext; // Allows to create<>() itself. + + explicit SimpleConstructorInitializerConstructionContext( + const CXXCtorInitializer *I) + : ConstructorInitializerConstructionContext( + ConstructionContext::SimpleConstructorInitializerKind, I) {} + +public: + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == SimpleConstructorInitializerKind; + } +}; + +/// Represents construction into a field or a base class within a bigger object +/// via a constructor initializer, with a single constructor, eg. +/// T(): field(Field(123)) { ... }. Such construction context may only appear +/// in C++17 because previously it was split into a temporary object constructor +/// and an elidable simple constructor-initializer copy-constructor and we were +/// producing separate construction contexts for these constructors. In C++17 +/// we have a single construction context that combines both. Note that if the +/// object has trivial destructor, then this code is indistinguishable from +/// a simple constructor-initializer constructor on the AST level; in this case +/// we provide a simple constructor-initializer construction context. +class CXX17ElidedCopyConstructorInitializerConstructionContext + : public ConstructorInitializerConstructionContext { + const CXXBindTemporaryExpr *BTE; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit CXX17ElidedCopyConstructorInitializerConstructionContext( + const CXXCtorInitializer *I, const CXXBindTemporaryExpr *BTE) + : ConstructorInitializerConstructionContext( + CXX17ElidedCopyConstructorInitializerKind, I), + BTE(BTE) { + assert(BTE); + } + +public: + const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == CXX17ElidedCopyConstructorInitializerKind; + } +}; + +/// Represents immediate initialization of memory allocated by operator new, +/// eg. new T(123);. +class NewAllocatedObjectConstructionContext : public ConstructionContext { + const CXXNewExpr *NE; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit NewAllocatedObjectConstructionContext(const CXXNewExpr *NE) + : ConstructionContext(ConstructionContext::NewAllocatedObjectKind), + NE(NE) { + assert(NE); + } + +public: + const CXXNewExpr *getCXXNewExpr() const { return NE; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == NewAllocatedObjectKind; + } +}; + +/// Represents a temporary object, eg. T(123), that does not immediately cross +/// function boundaries "by value"; constructors that construct function +/// value-type arguments or values that are immediately returned from the +/// function that returns a value receive separate construction context kinds. +class TemporaryObjectConstructionContext : public ConstructionContext { + const CXXBindTemporaryExpr *BTE; + const MaterializeTemporaryExpr *MTE; + +protected: + explicit TemporaryObjectConstructionContext( + ConstructionContext::Kind K, const CXXBindTemporaryExpr *BTE, + const MaterializeTemporaryExpr *MTE) + : ConstructionContext(K), BTE(BTE), MTE(MTE) { + // Both BTE and MTE can be null here, all combinations possible. + // Even though for now at least one should be non-null, we simply haven't + // implemented the other case yet (this would be a temporary in the middle + // of nowhere that doesn't have a non-trivial destructor). + } + +public: + /// CXXBindTemporaryExpr here is non-null as long as the temporary has + /// a non-trivial destructor. + const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { + return BTE; + } + + /// MaterializeTemporaryExpr is non-null as long as the temporary is actually + /// used after construction, eg. by binding to a reference (lifetime + /// extension), accessing a field, calling a method, or passing it into + /// a function (an elidable copy or move constructor would be a common + /// example) by reference. + const MaterializeTemporaryExpr *getMaterializedTemporaryExpr() const { + return MTE; + } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() >= TEMPORARY_BEGIN && CC->getKind() <= TEMPORARY_END; + } +}; + +/// Represents a temporary object that is not constructed for the purpose of +/// being immediately copied/moved by an elidable copy/move-constructor. +/// This includes temporary objects "in the middle of nowhere" like T(123) and +/// lifetime-extended temporaries. +class SimpleTemporaryObjectConstructionContext + : public TemporaryObjectConstructionContext { + friend class ConstructionContext; // Allows to create<>() itself. + + explicit SimpleTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE) + : TemporaryObjectConstructionContext( + ConstructionContext::SimpleTemporaryObjectKind, BTE, MTE) {} + +public: + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == SimpleTemporaryObjectKind; + } +}; + +/// Represents a temporary object that is constructed for the sole purpose +/// of being immediately copied by an elidable copy/move constructor. +/// For example, T t = T(123); includes a temporary T(123) that is immediately +/// copied to variable t. In such cases the elidable copy can (but not +/// necessarily should) be omitted ("elided") accodring to the rules of the +/// language; the constructor would then construct variable t directly. +/// This construction context contains information of the elidable constructor +/// and its respective construction context. +class ElidedTemporaryObjectConstructionContext + : public TemporaryObjectConstructionContext { + const CXXConstructExpr *ElidedCE; + const ConstructionContext *ElidedCC; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit ElidedTemporaryObjectConstructionContext( + const CXXBindTemporaryExpr *BTE, const MaterializeTemporaryExpr *MTE, + const CXXConstructExpr *ElidedCE, const ConstructionContext *ElidedCC) + : TemporaryObjectConstructionContext( + ConstructionContext::ElidedTemporaryObjectKind, BTE, MTE), + ElidedCE(ElidedCE), ElidedCC(ElidedCC) { + // Elided constructor and its context should be either both specified + // or both unspecified. In the former case, the constructor must be + // elidable. + assert(ElidedCE && ElidedCE->isElidable() && ElidedCC); + } + +public: + const CXXConstructExpr *getConstructorAfterElision() const { + return ElidedCE; + } + + const ConstructionContext *getConstructionContextAfterElision() const { + return ElidedCC; + } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == ElidedTemporaryObjectKind; + } +}; + +class ReturnedValueConstructionContext : public ConstructionContext { + const ReturnStmt *RS; + +protected: + explicit ReturnedValueConstructionContext(ConstructionContext::Kind K, + const ReturnStmt *RS) + : ConstructionContext(K), RS(RS) { + assert(classof(this)); + assert(RS); + } + +public: + const ReturnStmt *getReturnStmt() const { return RS; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() >= RETURNED_VALUE_BEGIN && + CC->getKind() <= RETURNED_VALUE_END; + } +}; + +/// Represents a temporary object that is being immediately returned from a +/// function by value, eg. return t; or return T(123);. In this case there is +/// always going to be a constructor at the return site. However, the usual +/// temporary-related bureaucracy (CXXBindTemporaryExpr, +/// MaterializeTemporaryExpr) is normally located in the caller function's AST. +class SimpleReturnedValueConstructionContext + : public ReturnedValueConstructionContext { + friend class ConstructionContext; // Allows to create<>() itself. + + explicit SimpleReturnedValueConstructionContext(const ReturnStmt *RS) + : ReturnedValueConstructionContext( + ConstructionContext::SimpleReturnedValueKind, RS) {} + +public: + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == SimpleReturnedValueKind; + } +}; + +/// Represents a temporary object that is being immediately returned from a +/// function by value, eg. return t; or return T(123); in C++17. +/// In C++17 there is not going to be an elidable copy constructor at the +/// return site. However, the usual temporary-related bureaucracy (CXXBindTemporaryExpr, +/// MaterializeTemporaryExpr) is normally located in the caller function's AST. +/// Note that if the object has trivial destructor, then this code is +/// indistinguishable from a simple returned value constructor on the AST level; +/// in this case we provide a simple returned value construction context. +class CXX17ElidedCopyReturnedValueConstructionContext + : public ReturnedValueConstructionContext { + const CXXBindTemporaryExpr *BTE; + + friend class ConstructionContext; // Allows to create<>() itself. + + explicit CXX17ElidedCopyReturnedValueConstructionContext( + const ReturnStmt *RS, const CXXBindTemporaryExpr *BTE) + : ReturnedValueConstructionContext( + ConstructionContext::CXX17ElidedCopyReturnedValueKind, RS), + BTE(BTE) { + assert(BTE); + } + +public: + const CXXBindTemporaryExpr *getCXXBindTemporaryExpr() const { return BTE; } + + static bool classof(const ConstructionContext *CC) { + return CC->getKind() == CXX17ElidedCopyReturnedValueKind; + } +}; + +} // end namespace clang + +#endif // LLVM_CLANG_ANALYSIS_CONSTRUCTIONCONTEXT_H diff --git a/include/clang/Analysis/ProgramPoint.h b/include/clang/Analysis/ProgramPoint.h index 2d59dec48a880..e8f0d61617eb7 100644 --- a/include/clang/Analysis/ProgramPoint.h +++ b/include/clang/Analysis/ProgramPoint.h @@ -73,8 +73,9 @@ public: PostStoreKind, PostConditionKind, PostLValueKind, + PostAllocatorCallKind, MinPostStmtKind = PostStmtKind, - MaxPostStmtKind = PostLValueKind, + MaxPostStmtKind = PostAllocatorCallKind, PostInitializerKind, CallEnterKind, CallExitBeginKind, @@ -97,7 +98,7 @@ private: llvm::PointerIntPair<const ProgramPointTag *, 2, unsigned> Tag; protected: - ProgramPoint() {} + ProgramPoint() = default; ProgramPoint(const void *P, Kind k, const LocationContext *l, @@ -134,7 +135,7 @@ public: getLocationContext(), tag); } - /// \brief Convert to the specified ProgramPoint type, asserting that this + /// Convert to the specified ProgramPoint type, asserting that this /// ProgramPoint is of the desired type. template<typename T> T castAs() const { @@ -145,7 +146,7 @@ public: return t; } - /// \brief Convert to the specified ProgramPoint type, returning None if this + /// Convert to the specified ProgramPoint type, returning None if this /// ProgramPoint is not of the desired type. template<typename T> Optional<T> getAs() const { @@ -166,7 +167,7 @@ public: return (Kind) x; } - /// \brief Is this a program point corresponding to purge/removal of dead + /// Is this a program point corresponding to purge/removal of dead /// symbols and bindings. bool isPurgeKind() { Kind K = getKind(); @@ -180,6 +181,10 @@ public: return L.getPointer(); } + const StackFrameContext *getStackFrame() const { + return getLocationContext()->getStackFrame(); + } + // For use with DenseMap. This hash is probably slow. unsigned getHashValue() const { llvm::FoldingSetNodeID ID; @@ -233,7 +238,7 @@ public: private: friend class ProgramPoint; - BlockEntrance() {} + BlockEntrance() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == BlockEntranceKind; } @@ -254,7 +259,7 @@ public: private: friend class ProgramPoint; - BlockExit() {} + BlockExit() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == BlockExitKind; } @@ -274,7 +279,7 @@ public: const T* getStmtAs() const { return dyn_cast<T>(getStmt()); } protected: - StmtPoint() {} + StmtPoint() = default; private: friend class ProgramPoint; static bool isKind(const ProgramPoint &Location) { @@ -294,7 +299,7 @@ public: private: friend class ProgramPoint; - PreStmt() {} + PreStmt() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PreStmtKind; } @@ -302,7 +307,7 @@ private: class PostStmt : public StmtPoint { protected: - PostStmt() {} + PostStmt() = default; PostStmt(const Stmt *S, const void *data, Kind k, const LocationContext *L, const ProgramPointTag *tag = nullptr) : StmtPoint(S, data, k, L, tag) {} @@ -333,7 +338,7 @@ public: private: friend class ProgramPoint; - PostCondition() {} + PostCondition() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostConditionKind; } @@ -341,7 +346,7 @@ private: class LocationCheck : public StmtPoint { protected: - LocationCheck() {} + LocationCheck() = default; LocationCheck(const Stmt *S, const LocationContext *L, ProgramPoint::Kind K, const ProgramPointTag *tag) : StmtPoint(S, nullptr, K, L, tag) {} @@ -362,7 +367,7 @@ public: private: friend class ProgramPoint; - PreLoad() {} + PreLoad() = default; static bool isKind(const ProgramPoint &location) { return location.getKind() == PreLoadKind; } @@ -376,7 +381,7 @@ public: private: friend class ProgramPoint; - PreStore() {} + PreStore() = default; static bool isKind(const ProgramPoint &location) { return location.getKind() == PreStoreKind; } @@ -390,13 +395,13 @@ public: private: friend class ProgramPoint; - PostLoad() {} + PostLoad() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostLoadKind; } }; -/// \brief Represents a program point after a store evaluation. +/// Represents a program point after a store evaluation. class PostStore : public PostStmt { public: /// Construct the post store point. @@ -409,7 +414,7 @@ public: setData2(Loc); } - /// \brief Returns the information about the location used in the store, + /// Returns the information about the location used in the store, /// how it was uttered in the code. const void *getLocationValue() const { return getData2(); @@ -417,7 +422,7 @@ public: private: friend class ProgramPoint; - PostStore() {} + PostStore() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostStoreKind; } @@ -431,7 +436,7 @@ public: private: friend class ProgramPoint; - PostLValue() {} + PostLValue() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostLValueKind; } @@ -447,7 +452,7 @@ public: private: friend class ProgramPoint; - PreStmtPurgeDeadSymbols() {} + PreStmtPurgeDeadSymbols() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PreStmtPurgeDeadSymbolsKind; } @@ -463,7 +468,7 @@ public: private: friend class ProgramPoint; - PostStmtPurgeDeadSymbols() {} + PostStmtPurgeDeadSymbols() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostStmtPurgeDeadSymbolsKind; } @@ -487,7 +492,7 @@ public: private: friend class ProgramPoint; - BlockEdge() {} + BlockEdge() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == BlockEdgeKind; } @@ -495,7 +500,7 @@ private: class PostInitializer : public ProgramPoint { public: - /// \brief Construct a PostInitializer point that represents a location after + /// Construct a PostInitializer point that represents a location after /// CXXCtorInitializer expression evaluation. /// /// \param I The initializer. @@ -509,14 +514,14 @@ public: return static_cast<const CXXCtorInitializer *>(getData1()); } - /// \brief Returns the location of the field. + /// Returns the location of the field. const void *getLocationValue() const { return getData2(); } private: friend class ProgramPoint; - PostInitializer() {} + PostInitializer() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostInitializerKind; } @@ -537,7 +542,7 @@ public: } protected: - ImplicitCallPoint() {} + ImplicitCallPoint() = default; private: friend class ProgramPoint; static bool isKind(const ProgramPoint &Location) { @@ -557,7 +562,7 @@ public: private: friend class ProgramPoint; - PreImplicitCall() {} + PreImplicitCall() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PreImplicitCallKind; } @@ -574,12 +579,26 @@ public: private: friend class ProgramPoint; - PostImplicitCall() {} + PostImplicitCall() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == PostImplicitCallKind; } }; +class PostAllocatorCall : public StmtPoint { +public: + PostAllocatorCall(const Stmt *S, const LocationContext *L, + const ProgramPointTag *Tag = nullptr) + : StmtPoint(S, nullptr, PostAllocatorCallKind, L, Tag) {} + +private: + friend class ProgramPoint; + PostAllocatorCall() = default; + static bool isKind(const ProgramPoint &Location) { + return Location.getKind() == PostAllocatorCallKind; + } +}; + /// Represents a point when we begin processing an inlined call. /// CallEnter uses the caller's location context. class CallEnter : public ProgramPoint { @@ -605,7 +624,7 @@ public: private: friend class ProgramPoint; - CallEnter() {} + CallEnter() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == CallEnterKind; } @@ -626,9 +645,13 @@ public: CallExitBegin(const StackFrameContext *L, const ReturnStmt *RS) : ProgramPoint(RS, CallExitBeginKind, L, nullptr) { } + const ReturnStmt *getReturnStmt() const { + return static_cast<const ReturnStmt *>(getData1()); + } + private: friend class ProgramPoint; - CallExitBegin() {} + CallExitBegin() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == CallExitBeginKind; } @@ -649,7 +672,7 @@ public: private: friend class ProgramPoint; - CallExitEnd() {} + CallExitEnd() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == CallExitEndKind; } @@ -672,7 +695,7 @@ public: private: friend class ProgramPoint; - LoopExit() {} + LoopExit() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == LoopExitKind; } @@ -691,7 +714,7 @@ public: private: friend class ProgramPoint; - EpsilonPoint() {} + EpsilonPoint() = default; static bool isKind(const ProgramPoint &Location) { return Location.getKind() == EpsilonKind; } diff --git a/include/clang/Basic/ABI.h b/include/clang/Basic/ABI.h index 75e9faf4617e2..bd919ce24f81f 100644 --- a/include/clang/Basic/ABI.h +++ b/include/clang/Basic/ABI.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Enums/classes describing ABI related information about constructors, +/// Enums/classes describing ABI related information about constructors, /// destructors and thunks. /// //===----------------------------------------------------------------------===// @@ -21,7 +21,7 @@ namespace clang { -/// \brief C++ constructor types. +/// C++ constructor types. enum CXXCtorType { Ctor_Complete, ///< Complete object ctor Ctor_Base, ///< Base object ctor @@ -30,7 +30,7 @@ enum CXXCtorType { Ctor_DefaultClosure, ///< Default closure variant of a ctor }; -/// \brief C++ destructor types. +/// C++ destructor types. enum CXXDtorType { Dtor_Deleting, ///< Deleting dtor Dtor_Complete, ///< Complete object dtor @@ -38,29 +38,29 @@ enum CXXDtorType { Dtor_Comdat ///< The COMDAT used for dtors }; -/// \brief A return adjustment. +/// A return adjustment. struct ReturnAdjustment { - /// \brief The non-virtual adjustment from the derived object to its + /// The non-virtual adjustment from the derived object to its /// nearest virtual base. int64_t NonVirtual; - /// \brief Holds the ABI-specific information about the virtual return + /// Holds the ABI-specific information about the virtual return /// adjustment, if needed. union VirtualAdjustment { // Itanium ABI struct { - /// \brief The offset (in bytes), relative to the address point + /// The offset (in bytes), relative to the address point /// of the virtual base class offset. int64_t VBaseOffsetOffset; } Itanium; // Microsoft ABI struct { - /// \brief The offset (in bytes) of the vbptr, relative to the beginning + /// The offset (in bytes) of the vbptr, relative to the beginning /// of the derived class. uint32_t VBPtrOffset; - /// \brief Index of the virtual base in the vbtable. + /// Index of the virtual base in the vbtable. uint32_t VBIndex; } Microsoft; @@ -104,31 +104,31 @@ struct ReturnAdjustment { } }; -/// \brief A \c this pointer adjustment. +/// A \c this pointer adjustment. struct ThisAdjustment { - /// \brief The non-virtual adjustment from the derived object to its + /// The non-virtual adjustment from the derived object to its /// nearest virtual base. int64_t NonVirtual; - /// \brief Holds the ABI-specific information about the virtual this + /// Holds the ABI-specific information about the virtual this /// adjustment, if needed. union VirtualAdjustment { // Itanium ABI struct { - /// \brief The offset (in bytes), relative to the address point, + /// The offset (in bytes), relative to the address point, /// of the virtual call offset. int64_t VCallOffsetOffset; } Itanium; struct { - /// \brief The offset of the vtordisp (in bytes), relative to the ECX. + /// The offset of the vtordisp (in bytes), relative to the ECX. int32_t VtordispOffset; - /// \brief The offset of the vbptr of the derived class (in bytes), + /// The offset of the vbptr of the derived class (in bytes), /// relative to the ECX after vtordisp adjustment. int32_t VBPtrOffset; - /// \brief The offset (in bytes) of the vbase offset in the vbtable. + /// The offset (in bytes) of the vbase offset in the vbtable. int32_t VBOffsetOffset; } Microsoft; @@ -174,16 +174,16 @@ struct ThisAdjustment { class CXXMethodDecl; -/// \brief The \c this pointer adjustment as well as an optional return +/// The \c this pointer adjustment as well as an optional return /// adjustment for a thunk. struct ThunkInfo { - /// \brief The \c this pointer adjustment. + /// The \c this pointer adjustment. ThisAdjustment This; - /// \brief The return adjustment. + /// The return adjustment. ReturnAdjustment Return; - /// \brief Holds a pointer to the overridden method this thunk is for, + /// Holds a pointer to the overridden method this thunk is for, /// if needed by the ABI to distinguish different thunks with equal /// adjustments. Otherwise, null. /// CAUTION: In the unlikely event you need to sort ThunkInfos, consider using diff --git a/include/clang/Basic/AddressSpaces.h b/include/clang/Basic/AddressSpaces.h index 6b0090813e9b4..217fbd763ff2e 100644 --- a/include/clang/Basic/AddressSpaces.h +++ b/include/clang/Basic/AddressSpaces.h @@ -1,4 +1,4 @@ -//===--- AddressSpaces.h - Language-specific address spaces -----*- C++ -*-===// +//===- AddressSpaces.h - Language-specific address spaces -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,25 +6,25 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Provides definitions for the various language-specific address +/// Provides definitions for the various language-specific address /// spaces. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_ADDRESSSPACES_H #define LLVM_CLANG_BASIC_ADDRESSSPACES_H -#include <assert.h> +#include <cassert> namespace clang { -/// \brief Defines the address space values used by the address space qualifier +/// Defines the address space values used by the address space qualifier /// of QualType. /// enum class LangAS : unsigned { - // The default value 0 is the value used in QualType for the the situation + // The default value 0 is the value used in QualType for the situation // where there is no address space qualifier. Default = 0, @@ -51,7 +51,7 @@ enum class LangAS : unsigned { /// The type of a lookup table which maps from language-specific address spaces /// to target-specific ones. -typedef unsigned LangASMap[(unsigned)LangAS::FirstTargetAddressSpace]; +using LangASMap = unsigned[(unsigned)LangAS::FirstTargetAddressSpace]; /// \return whether \p AS is a target-specific address space rather than a /// clang AST address space @@ -71,4 +71,4 @@ inline LangAS getLangASFromTargetAS(unsigned TargetAS) { } // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_ADDRESSSPACES_H diff --git a/include/clang/Basic/AlignedAllocation.h b/include/clang/Basic/AlignedAllocation.h index b3496949f39ac..9751f41184477 100644 --- a/include/clang/Basic/AlignedAllocation.h +++ b/include/clang/Basic/AlignedAllocation.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines a function that returns the minimum OS versions supporting +/// Defines a function that returns the minimum OS versions supporting /// C++17's aligned allocation functions. /// //===----------------------------------------------------------------------===// @@ -16,24 +16,24 @@ #ifndef LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H #define LLVM_CLANG_BASIC_ALIGNED_ALLOCATION_H -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/VersionTuple.h" namespace clang { -inline VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { +inline llvm::VersionTuple alignedAllocMinVersion(llvm::Triple::OSType OS) { switch (OS) { default: break; case llvm::Triple::Darwin: case llvm::Triple::MacOSX: // Earliest supporting version is 10.13. - return VersionTuple(10U, 13U); + return llvm::VersionTuple(10U, 13U); case llvm::Triple::IOS: case llvm::Triple::TvOS: // Earliest supporting version is 11.0.0. - return VersionTuple(11U); + return llvm::VersionTuple(11U); case llvm::Triple::WatchOS: // Earliest supporting version is 4.0.0. - return VersionTuple(4U); + return llvm::VersionTuple(4U); } llvm_unreachable("Unexpected OS"); diff --git a/include/clang/Basic/AllDiagnostics.h b/include/clang/Basic/AllDiagnostics.h index 1c83e2d0f8a0b..20c29d459d229 100644 --- a/include/clang/Basic/AllDiagnostics.h +++ b/include/clang/Basic/AllDiagnostics.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Includes all the separate Diagnostic headers & some related helpers. +/// Includes all the separate Diagnostic headers & some related helpers. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index 8b84c4b8b50de..0bbe52bf5f36f 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -83,6 +83,9 @@ def LocalVar : SubsetSubject<Var, def NonParmVar : SubsetSubject<Var, [{S->getKind() != Decl::ParmVar}], "variables">; +def NonLocalVar : SubsetSubject<Var, + [{!S->hasLocalStorage()}], + "variables with non-local storage">; def NonBitField : SubsetSubject<Field, [{!S->isBitField()}], "non-bit-field non-static data members">; @@ -111,6 +114,9 @@ def SharedVar : SubsetSubject<Var, def GlobalVar : SubsetSubject<Var, [{S->hasGlobalStorage()}], "global variables">; +def InlineFunction : SubsetSubject<Function, + [{S->isInlineSpecified()}], "inline functions">; + // FIXME: this hack is needed because DeclNodes.td defines the base Decl node // type to be a class, not a definition. This makes it impossible to create an // attribute subject which accepts a Decl. Normally, this is not a problem, @@ -162,6 +168,13 @@ class UnsignedArgument<string name, bit opt = 0> : Argument<name, opt>; class VariadicUnsignedArgument<string name> : Argument<name, 1>; class VariadicExprArgument<string name> : Argument<name, 1>; class VariadicStringArgument<string name> : Argument<name, 1>; +class VariadicIdentifierArgument<string name> : Argument<name, 1>; + +// Like VariadicUnsignedArgument except values are ParamIdx. +class VariadicParamIdxArgument<string name> : Argument<name, 1>; + +// Like VariadicParamIdxArgument but for a single function parameter index. +class ParamIdxArgument<string name, bit opt = 0> : Argument<name, opt>; // A version of the form major.minor[.subminor]. class VersionArgument<string name, bit opt = 0> : Argument<name, opt>; @@ -172,7 +185,8 @@ class VersionArgument<string name, bit opt = 0> : Argument<name, opt>; class AlignedArgument<string name, bit opt = 0> : Argument<name, opt>; // A bool argument with a default value -class DefaultBoolArgument<string name, bit default> : BoolArgument<name, 1> { +class DefaultBoolArgument<string name, bit default, bit fake = 0> + : BoolArgument<name, 1, fake> { bit Default = default; } @@ -231,9 +245,12 @@ class GCC<string name> : Spelling<name, "GCC"> { let KnownToGCC = 1; } -// The Clang spelling implies GNU<name> and CXX11<"clang", name>. This spelling -// should be used for any Clang-specific attributes. -class Clang<string name> : Spelling<name, "Clang">; +// The Clang spelling implies GNU<name>, CXX11<"clang", name>, and optionally, +// C2x<"clang", name>. This spelling should be used for any Clang-specific +// attributes. +class Clang<string name, bit allowInC = 1> : Spelling<name, "Clang"> { + bit AllowInC = allowInC; +} class Accessor<string name, list<Spelling> spellings> { string Name = name; @@ -291,6 +308,7 @@ def TargetAVR : TargetArch<["avr"]>; def TargetMips32 : TargetArch<["mips", "mipsel"]>; def TargetAnyMips : TargetArch<["mips", "mipsel", "mips64", "mips64el"]>; def TargetMSP430 : TargetArch<["msp430"]>; +def TargetRISCV : TargetArch<["riscv32", "riscv64"]>; def TargetX86 : TargetArch<["x86"]>; def TargetAnyX86 : TargetArch<["x86", "x86_64"]>; def TargetWindows : TargetArch<["x86", "x86_64", "arm", "thumb", "aarch64"]> { @@ -438,9 +456,6 @@ class Attr { // Set to true if all of the attribute's arguments should be parsed in an // unevaluated context. bit ParseArgumentsAsUnevaluated = 0; - // Set to true if this attribute can be duplicated on a subject when merging - // attributes. By default, attributes are not merged. - bit DuplicatesAllowedWhileMerging = 0; // Set to true if this attribute meaningful when applied to or inherited // in a class template definition. bit MeaningfulToClassTemplateDefinition = 0; @@ -475,7 +490,16 @@ class TypeAttr : Attr { class StmtAttr : Attr; /// An inheritable attribute is inherited by later redeclarations. -class InheritableAttr : Attr; +class InheritableAttr : Attr { + // Set to true if this attribute can be duplicated on a subject when inheriting + // attributes from prior declarations. + bit InheritEvenIfAlreadyPresent = 0; +} + +/// Some attributes, like calling conventions, can appear in either the +/// declaration or the type position. These attributes are morally type +/// attributes, but have historically been written on declarations. +class DeclOrTypeAttr : InheritableAttr; /// A target-specific attribute. This class is meant to be used as a mixin /// with InheritableAttr or Attr depending on the attribute's needs. @@ -487,7 +511,7 @@ class TargetSpecificAttr<TargetSpec target> { // "exists" for a given target. So two target-specific attributes can share // the same name when they exist in different targets. To support this, a // Kind can be explicitly specified for a target-specific attribute. This - // corresponds to the AttributeList::AT_* enum that is generated and it + // corresponds to the ParsedAttr::AT_* enum that is generated and it // should contain a shared value between the attributes. // // Target-specific attributes which use this feature should ensure that the @@ -584,6 +608,12 @@ def AlwaysInline : InheritableAttr { let Documentation = [Undocumented]; } +def Artificial : InheritableAttr { + let Spellings = [GCC<"artificial">]; + let Subjects = SubjectList<[InlineFunction], WarnDiag>; + let Documentation = [ArtificialDocs]; +} + def XRayInstrument : InheritableAttr { let Spellings = [Clang<"xray_always_instrument">, Clang<"xray_never_instrument">]; @@ -598,6 +628,12 @@ def XRayInstrument : InheritableAttr { def XRayLogArgs : InheritableAttr { let Spellings = [Clang<"xray_log_args">]; let Subjects = SubjectList<[Function, ObjCMethod]>; + // This argument is a count not an index, so it has the same encoding (base + // 1 including C++ implicit this parameter) at the source and LLVM levels of + // representation, so ParamIdxArgument is inappropriate. It is never used + // at the AST level of representation, so it never needs to be adjusted not + // to include any C++ implicit this parameter. Thus, we just store it and + // use it as an unsigned that never needs adjustment. let Args = [UnsignedArgument<"ArgumentCount">]; let Documentation = [XRayDocs]; } @@ -660,9 +696,7 @@ def AsmLabel : InheritableAttr { } def Availability : InheritableAttr { - // TODO: does not have a [[]] spelling because it requires custom parsing - // support. - let Spellings = [GNU<"availability">]; + let Spellings = [Clang<"availability">]; let Args = [IdentifierArgument<"platform">, VersionArgument<"introduced">, VersionArgument<"deprecated">, VersionArgument<"obsoleted">, BoolArgument<"unavailable">, StringArgument<"message">, @@ -706,7 +740,7 @@ static llvm::StringRef canonicalizePlatformName(llvm::StringRef Platform) { .Default(Platform); } }]; let HasCustomParsing = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Named]>; let Documentation = [AvailabilityDocs]; } @@ -739,7 +773,7 @@ def CarriesDependency : InheritableParamAttr { let Documentation = [CarriesDependencyDocs]; } -def CDecl : InheritableAttr { +def CDecl : DeclOrTypeAttr { let Spellings = [GCC<"cdecl">, Keyword<"__cdecl">, Keyword<"_cdecl">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; @@ -813,6 +847,27 @@ def Constructor : InheritableAttr { let Documentation = [Undocumented]; } +def CPUSpecific : InheritableAttr { + let Spellings = [Clang<"cpu_specific">]; + let Args = [VariadicIdentifierArgument<"Cpus">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [CPUSpecificCPUDispatchDocs]; + let AdditionalMembers = [{ + unsigned ActiveArgIndex = 0; + + IdentifierInfo *getCurCPUName() const { + return *(cpus_begin() + ActiveArgIndex); + } + }]; +} + +def CPUDispatch : InheritableAttr { + let Spellings = [Clang<"cpu_dispatch">]; + let Args = [VariadicIdentifierArgument<"Cpus">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [CPUSpecificCPUDispatchDocs]; +} + // CUDA attributes are spelled __attribute__((attr)) or __declspec(__attr__), // and they do not receive a [[]] spelling. def CUDAConstant : InheritableAttr { @@ -1007,7 +1062,8 @@ def EmptyBases : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { def AllocSize : InheritableAttr { let Spellings = [GCC<"alloc_size">]; let Subjects = SubjectList<[Function]>; - let Args = [IntArgument<"ElemSizeParam">, IntArgument<"NumElemsParam", 1>]; + let Args = [ParamIdxArgument<"ElemSizeParam">, + ParamIdxArgument<"NumElemsParam", /*opt*/ 1>]; let TemplateDependent = 1; let Documentation = [AllocSizeDocs]; } @@ -1039,14 +1095,14 @@ def FallThrough : StmtAttr { let Documentation = [FallthroughDocs]; } -def FastCall : InheritableAttr { +def FastCall : DeclOrTypeAttr { let Spellings = [GCC<"fastcall">, Keyword<"__fastcall">, Keyword<"_fastcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [FastCallDocs]; } -def RegCall : InheritableAttr { +def RegCall : DeclOrTypeAttr { let Spellings = [GCC<"regcall">, Keyword<"__regcall">]; let Documentation = [RegCallDocs]; } @@ -1094,7 +1150,7 @@ def Format : InheritableAttr { def FormatArg : InheritableAttr { let Spellings = [GCC<"format_arg">]; - let Args = [IntArgument<"FormatIdx">]; + let Args = [ParamIdxArgument<"FormatIdx">]; let Subjects = SubjectList<[ObjCMethod, HasFunctionProto]>; let Documentation = [Undocumented]; } @@ -1155,6 +1211,15 @@ def LayoutVersion : InheritableAttr, TargetSpecificAttr<TargetMicrosoftCXXABI> { let Documentation = [LayoutVersionDocs]; } +def TrivialABI : InheritableAttr { + // This attribute does not have a C [[]] spelling because it requires the + // CPlusPlus language option. + let Spellings = [Clang<"trivial_abi", 0>]; + let Subjects = SubjectList<[CXXRecord]>; + let Documentation = [TrivialABIDocs]; + let LangOpts = [CPlusPlus]; +} + def MaxFieldAlignment : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; @@ -1169,7 +1234,7 @@ def MayAlias : InheritableAttr { let Documentation = [Undocumented]; } -def MSABI : InheritableAttr { +def MSABI : DeclOrTypeAttr { let Spellings = [GCC<"ms_abi">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [MSABIDocs]; @@ -1310,6 +1375,17 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> { let Documentation = [MicroMipsDocs]; } +def RISCVInterrupt : InheritableAttr, TargetSpecificAttr<TargetRISCV> { + let Spellings = [GCC<"interrupt">]; + let Subjects = SubjectList<[Function]>; + let Args = [EnumArgument<"Interrupt", "InterruptType", + ["user", "supervisor", "machine"], + ["user", "supervisor", "machine"], + 1>]; + let ParseKind = "Interrupt"; + let Documentation = [RISCVInterruptDocs]; +} + // This is not a TargetSpecificAttr so that is silently accepted and // ignored on other targets as encouraged by the OpenCL spec. // @@ -1328,28 +1404,28 @@ def NoMicroMips : InheritableAttr, TargetSpecificAttr<TargetMips32> { // this should be rejected on non-kernels. def AMDGPUFlatWorkGroupSize : InheritableAttr { - let Spellings = [Clang<"amdgpu_flat_work_group_size">]; + let Spellings = [Clang<"amdgpu_flat_work_group_size", 0>]; let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max">]; let Documentation = [AMDGPUFlatWorkGroupSizeDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def AMDGPUWavesPerEU : InheritableAttr { - let Spellings = [Clang<"amdgpu_waves_per_eu">]; + let Spellings = [Clang<"amdgpu_waves_per_eu", 0>]; let Args = [UnsignedArgument<"Min">, UnsignedArgument<"Max", 1>]; let Documentation = [AMDGPUWavesPerEUDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def AMDGPUNumSGPR : InheritableAttr { - let Spellings = [Clang<"amdgpu_num_sgpr">]; + let Spellings = [Clang<"amdgpu_num_sgpr", 0>]; let Args = [UnsignedArgument<"NumSGPR">]; let Documentation = [AMDGPUNumSGPRNumVGPRDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; } def AMDGPUNumVGPR : InheritableAttr { - let Spellings = [Clang<"amdgpu_num_vgpr">]; + let Spellings = [Clang<"amdgpu_num_vgpr", 0>]; let Args = [UnsignedArgument<"NumVGPR">]; let Documentation = [AMDGPUNumSGPRNumVGPRDocs]; let Subjects = SubjectList<[Function], ErrorDiag, "kernel functions">; @@ -1365,18 +1441,18 @@ def NonNull : InheritableParamAttr { let Spellings = [GCC<"nonnull">]; let Subjects = SubjectList<[ObjCMethod, HasFunctionProto, ParmVar], WarnDiag, "functions, methods, and parameters">; - let Args = [VariadicUnsignedArgument<"Args">]; - let AdditionalMembers = -[{bool isNonNull(unsigned idx) const { - if (!args_size()) - return true; - for (const auto &V : args()) - if (V == idx) + let Args = [VariadicParamIdxArgument<"Args">]; + let AdditionalMembers = [{ + bool isNonNull(unsigned IdxAST) const { + if (!args_size()) return true; - return false; - } }]; + return args_end() != std::find_if( + args_begin(), args_end(), + [=](const ParamIdx &Idx) { return Idx.getASTIndex() == IdxAST; }); + } + }]; // FIXME: We should merge duplicates into a single nonnull attribute. - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Documentation = [NonNullDocs]; } @@ -1432,7 +1508,7 @@ def AssumeAligned : InheritableAttr { def AllocAlign : InheritableAttr { let Spellings = [GCC<"alloc_align">]; let Subjects = SubjectList<[HasFunctionProto]>; - let Args = [IntArgument<"ParamIndex">]; + let Args = [ParamIdxArgument<"ParamIndex">]; let Documentation = [AllocAlignDocs]; } @@ -1454,6 +1530,12 @@ def NotTailCalled : InheritableAttr { let Documentation = [NotTailCalledDocs]; } +def NoStackProtector : InheritableAttr { + let Spellings = [Clang<"no_stack_protector">]; + let Subjects = SubjectList<[Function]>; + let Documentation = [NoStackProtectorDocs]; +} + def NoThrow : InheritableAttr { let Spellings = [GCC<"nothrow">, Declspec<"nothrow">]; let Subjects = SubjectList<[Function]>; @@ -1483,13 +1565,11 @@ def ObjCBridgeMutable : InheritableAttr { } def ObjCBridgeRelated : InheritableAttr { - // TODO: this attribute does not have a [[]] spelling because it requires - // custom parsing support. - let Spellings = [GNU<"objc_bridge_related">]; + let Spellings = [Clang<"objc_bridge_related">]; let Subjects = SubjectList<[Record], ErrorDiag>; let Args = [IdentifierArgument<"RelatedClass">, - IdentifierArgument<"ClassMethod", 1>, - IdentifierArgument<"InstanceMethod", 1>]; + IdentifierArgument<"ClassMethod">, + IdentifierArgument<"InstanceMethod">]; let HasCustomParsing = 1; let Documentation = [Undocumented]; } @@ -1643,7 +1723,8 @@ def Ownership : InheritableAttr { Returns; } }]; - let Args = [IdentifierArgument<"Module">, VariadicUnsignedArgument<"Args">]; + let Args = [IdentifierArgument<"Module">, + VariadicParamIdxArgument<"Args">]; let Subjects = SubjectList<[HasFunctionProto]>; let Documentation = [Undocumented]; } @@ -1654,13 +1735,13 @@ def Packed : InheritableAttr { let Documentation = [Undocumented]; } -def IntelOclBicc : InheritableAttr { - let Spellings = [Clang<"intel_ocl_bicc">]; +def IntelOclBicc : DeclOrTypeAttr { + let Spellings = [Clang<"intel_ocl_bicc", 0>]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } -def Pcs : InheritableAttr { +def Pcs : DeclOrTypeAttr { let Spellings = [GCC<"pcs">]; let Args = [EnumArgument<"PCS", "PCSType", ["aapcs", "aapcs-vfp"], @@ -1690,7 +1771,9 @@ def ReqdWorkGroupSize : InheritableAttr { } def RequireConstantInit : InheritableAttr { - let Spellings = [Clang<"require_constant_initialization">]; + // This attribute does not have a C [[]] spelling because it requires the + // CPlusPlus language option. + let Spellings = [Clang<"require_constant_initialization", 0>]; let Subjects = SubjectList<[GlobalVar], ErrorDiag>; let Documentation = [RequireConstantInitDocs]; let LangOpts = [CPlusPlus]; @@ -1721,6 +1804,13 @@ def Section : InheritableAttr { let Documentation = [SectionDocs]; } +def CodeSeg : InheritableAttr { + let Spellings = [Declspec<"code_seg">]; + let Args = [StringArgument<"Name">]; + let Subjects = SubjectList<[Function, CXXRecord], ErrorDiag>; + let Documentation = [CodeSegDocs]; +} + def PragmaClangBSSSection : InheritableAttr { // This attribute has no spellings as it is only ever created implicitly. let Spellings = []; @@ -1761,13 +1851,13 @@ def Sentinel : InheritableAttr { let Documentation = [Undocumented]; } -def StdCall : InheritableAttr { +def StdCall : DeclOrTypeAttr { let Spellings = [GCC<"stdcall">, Keyword<"__stdcall">, Keyword<"_stdcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [StdCallDocs]; } -def SwiftCall : InheritableAttr { +def SwiftCall : DeclOrTypeAttr { let Spellings = [Clang<"swiftcall">]; // let Subjects = SubjectList<[Function]>; let Documentation = [SwiftCallDocs]; @@ -1794,38 +1884,38 @@ def Suppress : StmtAttr { let Documentation = [SuppressDocs]; } -def SysVABI : InheritableAttr { +def SysVABI : DeclOrTypeAttr { let Spellings = [GCC<"sysv_abi">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } -def ThisCall : InheritableAttr { +def ThisCall : DeclOrTypeAttr { let Spellings = [GCC<"thiscall">, Keyword<"__thiscall">, Keyword<"_thiscall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [ThisCallDocs]; } -def VectorCall : InheritableAttr { +def VectorCall : DeclOrTypeAttr { let Spellings = [Clang<"vectorcall">, Keyword<"__vectorcall">, Keyword<"_vectorcall">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [VectorCallDocs]; } -def Pascal : InheritableAttr { +def Pascal : DeclOrTypeAttr { let Spellings = [Clang<"pascal">, Keyword<"__pascal">, Keyword<"_pascal">]; // let Subjects = [Function, ObjCMethod]; let Documentation = [Undocumented]; } -def PreserveMost : InheritableAttr { +def PreserveMost : DeclOrTypeAttr { let Spellings = [Clang<"preserve_most">]; let Documentation = [PreserveMostDocs]; } -def PreserveAll : InheritableAttr { +def PreserveAll : DeclOrTypeAttr { let Spellings = [Clang<"preserve_all">]; let Documentation = [PreserveAllDocs]; } @@ -1840,12 +1930,27 @@ def Target : InheritableAttr { std::vector<std::string> Features; StringRef Architecture; bool DuplicateArchitecture = false; + bool operator ==(const ParsedTargetAttr &Other) const { + return DuplicateArchitecture == Other.DuplicateArchitecture && + Architecture == Other.Architecture && Features == Other.Features; + } }; ParsedTargetAttr parse() const { return parse(getFeaturesStr()); } + + template<class Compare> + ParsedTargetAttr parse(Compare cmp) const { + ParsedTargetAttr Attrs = parse(); + llvm::sort(std::begin(Attrs.Features), std::end(Attrs.Features), cmp); + return Attrs; + } + + bool isDefaultVersion() const { return getFeaturesStr() == "default"; } + static ParsedTargetAttr parse(StringRef Features) { ParsedTargetAttr Ret; + if (Features == "default") return Ret; SmallVector<StringRef, 1> AttrFeatures; Features.split(AttrFeatures, ","); @@ -1861,7 +1966,7 @@ def Target : InheritableAttr { // overall feature validity for the function with the rest of the // attributes on the function. if (Feature.startswith("fpmath=") || Feature.startswith("tune=")) - continue; + continue; // While we're here iterating check for a different target cpu. if (Feature.startswith("arch=")) { @@ -1879,6 +1984,13 @@ def Target : InheritableAttr { }]; } +def MinVectorWidth : InheritableAttr { + let Spellings = [Clang<"min_vector_width">]; + let Args = [UnsignedArgument<"VectorWidth">]; + let Subjects = SubjectList<[Function], ErrorDiag>; + let Documentation = [MinVectorWidthDocs]; +} + def TransparentUnion : InheritableAttr { let Spellings = [GCC<"transparent_union">]; // let Subjects = SubjectList<[Record, TypedefName]>; @@ -1913,7 +2025,7 @@ def DiagnoseIf : InheritableAttr { ["DT_Error", "DT_Warning"]>, BoolArgument<"ArgDependent", 0, /*fake*/ 1>, NamedArgument<"Parent", 0, /*fake*/ 1>]; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let LateParsed = 1; let AdditionalMembers = [{ bool isError() const { return diagnosticType == DT_Error; } @@ -1958,6 +2070,7 @@ def Unused : InheritableAttr { def Used : InheritableAttr { let Spellings = [GCC<"used">]; + let Subjects = SubjectList<[NonLocalVar, Function, ObjCMethod]>; let Documentation = [Undocumented]; } @@ -2006,7 +2119,10 @@ def TypeVisibility : InheritableAttr { } def VecReturn : InheritableAttr { - let Spellings = [Clang<"vecreturn">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ struct/class/union. + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"vecreturn", 0>]; let Subjects = SubjectList<[CXXRecord], ErrorDiag>; let Documentation = [Undocumented]; } @@ -2066,6 +2182,12 @@ def AnyX86NoCallerSavedRegisters : InheritableAttr, let Documentation = [AnyX86NoCallerSavedRegistersDocs]; } +def AnyX86NoCfCheck : InheritableAttr, TargetSpecificAttr<TargetAnyX86>{ + let Spellings = [GCC<"nocf_check">]; + let Subjects = SubjectList<[FunctionLike]>; + let Documentation = [AnyX86NoCfCheckDocs]; +} + def X86ForceAlignArgPointer : InheritableAttr, TargetSpecificAttr<TargetAnyX86> { let Spellings = [GCC<"force_align_arg_pointer">]; // Technically, this appertains to a FunctionDecl, but the target-specific @@ -2112,13 +2234,13 @@ def NoSanitizeSpecific : InheritableAttr { // an updated captability-based name and the older name will only be supported // under the GNU-style spelling. def GuardedVar : InheritableAttr { - let Spellings = [Clang<"guarded_var">]; + let Spellings = [Clang<"guarded_var", 0>]; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } def PtGuardedVar : InheritableAttr { - let Spellings = [Clang<"pt_guarded_var">]; + let Spellings = [Clang<"pt_guarded_var", 0>]; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2131,17 +2253,17 @@ def Lockable : InheritableAttr { } def ScopedLockable : InheritableAttr { - let Spellings = [Clang<"scoped_lockable">]; + let Spellings = [Clang<"scoped_lockable", 0>]; let Subjects = SubjectList<[Record]>; let Documentation = [Undocumented]; } def Capability : InheritableAttr { - let Spellings = [Clang<"capability">, Clang<"shared_capability">]; + let Spellings = [Clang<"capability", 0>, Clang<"shared_capability", 0>]; let Subjects = SubjectList<[Record, TypedefName], ErrorDiag>; let Args = [StringArgument<"Name">]; let Accessors = [Accessor<"isShared", - [Clang<"shared_capability">]>]; + [Clang<"shared_capability", 0>]>]; let Documentation = [Undocumented]; let AdditionalMembers = [{ bool isMutex() const { return getName().equals_lower("mutex"); } @@ -2150,83 +2272,83 @@ def Capability : InheritableAttr { } def AssertCapability : InheritableAttr { - let Spellings = [Clang<"assert_capability">, - Clang<"assert_shared_capability">]; + let Spellings = [Clang<"assert_capability", 0>, + Clang<"assert_shared_capability", 0>]; let Subjects = SubjectList<[Function]>; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [Clang<"assert_shared_capability">]>]; + [Clang<"assert_shared_capability", 0>]>]; let Documentation = [AssertCapabilityDocs]; } def AcquireCapability : InheritableAttr { - let Spellings = [Clang<"acquire_capability">, - Clang<"acquire_shared_capability">, + let Spellings = [Clang<"acquire_capability", 0>, + Clang<"acquire_shared_capability", 0>, GNU<"exclusive_lock_function">, GNU<"shared_lock_function">]; let Subjects = SubjectList<[Function]>; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [Clang<"acquire_shared_capability">, + [Clang<"acquire_shared_capability", 0>, GNU<"shared_lock_function">]>]; let Documentation = [AcquireCapabilityDocs]; } def TryAcquireCapability : InheritableAttr { - let Spellings = [Clang<"try_acquire_capability">, - Clang<"try_acquire_shared_capability">]; + let Spellings = [Clang<"try_acquire_capability", 0>, + Clang<"try_acquire_shared_capability", 0>]; let Subjects = SubjectList<[Function], ErrorDiag>; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Args = [ExprArgument<"SuccessValue">, VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [Clang<"try_acquire_shared_capability">]>]; + [Clang<"try_acquire_shared_capability", 0>]>]; let Documentation = [TryAcquireCapabilityDocs]; } def ReleaseCapability : InheritableAttr { - let Spellings = [Clang<"release_capability">, - Clang<"release_shared_capability">, - Clang<"release_generic_capability">, - Clang<"unlock_function">]; + let Spellings = [Clang<"release_capability", 0>, + Clang<"release_shared_capability", 0>, + Clang<"release_generic_capability", 0>, + Clang<"unlock_function", 0>]; let Subjects = SubjectList<[Function]>; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Args = [VariadicExprArgument<"Args">]; let Accessors = [Accessor<"isShared", - [Clang<"release_shared_capability">]>, + [Clang<"release_shared_capability", 0>]>, Accessor<"isGeneric", - [Clang<"release_generic_capability">, - Clang<"unlock_function">]>]; + [Clang<"release_generic_capability", 0>, + Clang<"unlock_function", 0>]>]; let Documentation = [ReleaseCapabilityDocs]; } def RequiresCapability : InheritableAttr { - let Spellings = [Clang<"requires_capability">, - Clang<"exclusive_locks_required">, - Clang<"requires_shared_capability">, - Clang<"shared_locks_required">]; + let Spellings = [Clang<"requires_capability", 0>, + Clang<"exclusive_locks_required", 0>, + Clang<"requires_shared_capability", 0>, + Clang<"shared_locks_required", 0>]; let Args = [VariadicExprArgument<"Args">]; let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Function]>; - let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability">, - Clang<"shared_locks_required">]>]; + let Accessors = [Accessor<"isShared", [Clang<"requires_shared_capability", 0>, + Clang<"shared_locks_required", 0>]>]; let Documentation = [Undocumented]; } @@ -2242,7 +2364,7 @@ def GuardedBy : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2253,7 +2375,7 @@ def PtGuardedBy : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2264,7 +2386,7 @@ def AcquiredAfter : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2275,7 +2397,7 @@ def AcquiredBefore : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Field, SharedVar]>; let Documentation = [Undocumented]; } @@ -2286,7 +2408,7 @@ def AssertExclusiveLock : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } @@ -2297,7 +2419,7 @@ def AssertSharedLock : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } @@ -2310,7 +2432,7 @@ def ExclusiveTrylockFunction : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } @@ -2323,7 +2445,7 @@ def SharedTrylockFunction : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } @@ -2344,7 +2466,7 @@ def LocksExcluded : InheritableAttr { let LateParsed = 1; let TemplateDependent = 1; let ParseArgumentsAsUnevaluated = 1; - let DuplicatesAllowedWhileMerging = 1; + let InheritEvenIfAlreadyPresent = 1; let Subjects = SubjectList<[Function]>; let Documentation = [Undocumented]; } @@ -2352,7 +2474,10 @@ def LocksExcluded : InheritableAttr { // C/C++ consumed attributes. def Consumable : InheritableAttr { - let Spellings = [Clang<"consumable">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ struct/class/union. + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"consumable", 0>]; let Subjects = SubjectList<[CXXRecord]>; let Args = [EnumArgument<"DefaultState", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2361,19 +2486,28 @@ def Consumable : InheritableAttr { } def ConsumableAutoCast : InheritableAttr { - let Spellings = [Clang<"consumable_auto_cast_state">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ struct/class/union. + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"consumable_auto_cast_state", 0>]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [Undocumented]; } def ConsumableSetOnRead : InheritableAttr { - let Spellings = [Clang<"consumable_set_state_on_read">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ struct/class/union. + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"consumable_set_state_on_read", 0>]; let Subjects = SubjectList<[CXXRecord]>; let Documentation = [Undocumented]; } def CallableWhen : InheritableAttr { - let Spellings = [Clang<"callable_when">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ function (but doesn't require it to be a member function). + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"callable_when", 0>]; let Subjects = SubjectList<[CXXMethod]>; let Args = [VariadicEnumArgument<"CallableStates", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2382,7 +2516,10 @@ def CallableWhen : InheritableAttr { } def ParamTypestate : InheritableAttr { - let Spellings = [Clang<"param_typestate">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to a parameter whose type is a consumable C++ class. + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"param_typestate", 0>]; let Subjects = SubjectList<[ParmVar]>; let Args = [EnumArgument<"ParamState", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2391,7 +2528,10 @@ def ParamTypestate : InheritableAttr { } def ReturnTypestate : InheritableAttr { - let Spellings = [Clang<"return_typestate">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to a parameter or function return type that is a consumable C++ class. + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"return_typestate", 0>]; let Subjects = SubjectList<[Function, ParmVar]>; let Args = [EnumArgument<"State", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2400,7 +2540,10 @@ def ReturnTypestate : InheritableAttr { } def SetTypestate : InheritableAttr { - let Spellings = [Clang<"set_typestate">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ function (but doesn't require it to be a member function). + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"set_typestate", 0>]; let Subjects = SubjectList<[CXXMethod]>; let Args = [EnumArgument<"NewState", "ConsumedState", ["unknown", "consumed", "unconsumed"], @@ -2409,7 +2552,10 @@ def SetTypestate : InheritableAttr { } def TestTypestate : InheritableAttr { - let Spellings = [Clang<"test_typestate">]; + // This attribute does not have a C [[]] spelling because it only appertains + // to C++ function (but doesn't require it to be a member function). + // FIXME: should this attribute have a CPlusPlus language option? + let Spellings = [Clang<"test_typestate", 0>]; let Subjects = SubjectList<[CXXMethod]>; let Args = [EnumArgument<"TestState", "ConsumedState", ["consumed", "unconsumed"], @@ -2420,18 +2566,18 @@ def TestTypestate : InheritableAttr { // Type safety attributes for `void *' pointers and type tags. def ArgumentWithTypeTag : InheritableAttr { - let Spellings = [GNU<"argument_with_type_tag">, - GNU<"pointer_with_type_tag">]; + let Spellings = [Clang<"argument_with_type_tag">, + Clang<"pointer_with_type_tag">]; + let Subjects = SubjectList<[HasFunctionProto], ErrorDiag>; let Args = [IdentifierArgument<"ArgumentKind">, - UnsignedArgument<"ArgumentIdx">, - UnsignedArgument<"TypeTagIdx">, - BoolArgument<"IsPointer">]; - let HasCustomParsing = 1; + ParamIdxArgument<"ArgumentIdx">, + ParamIdxArgument<"TypeTagIdx">, + BoolArgument<"IsPointer", /*opt*/0, /*fake*/1>]; let Documentation = [ArgumentWithTypeTagDocs, PointerWithTypeTagDocs]; } def TypeTagForDatatype : InheritableAttr { - let Spellings = [GNU<"type_tag_for_datatype">]; + let Spellings = [Clang<"type_tag_for_datatype">]; let Args = [IdentifierArgument<"ArgumentKind">, TypeArgument<"MatchingCType">, BoolArgument<"LayoutCompatible">, @@ -2469,6 +2615,16 @@ def DLLImport : InheritableAttr, TargetSpecificAttr<TargetWindows> { let Spellings = [Declspec<"dllimport">, GCC<"dllimport">]; let Subjects = SubjectList<[Function, Var, CXXRecord, ObjCInterface]>; let Documentation = [DLLImportDocs]; + + + let AdditionalMembers = [{ +private: + bool PropagatedToBaseTemplate = false; + +public: + void setPropagatedToBaseTemplate() { PropagatedToBaseTemplate = true; } + bool wasPropagatedToBaseTemplate() { return PropagatedToBaseTemplate; } + }]; } def SelectAny : InheritableAttr { @@ -2510,7 +2666,7 @@ def UPtr : TypeAttr { def MSInheritance : InheritableAttr { let LangOpts = [MicrosoftExt]; - let Args = [DefaultBoolArgument<"BestCase", 1>]; + let Args = [DefaultBoolArgument<"BestCase", /*default*/1, /*fake*/1>]; let Spellings = [Keyword<"__single_inheritance">, Keyword<"__multiple_inheritance">, Keyword<"__virtual_inheritance">, @@ -2565,7 +2721,7 @@ def InitSeg : Attr { let Documentation = [InitSegDocs]; let AdditionalMembers = [{ void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const { - OS << '(' << getSection() << ')'; + OS << " (" << getSection() << ')'; } }]; } @@ -2575,7 +2731,7 @@ def LoopHint : Attr { /// 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. + /// interleave_count: interleaves 'Value' loop iterations. /// unroll: fully unroll loop if State == Enable. /// unroll_count: unrolls loop 'Value' times. /// distribute: attempt to distribute loop if State == Enable @@ -2620,12 +2776,12 @@ def LoopHint : Attr { if (SpellingIndex == Pragma_nounroll) return; else if (SpellingIndex == Pragma_unroll) { - OS << getValueString(Policy); + OS << ' ' << getValueString(Policy); return; } assert(SpellingIndex == Pragma_clang_loop && "Unexpected spelling"); - OS << getOptionName(option) << getValueString(Policy); + OS << ' ' << getOptionName(option) << getValueString(Policy); } // Return a string containing the loop hint argument including the @@ -2693,6 +2849,14 @@ def OMPCaptureKind : Attr { let Documentation = [Undocumented]; } +def OMPReferencedVar : Attr { + // This attribute has no spellings as it is only ever created implicitly. + let Spellings = []; + let SemaHandler = 0; + let Args = [ExprArgument<"Ref">]; + let Documentation = [Undocumented]; +} + def OMPDeclareSimdDecl : Attr { let Spellings = [Pragma<"omp", "declare simd">]; let Subjects = SubjectList<[Function]>; @@ -2712,37 +2876,37 @@ def OMPDeclareSimdDecl : Attr { void printPrettyPragma(raw_ostream & OS, const PrintingPolicy &Policy) const { if (getBranchState() != BS_Undefined) - OS << ConvertBranchStateTyToStr(getBranchState()) << " "; + OS << ' ' << ConvertBranchStateTyToStr(getBranchState()); if (auto *E = getSimdlen()) { - OS << "simdlen("; + OS << " simdlen("; E->printPretty(OS, nullptr, Policy); - OS << ") "; + OS << ")"; } if (uniforms_size() > 0) { - OS << "uniform"; + OS << " uniform"; StringRef Sep = "("; for (auto *E : uniforms()) { OS << Sep; E->printPretty(OS, nullptr, Policy); Sep = ", "; } - OS << ") "; + OS << ")"; } alignments_iterator NI = alignments_begin(); for (auto *E : aligneds()) { - OS << "aligned("; + OS << " aligned("; E->printPretty(OS, nullptr, Policy); if (*NI) { OS << ": "; (*NI)->printPretty(OS, nullptr, Policy); } - OS << ") "; + OS << ")"; ++NI; } steps_iterator I = steps_begin(); modifiers_iterator MI = modifiers_begin(); for (auto *E : linears()) { - OS << "linear("; + OS << " linear("; if (*MI != OMPC_LINEAR_unknown) OS << getOpenMPSimpleClauseTypeName(OMPC_linear, *MI) << "("; E->printPretty(OS, nullptr, Policy); @@ -2752,7 +2916,7 @@ def OMPDeclareSimdDecl : Attr { OS << ": "; (*I)->printPretty(OS, nullptr, Policy); } - OS << ") "; + OS << ")"; ++I; ++MI; } @@ -2773,7 +2937,7 @@ def OMPDeclareTargetDecl : Attr { void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const { // Use fake syntax because it is for testing and debugging purpose only. if (getMapType() != MT_To) - OS << ConvertMapTypeTyToStr(getMapType()) << " "; + OS << ' ' << ConvertMapTypeTyToStr(getMapType()); } }]; } diff --git a/include/clang/Basic/AttrDocs.td b/include/clang/Basic/AttrDocs.td index ecff329c4ccba..5a5ab78b49d11 100644 --- a/include/clang/Basic/AttrDocs.td +++ b/include/clang/Basic/AttrDocs.td @@ -191,6 +191,65 @@ in generation of more efficient code. }]; } +def CPUSpecificCPUDispatchDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``cpu_specific`` and ``cpu_dispatch`` attributes are used to define and +resolve multiversioned functions. This form of multiversioning provides a +mechanism for declaring versions across translation units and manually +specifying the resolved function list. A specified CPU defines a set of minimum +features that are required for the function to be called. The result of this is +that future processors execute the most restrictive version of the function the +new processor can execute. + +Function versions are defined with ``cpu_specific``, which takes one or more CPU +names as a parameter. For example: + +.. code-block:: c + + // Declares and defines the ivybridge version of single_cpu. + __attribute__((cpu_specific(ivybridge))) + void single_cpu(void){} + + // Declares and defines the atom version of single_cpu. + __attribute__((cpu_specific(atom))) + void single_cpu(void){} + + // Declares and defines both the ivybridge and atom version of multi_cpu. + __attribute__((cpu_specific(ivybridge, atom))) + void multi_cpu(void){} + +A dispatching (or resolving) function can be declared anywhere in a project's +source code with ``cpu_dispatch``. This attribute takes one or more CPU names +as a parameter (like ``cpu_specific``). Functions marked with ``cpu_dispatch`` +are not expected to be defined, only declared. If such a marked function has a +definition, any side effects of the function are ignored; trivial function +bodies are permissible for ICC compatibility. + +.. code-block:: c + + // Creates a resolver for single_cpu above. + __attribute__((cpu_dispatch(ivybridge, atom))) + void single_cpu(void){} + + // Creates a resolver for multi_cpu, but adds a 3rd version defined in another + // translation unit. + __attribute__((cpu_dispatch(ivybridge, atom, sandybridge))) + void multi_cpu(void){} + +Note that it is possible to have a resolving function that dispatches based on +more or fewer options than are present in the program. Specifying fewer will +result in the omitted options not being considered during resolution. Specifying +a version for resolution that isn't defined in the program will result in a +linking failure. + +It is also possible to specify a CPU name of ``generic`` which will be resolved +if the executing processor doesn't satisfy the features required in the CPU +name. The behavior of a program executing on a processor that doesn't satisfy +any option of a multiversioned function is undefined. + }]; +} + def C11NoReturnDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -273,7 +332,7 @@ def AllocSizeDocs : Documentation { let Content = [{ The ``alloc_size`` attribute can be placed on functions that return pointers in order to hint to the compiler how many bytes of memory will be available at the -returned poiner. ``alloc_size`` takes one or two arguments. +returned pointer. ``alloc_size`` takes one or two arguments. - ``alloc_size(N)`` implies that argument number N equals the number of available bytes at the returned pointer. @@ -306,12 +365,24 @@ An example of how to use ``alloc_size`` }]; } +def CodeSegDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``__declspec(code_seg)`` attribute enables the placement of code into separate +named segments that can be paged or locked in memory individually. This attribute +is used to control the placement of instantiated templates and compiler-generated +code. See the documentation for `__declspec(code_seg)`_ on MSDN. + +.. _`__declspec(code_seg)`: http://msdn.microsoft.com/en-us/library/dn636922.aspx + }]; +} + def AllocAlignDocs : Documentation { let Category = DocCatFunction; let Content = [{ Use ``__attribute__((alloc_align(<alignment>))`` on a function declaration to specify that the return value of the function (which must be a -pointer type) is at least as aligned as the value of the indicated parameter. The +pointer type) is at least as aligned as the value of the indicated parameter. The parameter is given by its index in the list of formal parameters; the first parameter has index 1 unless the function is a C++ non-static member function, in which case the first parameter has index 2 to account for the implicit ``this`` @@ -330,7 +401,7 @@ parameter. void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3))); Note that this attribute merely informs the compiler that a function always -returns a sufficiently aligned pointer. It does not cause the compiler to +returns a sufficiently aligned pointer. It does not cause the compiler to emit code to enforce that alignment. The behavior is undefined if the returned poitner is not sufficiently aligned. }]; @@ -353,7 +424,7 @@ available in C. int isdigit(int c); int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF"))); - + void foo(char c) { isdigit(c); isdigit(10); @@ -406,7 +477,7 @@ overload out of a number of viable overloads using enable_if. void f() __attribute__((enable_if(true, ""))); // #1 void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, ""))); // #2 - + void g(int i, int j) __attribute__((enable_if(i, ""))); // #1 void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true))); // #2 @@ -913,16 +984,16 @@ in the metadata name for that object. The `objc_runtime_name` attribute allows annotated interfaces or protocols to use the specified string argument in the object's metadata name instead of the default name. - + **Usage**: ``__attribute__((objc_runtime_name("MyLocalName")))``. This attribute can only be placed before an @protocol or @interface declaration: - + .. code-block:: objc - + __attribute__((objc_runtime_name("MyLocalName"))) @interface Message @end - + }]; } @@ -1228,7 +1299,7 @@ potentially-evaluated discarded-value expression that is not explicitly cast to .. code-block: c++ struct [[nodiscard]] error_info { /*...*/ }; error_info enable_missile_safety_mode(); - + void launch_missiles(); void test_missiles() { enable_missile_safety_mode(); // diagnoses @@ -1430,6 +1501,29 @@ as ``-mlong-calls`` and ``-mno-long-calls``. }]; } +def RISCVInterruptDocs : Documentation { + let Category = DocCatFunction; + let Heading = "interrupt (RISCV)"; + let Content = [{ +Clang supports the GNU style ``__attribute__((interrupt))`` attribute on RISCV +targets. This attribute may be attached to a function definition and instructs +the backend to generate appropriate function entry/exit code so that it can be +used directly as an interrupt service routine. + +Permissible values for this parameter are ``user``, ``supervisor``, +and ``machine``. If there is no parameter, then it defaults to machine. + +Repeated interrupt attribute on the same declaration will cause a warning +to be emitted. In case of repeated declarations, the last one prevails. + +Refer to: +https://gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html +https://riscv.org/specifications/privileged-isa/ +The RISC-V Instruction Set Manual Volume II: Privileged Architecture +Version 1.10. + }]; +} + def AVRInterruptDocs : Documentation { let Category = DocCatFunction; let Heading = "interrupt (AVR)"; @@ -1474,6 +1568,49 @@ for the function. Example "subtarget features" from the x86 backend include: "mmx", "sse", "sse4.2", "avx", "xop" and largely correspond to the machine specific options handled by the front end. + +Additionally, this attribute supports function multiversioning for ELF based +x86/x86-64 targets, which can be used to create multiple implementations of the +same function that will be resolved at runtime based on the priority of their +``target`` attribute strings. A function is considered a multiversioned function +if either two declarations of the function have different ``target`` attribute +strings, or if it has a ``target`` attribute string of ``default``. For +example: + + .. code-block:: c++ + + __attribute__((target("arch=atom"))) + void foo() {} // will be called on 'atom' processors. + __attribute__((target("default"))) + void foo() {} // will be called on any other processors. + +All multiversioned functions must contain a ``default`` (fallback) +implementation, otherwise usages of the function are considered invalid. +Additionally, a function may not become multiversioned after its first use. +}]; +} + +def MinVectorWidthDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((min_vector_width(width)))`` attribute. This +attribute may be attached to a function and informs the backend that this +function desires vectors of at least this width to be generated. Target-specific +maximum vector widths still apply. This means even if you ask for something +larger than the target supports, you will only get what the target supports. +This attribute is meant to be a hint to control target heuristics that may +generate narrower vectors than what the target hardware supports. + +This is currently used by the X86 target to allow some CPUs that support 512-bit +vectors to be limited to using 256-bit vectors to avoid frequency penalties. +This is currently enabled with the ``-prefer-vector-width=256`` command line +option. The ``min_vector_width`` attribute can be used to prevent the backend +from trying to split vector operations to match the ``prefer-vector-width``. All +X86 vector intrinsics from x86intrin.h already set this attribute. Additionally, +use of any of the X86-specific vector builtins will implicitly set this +attribute on the calling function. The intent is that explicitly writing vector +code using the X86 intrinsics will prevent ``prefer-vector-width`` from +affecting the code. }]; } @@ -1785,13 +1922,14 @@ This attribute accepts a single parameter that must be one of the following: def NoSanitizeDocs : Documentation { let Category = DocCatFunction; let Content = [{ -Use the ``no_sanitize`` attribute on a function declaration to specify -that a particular instrumentation or set of instrumentations should not be -applied to that function. The attribute takes a list of string literals, -which have the same meaning as values accepted by the ``-fno-sanitize=`` -flag. For example, ``__attribute__((no_sanitize("address", "thread")))`` -specifies that AddressSanitizer and ThreadSanitizer should not be applied -to the function. +Use the ``no_sanitize`` attribute on a function or a global variable +declaration to specify that a particular instrumentation or set of +instrumentations should not be applied. The attribute takes a list of +string literals, which have the same meaning as values accepted by the +``-fno-sanitize=`` flag. For example, +``__attribute__((no_sanitize("address", "thread")))`` specifies that +AddressSanitizer and ThreadSanitizer should not be applied to the +function or variable. See :ref:`Controlling Code Generation <controlling-code-generation>` for a full list of supported sanitizer flags. @@ -1806,9 +1944,9 @@ def NoSanitizeAddressDocs : Documentation { let Content = [{ .. _langext-address_sanitizer: -Use ``__attribute__((no_sanitize_address))`` on a function declaration to -specify that address safety instrumentation (e.g. AddressSanitizer) should -not be applied to that function. +Use ``__attribute__((no_sanitize_address))`` on a function or a global +variable declaration to specify that address safety instrumentation +(e.g. AddressSanitizer) should not be applied. }]; } @@ -2224,6 +2362,48 @@ It is only supported when using the Microsoft C++ ABI. }]; } +def TrivialABIDocs : Documentation { + let Category = DocCatVariable; + let Content = [{ +The ``trivial_abi`` attribute can be applied to a C++ class, struct, or union. +It instructs the compiler to pass and return the type using the C ABI for the +underlying type when the type would otherwise be considered non-trivial for the +purpose of calls. +A class annotated with `trivial_abi` can have non-trivial destructors or copy/move constructors without automatically becoming non-trivial for the purposes of calls. For example: + + .. code-block:: c++ + + // A is trivial for the purposes of calls because `trivial_abi` makes the + // user-provided special functions trivial. + struct __attribute__((trivial_abi)) A { + ~A(); + A(const A &); + A(A &&); + int x; + }; + + // B's destructor and copy/move constructor are considered trivial for the + // purpose of calls because A is trivial. + struct B { + A a; + }; + +If a type is trivial for the purposes of calls, has a non-trivial destructor, +and is passed as an argument by value, the convention is that the callee will +destroy the object before returning. + +Attribute ``trivial_abi`` has no effect in the following cases: + +- The class directly declares a virtual base or virtual methods. +- The class has a base class that is non-trivial for the purposes of calls. +- The class has a non-static data member whose type is non-trivial for the purposes of calls, which includes: + + - classes that are non-trivial for the purposes of calls + - __weak-qualified types in Objective-C++ + - arrays of any of the above + }]; +} + def MSInheritanceDocs : Documentation { let Category = DocCatType; let Heading = "__single_inhertiance, __multiple_inheritance, __virtual_inheritance"; @@ -2565,7 +2745,7 @@ The ``_Nullable`` nullability qualifier indicates that a value of the ``_Nullabl int fetch_or_zero(int * _Nullable ptr); -a caller of ``fetch_or_zero`` can provide null. +a caller of ``fetch_or_zero`` can provide null. }]; } @@ -2641,23 +2821,23 @@ used to process multiple arguments from a single invocation from a SIMD loop concurrently. The syntax of the `declare simd` construct is as follows: - .. code-block:: c + .. code-block:: none - #pragma omp declare simd [clause[[,] clause] ...] new-line - [#pragma omp declare simd [clause[[,] clause] ...] new-line] - [...] - function definition or declaration + #pragma omp declare simd [clause[[,] clause] ...] new-line + [#pragma omp declare simd [clause[[,] clause] ...] new-line] + [...] + function definition or declaration where clause is one of the following: - .. code-block:: c + .. code-block:: none - simdlen(length) - linear(argument-list[:constant-linear-step]) - aligned(argument-list[:alignment]) - uniform(argument-list) - inbranch - notinbranch + simdlen(length) + linear(argument-list[:constant-linear-step]) + aligned(argument-list[:alignment]) + uniform(argument-list) + inbranch + notinbranch }]; } @@ -2673,12 +2853,34 @@ The syntax of the declare target directive is as follows: .. code-block:: c - #pragma omp declare target new-line - declarations-definition-seq - #pragma omp end declare target new-line + #pragma omp declare target new-line + declarations-definition-seq + #pragma omp end declare target new-line }]; } +def NoStackProtectorDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +Clang supports the ``__attribute__((no_stack_protector))`` attribute which disables +the stack protector on the specified function. This attribute is useful for +selectively disabling the stack protector on some functions when building with +``-fstack-protector`` compiler option. + +For example, it disables the stack protector for the function ``foo`` but function +``bar`` will still be built with the stack protector with the ``-fstack-protector`` +option. + +.. code-block:: c + + int __attribute__((no_stack_protector)) + foo (int x); // stack protection will be disabled for foo. + + int bar(int y); // bar can be built with the stack protector. + + }]; +} + def NotTailCalledDocs : Documentation { let Category = DocCatFunction; let Content = [{ @@ -2737,7 +2939,7 @@ def NoThrowDocs : Documentation { let Category = DocCatFunction; let Content = [{ Clang supports the GNU style ``__attribute__((nothrow))`` and Microsoft style -``__declspec(nothrow)`` attribute as an equivilent of `noexcept` on function +``__declspec(nothrow)`` attribute as an equivalent of `noexcept` on function declarations. This attribute informs the compiler that the annotated function does not throw an exception. This prevents exception-unwinding. This attribute is particularly useful on functions in the C Standard Library that are @@ -2800,7 +3002,7 @@ Use this attribute to indicate that the specified function has no caller-saved registers. That is, all registers are callee-saved except for registers used for passing parameters to the function or returning parameters from the function. -The compiler saves and restores any modified registers that were not used for +The compiler saves and restores any modified registers that were not used for passing or returning arguments to the function. The user can call functions specified with the 'no_caller_saved_registers' @@ -2852,6 +3054,23 @@ jumps from i386 arch code). }]; } +def AnyX86NoCfCheckDocs : Documentation{ + let Category = DocCatFunction; + let Content = [{ +Jump Oriented Programming attacks rely on tampering with addresses used by +indirect call / jmp, e.g. redirect control-flow to non-programmer +intended bytes in the binary. +X86 Supports Indirect Branch Tracking (IBT) as part of Control-Flow +Enforcement Technology (CET). IBT instruments ENDBR instructions used to +specify valid targets of indirect call / jmp. +The ``nocf_check`` attribute has two roles: +1. Appertains to a function - do not add ENDBR instruction at the beginning of +the function. +2. Appertains to a function pointer - do not track the target function of this +pointer (by adding nocf_check prefix to the indirect-call instruction). +}]; +} + def SwiftCallDocs : Documentation { let Category = DocCatVariable; let Content = [{ @@ -3031,7 +3250,7 @@ the ability to distinguish between different versions of the same entity but with different ABI versions supported. For example, a newer version of a class could have a different set of data members and thus have a different size. Using the ``abi_tag`` attribute, it is possible to have different mangled names for -a global variable of the class type. Therefor, the old code could keep using +a global variable of the class type. Therefore, the old code could keep using the old manged name and the new code will use the new mangled name with tags. }]; } @@ -3213,3 +3432,13 @@ For more information see or `msvc documentation <https://docs.microsoft.com/pl-pl/cpp/cpp/selectany>`_. }]; } + +def ArtificialDocs : Documentation { + let Category = DocCatFunction; + let Content = [{ +The ``artificial`` attribute can be applied to an inline function. If such a +function is inlined, the attribute indicates that debuggers should associate +the resulting instructions with the call site, rather than with the +corresponding line within the inlined callee. + }]; +} diff --git a/include/clang/Basic/AttrKinds.h b/include/clang/Basic/AttrKinds.h index 8f7394f59d4d1..d82dbb032be97 100644 --- a/include/clang/Basic/AttrKinds.h +++ b/include/clang/Basic/AttrKinds.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::attr::Kind enum. +/// Defines the clang::attr::Kind enum. /// //===----------------------------------------------------------------------===// @@ -19,7 +19,7 @@ namespace clang { namespace attr { -// \brief A list of all the recognized kinds of attributes. +// A list of all the recognized kinds of attributes. enum Kind { #define ATTR(X) X, #define ATTR_RANGE(CLASS, FIRST_NAME, LAST_NAME) \ diff --git a/include/clang/Basic/AttrSubjectMatchRules.h b/include/clang/Basic/AttrSubjectMatchRules.h index 4c88adf57f17d..81aa634dfeb86 100644 --- a/include/clang/Basic/AttrSubjectMatchRules.h +++ b/include/clang/Basic/AttrSubjectMatchRules.h @@ -16,7 +16,7 @@ namespace clang { namespace attr { -/// \brief A list of all the recognized kinds of attributes. +/// A list of all the recognized kinds of attributes. enum SubjectMatchRule { #define ATTR_MATCH_RULE(X, Spelling, IsAbstract) X, #include "clang/Basic/AttrSubMatchRulesList.inc" diff --git a/include/clang/Basic/Attributes.h b/include/clang/Basic/Attributes.h index c651abacd482b..3152453694c9d 100644 --- a/include/clang/Basic/Attributes.h +++ b/include/clang/Basic/Attributes.h @@ -32,7 +32,7 @@ enum class AttrSyntax { Pragma }; -/// \brief Return the version number associated with the attribute if we +/// 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 TargetInfo &Target, diff --git a/include/clang/Basic/BitmaskEnum.h b/include/clang/Basic/BitmaskEnum.h new file mode 100644 index 0000000000000..12ff3cf207be3 --- /dev/null +++ b/include/clang/Basic/BitmaskEnum.h @@ -0,0 +1,25 @@ +//===--- BitmaskEnum.h - wrapper of LLVM's bitmask enum facility-*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Provides LLVM's BitmaskEnum facility to enumeration types declared in +/// namespace clang. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_BITMASKENUM_H +#define LLVM_CLANG_BASIC_BITMASKENUM_H + +#include "llvm/ADT/BitmaskEnum.h" + +namespace clang { + LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); +} + +#endif diff --git a/include/clang/Basic/Builtins.def b/include/clang/Basic/Builtins.def index 3d4deb5ed3064..edd823754a374 100644 --- a/include/clang/Basic/Builtins.def +++ b/include/clang/Basic/Builtins.def @@ -48,8 +48,8 @@ // . -> "...". This may only occur at the end of the function list. // // Types may be prefixed with the following modifiers: -// L -> long (e.g. Li for 'long int') -// LL -> long long +// L -> long (e.g. Li for 'long int', Ld for 'long double') +// LL -> long long (e.g. LLi for 'long long int', LLd for __float128) // LLL -> __int128_t (e.g. LLLi) // W -> int64_t // N -> 'int' size if target is LP64, 'L' otherwise. @@ -89,9 +89,10 @@ // S:N: -> similar to the s:N: attribute, but the function is like vscanf // in that it accepts its arguments as a va_list rather than // through an ellipsis -// e -> const, but only when -fmath-errno=0 +// e -> const, but only when -fno-math-errno // j -> returns_twice (like setjmp) // u -> arguments are not evaluated for their side-effects +// V:N: -> requires vectors of at least N bits to be legal // FIXME: gcc has nonnull #if defined(BUILTIN) && !defined(LIBBUILTIN) @@ -110,9 +111,11 @@ BUILTIN(__builtin_abs , "ii" , "ncF") BUILTIN(__builtin_copysign, "ddd", "ncF") BUILTIN(__builtin_copysignf, "fff", "ncF") BUILTIN(__builtin_copysignl, "LdLdLd", "ncF") +BUILTIN(__builtin_copysignf128, "LLdLLdLLd", "ncF") BUILTIN(__builtin_fabs , "dd" , "ncF") BUILTIN(__builtin_fabsf, "ff" , "ncF") BUILTIN(__builtin_fabsl, "LdLd", "ncF") +BUILTIN(__builtin_fabsf128, "LLdLLd", "ncF") BUILTIN(__builtin_fmod , "ddd" , "Fne") BUILTIN(__builtin_fmodf, "fff" , "Fne") BUILTIN(__builtin_fmodl, "LdLdLd", "Fne") @@ -122,9 +125,11 @@ BUILTIN(__builtin_frexpl, "LdLdi*", "Fn") BUILTIN(__builtin_huge_val, "d", "nc") BUILTIN(__builtin_huge_valf, "f", "nc") BUILTIN(__builtin_huge_vall, "Ld", "nc") +BUILTIN(__builtin_huge_valf128, "LLd", "nc") BUILTIN(__builtin_inf , "d" , "nc") BUILTIN(__builtin_inff , "f" , "nc") BUILTIN(__builtin_infl , "Ld" , "nc") +BUILTIN(__builtin_inff128 , "LLd" , "nc") BUILTIN(__builtin_labs , "LiLi" , "Fnc") BUILTIN(__builtin_llabs, "LLiLLi", "Fnc") BUILTIN(__builtin_ldexp , "ddi" , "Fne") @@ -133,12 +138,14 @@ BUILTIN(__builtin_ldexpl, "LdLdi", "Fne") BUILTIN(__builtin_modf , "ddd*" , "Fn") BUILTIN(__builtin_modff, "fff*" , "Fn") BUILTIN(__builtin_modfl, "LdLdLd*", "Fn") -BUILTIN(__builtin_nan, "dcC*" , "ncF") -BUILTIN(__builtin_nanf, "fcC*" , "ncF") -BUILTIN(__builtin_nanl, "LdcC*", "ncF") -BUILTIN(__builtin_nans, "dcC*" , "ncF") -BUILTIN(__builtin_nansf, "fcC*" , "ncF") -BUILTIN(__builtin_nansl, "LdcC*", "ncF") +BUILTIN(__builtin_nan, "dcC*" , "FnU") +BUILTIN(__builtin_nanf, "fcC*" , "FnU") +BUILTIN(__builtin_nanl, "LdcC*", "FnU") +BUILTIN(__builtin_nanf128, "LLdcC*", "FnU") +BUILTIN(__builtin_nans, "dcC*" , "FnU") +BUILTIN(__builtin_nansf, "fcC*" , "FnU") +BUILTIN(__builtin_nansl, "LdcC*", "FnU") +BUILTIN(__builtin_nansf128, "LLdcC*", "FnU") BUILTIN(__builtin_powi , "ddi" , "Fnc") BUILTIN(__builtin_powif, "ffi" , "Fnc") BUILTIN(__builtin_powil, "LdLdi", "Fnc") @@ -715,6 +722,10 @@ ATOMIC_BUILTIN(__opencl_atomic_fetch_xor, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_min, "v.", "t") ATOMIC_BUILTIN(__opencl_atomic_fetch_max, "v.", "t") +// GCC does not support these, they are a Clang extension. +ATOMIC_BUILTIN(__atomic_fetch_min, "v.", "t") +ATOMIC_BUILTIN(__atomic_fetch_max, "v.", "t") + #undef ATOMIC_BUILTIN // Non-overloaded atomic builtins. @@ -734,6 +745,14 @@ BUILTIN(__builtin_rindex, "c*cC*i", "Fn") LANGBUILTIN(_alloca, "v*z", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__annotation, "wC*.","n", ALL_MS_LANGUAGES) LANGBUILTIN(__assume, "vb", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittest, "UcNiC*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandcomplement, "UcNi*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandreset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandset, "UcNi*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittest64, "UcWiC*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandcomplement64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandreset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_bittestandset64, "UcWi*Wi", "n", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ushort, "UsUs", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_ulong, "UNiUNi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) LIBBUILTIN(_byteswap_uint64, "ULLiULLi", "fnc", "stdlib.h", ALL_MS_LANGUAGES) @@ -773,7 +792,16 @@ LANGBUILTIN(_InterlockedOr, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor8, "ccD*c", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor16, "ssD*s", "n", ALL_MS_LANGUAGES) LANGBUILTIN(_InterlockedXor, "NiNiD*Ni", "n", ALL_MS_LANGUAGES) -LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandreset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset64, "UcWiD*Wi", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset_acq, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset_nf, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(_interlockedbittestandset_rel, "UcNiD*Ni", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__noop, "i.", "n", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt16, "UsUs", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__popcnt, "UiUi", "nc", ALL_MS_LANGUAGES) @@ -796,6 +824,10 @@ LANGBUILTIN(__fastfail, "vUi", "nr", ALL_MS_LANGUAGES) LIBBUILTIN(_setjmpex, "iJ", "fj", "setjmpex.h", ALL_MS_LANGUAGES) // C99 library functions +// C99 stdarg.h +LIBBUILTIN(va_start, "vA.", "fn", "stdarg.h", ALL_LANGUAGES) +LIBBUILTIN(va_end, "vA", "fn", "stdarg.h", ALL_LANGUAGES) +LIBBUILTIN(va_copy, "vAA", "fn", "stdarg.h", ALL_LANGUAGES) // C99 stdlib.h LIBBUILTIN(abort, "v", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(calloc, "v*zz", "f", "stdlib.h", ALL_LANGUAGES) @@ -803,6 +835,13 @@ LIBBUILTIN(exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(_Exit, "vi", "fr", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(malloc, "v*z", "f", "stdlib.h", ALL_LANGUAGES) LIBBUILTIN(realloc, "v*v*z", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtod, "dcC*c**", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtof, "fcC*c**", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtold, "LdcC*c**", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtol, "LicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtoll, "LLicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtoul, "ULicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) +LIBBUILTIN(strtoull, "ULLicC*c**i", "f", "stdlib.h", ALL_LANGUAGES) // C99 string.h LIBBUILTIN(memcpy, "v*v*vC*z", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(memcmp, "ivC*vC*z", "f", "string.h", ALL_LANGUAGES) @@ -826,6 +865,7 @@ LIBBUILTIN(memset, "v*v*iz", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strerror, "c*i", "f", "string.h", ALL_LANGUAGES) LIBBUILTIN(strlen, "zcC*", "f", "string.h", ALL_LANGUAGES) // C99 stdio.h +// FIXME: This list is incomplete. LIBBUILTIN(printf, "icC*.", "fp:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(fprintf, "iP*cC*.", "fp:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(snprintf, "ic*zcC*.", "fp:2:", "stdio.h", ALL_LANGUAGES) @@ -840,6 +880,10 @@ LIBBUILTIN(sscanf, "icC*RcC*R.", "fs:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vscanf, "icC*Ra", "fS:0:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vfscanf, "iP*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) LIBBUILTIN(vsscanf, "icC*RcC*Ra", "fS:1:", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(fopen, "P*cC*cC*", "f", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(fread, "zv*zzP*", "f", "stdio.h", ALL_LANGUAGES) +LIBBUILTIN(fwrite, "zvC*zzP*", "f", "stdio.h", ALL_LANGUAGES) + // C99 ctype.h LIBBUILTIN(isalnum, "ii", "fnU", "ctype.h", ALL_LANGUAGES) LIBBUILTIN(isalpha, "ii", "fnU", "ctype.h", ALL_LANGUAGES) @@ -1361,12 +1405,15 @@ BUILTIN(__builtin_smulll_overflow, "bSLLiCSLLiCSLLi*", "n") // Clang builtins (not available in GCC). BUILTIN(__builtin_addressof, "v*v&", "nct") -BUILTIN(__builtin_operator_new, "v*z", "c") -BUILTIN(__builtin_operator_delete, "vv*", "n") +BUILTIN(__builtin_operator_new, "v*z", "tc") +BUILTIN(__builtin_operator_delete, "vv*", "tn") BUILTIN(__builtin_char_memchr, "c*cC*iz", "n") +BUILTIN(__builtin_dump_struct, "ivC*v*", "tn") // Safestack builtins BUILTIN(__builtin___get_unsafe_stack_start, "v*", "Fn") +BUILTIN(__builtin___get_unsafe_stack_bottom, "v*", "Fn") +BUILTIN(__builtin___get_unsafe_stack_top, "v*", "Fn") BUILTIN(__builtin___get_unsafe_stack_ptr, "v*", "Fn") // Nontemporal loads/stores builtins @@ -1381,6 +1428,7 @@ BUILTIN(__builtin_coro_promise, "v*v*IiIb", "n") BUILTIN(__builtin_coro_size, "z", "n") BUILTIN(__builtin_coro_frame, "v*", "n") +BUILTIN(__builtin_coro_noop, "v*", "n") BUILTIN(__builtin_coro_free, "v*v*", "n") BUILTIN(__builtin_coro_id, "v*Iiv*v*v*", "n") @@ -1443,6 +1491,7 @@ LANGBUILTIN(omp_is_initial_device, "i", "nc", OMP_LANG) // Builtins for XRay BUILTIN(__xray_customevent, "vcC*z", "") +BUILTIN(__xray_typedevent, "vzcC*z", "") // Win64-compatible va_list functions BUILTIN(__builtin_ms_va_start, "vc*&.", "nt") diff --git a/include/clang/Basic/Builtins.h b/include/clang/Basic/Builtins.h index 963c72ea82e0e..fa2bcc4c7ab0b 100644 --- a/include/clang/Basic/Builtins.h +++ b/include/clang/Basic/Builtins.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines enum values for all the target-independent builtin +/// Defines enum values for all the target-independent builtin /// functions. /// //===----------------------------------------------------------------------===// @@ -59,7 +59,7 @@ struct Info { const char *Features; }; -/// \brief Holds information about both target-independent and +/// Holds information about both target-independent and /// target-specific builtins, allowing easy queries by clients. /// /// Builtins from an optional auxiliary target are stored in @@ -72,122 +72,129 @@ class Context { public: Context() {} - /// \brief Perform target-specific initialization + /// Perform target-specific initialization /// \param AuxTarget Target info to incorporate builtins from. May be nullptr. void InitializeTarget(const TargetInfo &Target, const TargetInfo *AuxTarget); - /// \brief Mark the identifiers for all the builtins with their + /// Mark the identifiers for all the builtins with their /// appropriate builtin ID # and mark any non-portable builtin identifiers as /// such. void initializeBuiltins(IdentifierTable &Table, const LangOptions& LangOpts); - /// \brief Return the identifier name for the specified builtin, + /// Return the identifier name for the specified builtin, /// e.g. "__builtin_abs". const char *getName(unsigned ID) const { return getRecord(ID).Name; } - /// \brief Get the type descriptor string for the specified builtin. + /// Get the type descriptor string for the specified builtin. const char *getTypeString(unsigned ID) const { return getRecord(ID).Type; } - /// \brief Return true if this function is a target-specific builtin. + /// Return true if this function is a target-specific builtin. bool isTSBuiltin(unsigned ID) const { return ID >= Builtin::FirstTSBuiltin; } - /// \brief Return true if this function has no side effects. + /// Return true if this function has no side effects. bool isPure(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'U') != nullptr; } - /// \brief Return true if this function has no side effects and doesn't + /// Return true if this function has no side effects and doesn't /// read memory. bool isConst(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'c') != nullptr; } - /// \brief Return true if we know this builtin never throws an exception. + /// Return true if we know this builtin never throws an exception. bool isNoThrow(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'n') != nullptr; } - /// \brief Return true if we know this builtin never returns. + /// Return true if we know this builtin never returns. bool isNoReturn(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'r') != nullptr; } - /// \brief Return true if we know this builtin can return twice. + /// Return true if we know this builtin can return twice. bool isReturnsTwice(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'j') != nullptr; } - /// \brief Returns true if this builtin does not perform the side-effects + /// Returns true if this builtin does not perform the side-effects /// of its arguments. bool isUnevaluated(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'u') != nullptr; } - /// \brief Return true if this is a builtin for a libc/libm function, + /// Return true if this is a builtin for a libc/libm function, /// with a "__builtin_" prefix (e.g. __builtin_abs). bool isLibFunction(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'F') != nullptr; } - /// \brief Determines whether this builtin is a predefined libc/libm + /// Determines whether this builtin is a predefined libc/libm /// function, such as "malloc", where we know the signature a /// priori. bool isPredefinedLibFunction(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'f') != nullptr; } - /// \brief Returns true if this builtin requires appropriate header in other + /// Returns true if this builtin requires appropriate header in other /// compilers. In Clang it will work even without including it, but we can emit /// a warning about missing header. bool isHeaderDependentFunction(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'h') != nullptr; } - /// \brief Determines whether this builtin is a predefined compiler-rt/libgcc + /// Determines whether this builtin is a predefined compiler-rt/libgcc /// function, such as "__clear_cache", where we know the signature a /// priori. bool isPredefinedRuntimeFunction(unsigned ID) const { return strchr(getRecord(ID).Attributes, 'i') != nullptr; } - /// \brief Determines whether this builtin has custom typechecking. + /// Determines whether this builtin has custom typechecking. bool hasCustomTypechecking(unsigned ID) const { return strchr(getRecord(ID).Attributes, 't') != nullptr; } - /// \brief Determines whether this builtin has a result or any arguments which + /// Determines whether this builtin has a result or any arguments which /// are pointer types. bool hasPtrArgsOrResult(unsigned ID) const { return strchr(getRecord(ID).Type, '*') != nullptr; } - /// \brief Completely forget that the given ID was ever considered a builtin, + /// Return true if this builtin has a result or any arguments which are + /// reference types. + bool hasReferenceArgsOrResult(unsigned ID) const { + return strchr(getRecord(ID).Type, '&') != nullptr || + strchr(getRecord(ID).Type, 'A') != nullptr; + } + + /// Completely forget that the given ID was ever considered a builtin, /// e.g., because the user provided a conflicting signature. void forgetBuiltin(unsigned ID, IdentifierTable &Table); - /// \brief If this is a library function that comes from a specific + /// If this is a library function that comes from a specific /// header, retrieve that header name. const char *getHeaderName(unsigned ID) const { return getRecord(ID).HeaderName; } - /// \brief Determine whether this builtin is like printf in its + /// Determine whether this builtin is like printf in its /// formatting rules and, if so, set the index to the format string /// argument and whether this function as a va_list argument. bool isPrintfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); - /// \brief Determine whether this builtin is like scanf in its + /// Determine whether this builtin is like scanf in its /// formatting rules and, if so, set the index to the format string /// argument and whether this function as a va_list argument. bool isScanfLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg); - /// \brief Return true if this function has no side effects and doesn't + /// Return true if this function has no side effects and doesn't /// read memory, except for possibly errno. /// /// Such functions can be const when the MathErrno lang option is disabled. @@ -199,12 +206,14 @@ public: return getRecord(ID).Features; } - /// \brief Return true if builtin ID belongs to AuxTarget. + unsigned getRequiredVectorWidth(unsigned ID) const; + + /// Return true if builtin ID belongs to AuxTarget. bool isAuxBuiltinID(unsigned ID) const { return ID >= (Builtin::FirstTSBuiltin + TSRecords.size()); } - /// Return real buitin ID (i.e. ID it would have furing compilation + /// Return real builtin ID (i.e. ID it would have during compilation /// for AuxTarget). unsigned getAuxBuiltinID(unsigned ID) const { return ID - TSRecords.size(); } @@ -212,26 +221,30 @@ public: /// prefix. static bool isBuiltinFunc(const char *Name); + /// Returns true if this is a builtin that can be redeclared. Returns true + /// for non-builtins. + bool canBeRedeclared(unsigned ID) const; + private: const Info &getRecord(unsigned ID) const; - /// \brief Is this builtin supported according to the given language options? + /// Is this builtin supported according to the given language options? bool builtinIsSupported(const Builtin::Info &BuiltinInfo, const LangOptions &LangOpts); - /// \brief Helper function for isPrintfLike and isScanfLike. + /// Helper function for isPrintfLike and isScanfLike. bool isLike(unsigned ID, unsigned &FormatIdx, bool &HasVAListArg, const char *Fmt) const; }; } -/// \brief Kinds of BuiltinTemplateDecl. +/// Kinds of BuiltinTemplateDecl. enum BuiltinTemplateKind : int { - /// \brief This names the __make_integer_seq BuiltinTemplateDecl. + /// This names the __make_integer_seq BuiltinTemplateDecl. BTK__make_integer_seq, - /// \brief This names the __type_pack_element BuiltinTemplateDecl. + /// This names the __type_pack_element BuiltinTemplateDecl. BTK__type_pack_element }; diff --git a/include/clang/Basic/BuiltinsAArch64.def b/include/clang/Basic/BuiltinsAArch64.def index 55a4f70176d00..b5d971d0bc6e4 100644 --- a/include/clang/Basic/BuiltinsAArch64.def +++ b/include/clang/Basic/BuiltinsAArch64.def @@ -18,6 +18,10 @@ # define LANGBUILTIN(ID, TYPE, ATTRS, BUILTIN_LANG) BUILTIN(ID, TYPE, ATTRS) #endif +#if defined(BUILTIN) && !defined(TARGET_HEADER_BUILTIN) +# define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS) +#endif + // In libgcc BUILTIN(__clear_cache, "vv*v*", "i") @@ -65,9 +69,40 @@ BUILTIN(__builtin_arm_wsr, "vcC*Ui", "nc") BUILTIN(__builtin_arm_wsr64, "vcC*LUi", "nc") BUILTIN(__builtin_arm_wsrp, "vcC*vC*", "nc") +// MSVC LANGBUILTIN(__dmb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__dsb, "vUi", "nc", ALL_MS_LANGUAGES) LANGBUILTIN(__isb, "vUi", "nc", ALL_MS_LANGUAGES) +LANGBUILTIN(__yield, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfe, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__wfi, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sev, "v", "", ALL_MS_LANGUAGES) +LANGBUILTIN(__sevl, "v", "", ALL_MS_LANGUAGES) + +// MSVC intrinsics for volatile but non-acquire/release loads and stores +LANGBUILTIN(__iso_volatile_load8, "ccCD*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_load16, "ssCD*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_load32, "iiCD*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_load64, "LLiLLiCD*", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_store8, "vcD*c", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_store16, "vsD*s", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_store32, "viD*i", "n", ALL_MS_LANGUAGES) +LANGBUILTIN(__iso_volatile_store64, "vLLiD*LLi", "n", ALL_MS_LANGUAGES) + +TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_BitScanReverse, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_BitScanForward64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") + +TARGET_HEADER_BUILTIN(_InterlockedAnd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedDecrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchange64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangeAdd64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedExchangeSub64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedIncrement64, "LLiLLiD*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedOr64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_InterlockedXor64, "LLiLLiD*LLi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") #undef BUILTIN #undef LANGBUILTIN +#undef TARGET_HEADER_BUILTIN diff --git a/include/clang/Basic/BuiltinsAMDGPU.def b/include/clang/Basic/BuiltinsAMDGPU.def index ec6a0fb917657..46cd738ae43f6 100644 --- a/include/clang/Basic/BuiltinsAMDGPU.def +++ b/include/clang/Basic/BuiltinsAMDGPU.def @@ -21,9 +21,9 @@ // SI+ only builtins. //===----------------------------------------------------------------------===// -BUILTIN(__builtin_amdgcn_dispatch_ptr, "Uc*2", "nc") -BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "Uc*2", "nc") -BUILTIN(__builtin_amdgcn_implicitarg_ptr, "Uc*2", "nc") +BUILTIN(__builtin_amdgcn_dispatch_ptr, "Uc*4", "nc") +BUILTIN(__builtin_amdgcn_kernarg_segment_ptr, "Uc*4", "nc") +BUILTIN(__builtin_amdgcn_implicitarg_ptr, "Uc*4", "nc") BUILTIN(__builtin_amdgcn_workgroup_id_x, "Ui", "nc") BUILTIN(__builtin_amdgcn_workgroup_id_y, "Ui", "nc") @@ -93,6 +93,9 @@ BUILTIN(__builtin_amdgcn_ds_bpermute, "iii", "nc") BUILTIN(__builtin_amdgcn_readfirstlane, "ii", "nc") BUILTIN(__builtin_amdgcn_readlane, "iii", "nc") BUILTIN(__builtin_amdgcn_fmed3f, "ffff", "nc") +BUILTIN(__builtin_amdgcn_ds_faddf, "ff*fIiIiIb", "n") +BUILTIN(__builtin_amdgcn_ds_fminf, "ff*fIiIiIb", "n") +BUILTIN(__builtin_amdgcn_ds_fmaxf, "ff*fIiIiIb", "n") //===----------------------------------------------------------------------===// // VI+ only builtins. @@ -118,6 +121,18 @@ TARGET_BUILTIN(__builtin_amdgcn_mov_dpp, "iiIiIiIiIb", "nc", "dpp") TARGET_BUILTIN(__builtin_amdgcn_fmed3h, "hhhh", "nc", "gfx9-insts") //===----------------------------------------------------------------------===// +// Deep learning builtins. +//===----------------------------------------------------------------------===// + +TARGET_BUILTIN(__builtin_amdgcn_fdot2, "fV2hV2hf", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_sdot2, "SiV2SsV2SsSi", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_udot2, "UiV2UsV2UsUi", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_sdot4, "SiSiSiSi", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_udot4, "UiUiUiUi", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_sdot8, "SiSiSiSi", "nc", "dl-insts") +TARGET_BUILTIN(__builtin_amdgcn_udot8, "UiUiUiUi", "nc", "dl-insts") + +//===----------------------------------------------------------------------===// // Special builtins. //===----------------------------------------------------------------------===// BUILTIN(__builtin_amdgcn_read_exec, "LUi", "nc") diff --git a/include/clang/Basic/BuiltinsHexagon.def b/include/clang/Basic/BuiltinsHexagon.def index fda50b53589bd..f976720d116d0 100644 --- a/include/clang/Basic/BuiltinsHexagon.def +++ b/include/clang/Basic/BuiltinsHexagon.def @@ -17,28 +17,51 @@ // The builtins below are not autogenerated from iset.py. // Make sure you do not overwrite these. -BUILTIN(__builtin_brev_ldd, "LLi*LLi*LLi*i", "") -BUILTIN(__builtin_brev_ldw, "i*i*i*i", "") -BUILTIN(__builtin_brev_ldh, "s*s*s*i", "") -BUILTIN(__builtin_brev_lduh, "Us*Us*Us*i", "") -BUILTIN(__builtin_brev_ldb, "c*c*c*i", "") -BUILTIN(__builtin_brev_ldub, "Uc*Uc*Uc*i", "") +BUILTIN(__builtin_brev_ldd, "v*LLi*CLLi*iC", "") +BUILTIN(__builtin_brev_ldw, "v*i*Ci*iC", "") +BUILTIN(__builtin_brev_ldh, "v*s*Cs*iC", "") +BUILTIN(__builtin_brev_lduh, "v*Us*CUs*iC", "") +BUILTIN(__builtin_brev_ldb, "v*Sc*CSc*iC", "") +BUILTIN(__builtin_brev_ldub, "v*Uc*CUc*iC", "") BUILTIN(__builtin_circ_ldd, "LLi*LLi*LLi*iIi", "") BUILTIN(__builtin_circ_ldw, "i*i*i*iIi", "") BUILTIN(__builtin_circ_ldh, "s*s*s*iIi", "") BUILTIN(__builtin_circ_lduh, "Us*Us*Us*iIi", "") BUILTIN(__builtin_circ_ldb, "c*c*c*iIi", "") BUILTIN(__builtin_circ_ldub, "Uc*Uc*Uc*iIi", "") -BUILTIN(__builtin_brev_std, "LLi*LLi*LLii", "") -BUILTIN(__builtin_brev_stw, "i*i*ii", "") -BUILTIN(__builtin_brev_sth, "s*s*ii", "") -BUILTIN(__builtin_brev_sthhi, "s*s*ii", "") -BUILTIN(__builtin_brev_stb, "c*c*ii", "") +BUILTIN(__builtin_brev_std, "LLi*CLLi*LLiiC", "") +BUILTIN(__builtin_brev_stw, "i*Ci*iiC", "") +BUILTIN(__builtin_brev_sth, "s*Cs*iiC", "") +BUILTIN(__builtin_brev_sthhi, "s*Cs*iiC", "") +BUILTIN(__builtin_brev_stb, "c*Cc*iiC", "") BUILTIN(__builtin_circ_std, "LLi*LLi*LLiiIi", "") BUILTIN(__builtin_circ_stw, "i*i*iiIi", "") BUILTIN(__builtin_circ_sth, "s*s*iiIi", "") BUILTIN(__builtin_circ_sthhi, "s*s*iiIi", "") BUILTIN(__builtin_circ_stb, "c*c*iiIi", "") +BUILTIN(__builtin_HEXAGON_L2_loadrub_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrb_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadruh_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrh_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadri_pci, "iv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrd_pci, "LLiv*IiivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrub_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrb_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadruh_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrh_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadri_pcr, "iv*ivC*", "") +BUILTIN(__builtin_HEXAGON_L2_loadrd_pcr, "LLiv*ivC*", "") + +BUILTIN(__builtin_HEXAGON_S2_storerb_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerh_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerf_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storeri_pci, "vv*IiiivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerd_pci, "vv*IiiLLivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerb_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerh_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerf_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storeri_pcr, "vv*iivC*", "") +BUILTIN(__builtin_HEXAGON_S2_storerd_pcr, "vv*iLLivC*", "") // The builtins above are not autogenerated from iset.py. // Make sure you do not overwrite these. diff --git a/include/clang/Basic/BuiltinsNEON.def b/include/clang/Basic/BuiltinsNEON.def index 7800ae69c4c96..241b93a915a94 100644 --- a/include/clang/Basic/BuiltinsNEON.def +++ b/include/clang/Basic/BuiltinsNEON.def @@ -16,6 +16,7 @@ #define GET_NEON_BUILTINS #include "clang/Basic/arm_neon.inc" +#include "clang/Basic/arm_fp16.inc" #undef GET_NEON_BUILTINS #undef BUILTIN diff --git a/include/clang/Basic/BuiltinsNVPTX.def b/include/clang/Basic/BuiltinsNVPTX.def index 7bab73a3b110c..08c60979779b7 100644 --- a/include/clang/Basic/BuiltinsNVPTX.def +++ b/include/clang/Basic/BuiltinsNVPTX.def @@ -18,6 +18,19 @@ # define TARGET_BUILTIN(ID, TYPE, ATTRS, FEATURE) BUILTIN(ID, TYPE, ATTRS) #endif +#pragma push_macro("SM_70") +#define SM_70 "sm_70|sm_71" +#pragma push_macro("SM_60") +#define SM_60 "sm_60|sm_61|sm_62|" SM_70 + +#pragma push_macro("PTX61") +#define PTX61 "ptx61" +#pragma push_macro("PTX60") +#define PTX60 "ptx60|" PTX61 + +#pragma push_macro("AND") +#define AND(a, b) a "," b + // Special Registers BUILTIN(__nvvm_read_ptx_sreg_tid_x, "i", "nc") @@ -372,7 +385,7 @@ BUILTIN(__nvvm_bitcast_ll2d, "dLLi", "") BUILTIN(__nvvm_bitcast_d2ll, "LLid", "") // FNS -TARGET_BUILTIN(__nvvm_fns, "UiUiUii", "n", "ptx60") +TARGET_BUILTIN(__nvvm_fns, "UiUiUii", "n", PTX60) // Sync @@ -381,9 +394,9 @@ BUILTIN(__nvvm_bar0_popc, "ii", "") BUILTIN(__nvvm_bar0_and, "ii", "") BUILTIN(__nvvm_bar0_or, "ii", "") BUILTIN(__nvvm_bar_sync, "vi", "n") -TARGET_BUILTIN(__nvvm_bar_warp_sync, "vUi", "n", "ptx60") -TARGET_BUILTIN(__nvvm_barrier_sync, "vUi", "n", "ptx60") -TARGET_BUILTIN(__nvvm_barrier_sync_cnt, "vUiUi", "n", "ptx60") +TARGET_BUILTIN(__nvvm_bar_warp_sync, "vUi", "n", PTX60) +TARGET_BUILTIN(__nvvm_barrier_sync, "vUi", "n", PTX60) +TARGET_BUILTIN(__nvvm_barrier_sync_cnt, "vUiUi", "n", PTX60) // Shuffle @@ -396,14 +409,14 @@ BUILTIN(__nvvm_shfl_bfly_f32, "ffii", "") BUILTIN(__nvvm_shfl_idx_i32, "iiii", "") BUILTIN(__nvvm_shfl_idx_f32, "ffii", "") -TARGET_BUILTIN(__nvvm_shfl_sync_down_i32, "iUiiii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_down_f32, "fUifii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_up_i32, "iUiiii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_up_f32, "fUifii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_bfly_i32, "iUiiii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_bfly_f32, "fUifii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_idx_i32, "iUiiii", "", "ptx60") -TARGET_BUILTIN(__nvvm_shfl_sync_idx_f32, "fUifii", "", "ptx60") +TARGET_BUILTIN(__nvvm_shfl_sync_down_i32, "iUiiii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_down_f32, "fUifii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_up_i32, "iUiiii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_up_f32, "fUifii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_bfly_i32, "iUiiii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_bfly_f32, "fUifii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_idx_i32, "iUiiii", "", PTX60) +TARGET_BUILTIN(__nvvm_shfl_sync_idx_f32, "fUifii", "", PTX60) // Vote BUILTIN(__nvvm_vote_all, "bb", "") @@ -411,17 +424,17 @@ BUILTIN(__nvvm_vote_any, "bb", "") BUILTIN(__nvvm_vote_uni, "bb", "") BUILTIN(__nvvm_vote_ballot, "Uib", "") -TARGET_BUILTIN(__nvvm_vote_all_sync, "bUib", "", "ptx60") -TARGET_BUILTIN(__nvvm_vote_any_sync, "bUib", "", "ptx60") -TARGET_BUILTIN(__nvvm_vote_uni_sync, "bUib", "", "ptx60") -TARGET_BUILTIN(__nvvm_vote_ballot_sync, "UiUib", "", "ptx60") +TARGET_BUILTIN(__nvvm_vote_all_sync, "bUib", "", PTX60) +TARGET_BUILTIN(__nvvm_vote_any_sync, "bUib", "", PTX60) +TARGET_BUILTIN(__nvvm_vote_uni_sync, "bUib", "", PTX60) +TARGET_BUILTIN(__nvvm_vote_ballot_sync, "UiUib", "", PTX60) // Match -TARGET_BUILTIN(__nvvm_match_any_sync_i32, "UiUiUi", "", "ptx60") -TARGET_BUILTIN(__nvvm_match_any_sync_i64, "WiUiWi", "", "ptx60") +TARGET_BUILTIN(__nvvm_match_any_sync_i32, "UiUiUi", "", PTX60) +TARGET_BUILTIN(__nvvm_match_any_sync_i64, "WiUiWi", "", PTX60) // These return a pair {value, predicate}, which requires custom lowering. -TARGET_BUILTIN(__nvvm_match_all_sync_i32p, "UiUiUii*", "", "ptx60") -TARGET_BUILTIN(__nvvm_match_all_sync_i64p, "WiUiWii*", "", "ptx60") +TARGET_BUILTIN(__nvvm_match_all_sync_i32p, "UiUiUii*", "", PTX60) +TARGET_BUILTIN(__nvvm_match_all_sync_i64p, "WiUiWii*", "", PTX60) // Membar @@ -462,194 +475,120 @@ BUILTIN(__builtin_ptx_get_image_channel_orderi_, "ii", "") // - they are used in address space analysis and optimization // So it does not hurt to expose them as builtins. // -BUILTIN(__nvvm_atom_add_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_add_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_add_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_add_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_add_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_add_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_add_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_add_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_add_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_add_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_add_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_add_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_add_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_add_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_add_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_add_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_add_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_add_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_add_gen_ll, "LLiLLiD*LLi", "n", "satom") -BUILTIN(__nvvm_atom_add_g_f, "ffD*1f", "n") -BUILTIN(__nvvm_atom_add_s_f, "ffD*3f", "n") +TARGET_BUILTIN(__nvvm_atom_cta_add_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_add_gen_ll, "LLiLLiD*LLi", "n", SM_60) BUILTIN(__nvvm_atom_add_gen_f, "ffD*f", "n") -TARGET_BUILTIN(__nvvm_atom_cta_add_gen_f, "ffD*f", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_add_gen_f, "ffD*f", "n", "satom") -BUILTIN(__nvvm_atom_add_g_d, "ddD*1d", "n") -BUILTIN(__nvvm_atom_add_s_d, "ddD*3d", "n") -TARGET_BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_cta_add_gen_d, "ddD*d", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_add_gen_d, "ddD*d", "n", "satom") - -BUILTIN(__nvvm_atom_sub_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_sub_s_i, "iiD*3i", "n") +TARGET_BUILTIN(__nvvm_atom_cta_add_gen_f, "ffD*f", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_add_gen_f, "ffD*f", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_add_gen_d, "ddD*d", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_cta_add_gen_d, "ddD*d", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_add_gen_d, "ddD*d", "n", SM_60) + BUILTIN(__nvvm_atom_sub_gen_i, "iiD*i", "n") -BUILTIN(__nvvm_atom_sub_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_sub_s_l, "LiLiD*3Li", "n") BUILTIN(__nvvm_atom_sub_gen_l, "LiLiD*Li", "n") -BUILTIN(__nvvm_atom_sub_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_sub_s_ll, "LLiLLiD*3LLi", "n") BUILTIN(__nvvm_atom_sub_gen_ll, "LLiLLiD*LLi", "n") -BUILTIN(__nvvm_atom_xchg_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_xchg_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_xchg_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_xchg_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_xchg_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_xchg_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_xchg_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_xchg_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_xchg_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_ll, "LLiLLiD*LLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_xchg_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_xchg_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_max_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_max_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_max_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_max_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_max_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_max_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_max_s_ui, "UiUiD*3Ui", "n") +TARGET_BUILTIN(__nvvm_atom_cta_max_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_max_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_max_gen_ui, "UiUiD*Ui", "n") -TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ui, "UiUiD*Ui", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ui, "UiUiD*Ui", "n", "satom") -BUILTIN(__nvvm_atom_max_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_max_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ui, "UiUiD*Ui", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ui, "UiUiD*Ui", "n", SM_60) BUILTIN(__nvvm_atom_max_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_max_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_max_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_max_g_ul, "ULiULiD*1ULi", "n") -BUILTIN(__nvvm_atom_max_s_ul, "ULiULiD*3ULi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_max_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_max_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_max_gen_ul, "ULiULiD*ULi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ul, "ULiULiD*ULi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ul, "ULiULiD*ULi", "n", "satom") -BUILTIN(__nvvm_atom_max_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_max_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ul, "ULiULiD*ULi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ul, "ULiULiD*ULi", "n", SM_60) BUILTIN(__nvvm_atom_max_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ll, "LLiLLiD*LLi", "n", "satom") -BUILTIN(__nvvm_atom_max_g_ull, "ULLiULLiD*1ULLi", "n") -BUILTIN(__nvvm_atom_max_s_ull, "ULLiULLiD*3ULLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ll, "LLiLLiD*LLi", "n", SM_60) BUILTIN(__nvvm_atom_max_gen_ull, "ULLiULLiD*ULLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ull, "ULLiULLiD*ULLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ull, "ULLiULLiD*ULLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_max_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_max_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) -BUILTIN(__nvvm_atom_min_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_min_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_min_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_min_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_min_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_min_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_min_s_ui, "UiUiD*3Ui", "n") +TARGET_BUILTIN(__nvvm_atom_cta_min_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_min_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_min_gen_ui, "UiUiD*Ui", "n") -TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ui, "UiUiD*Ui", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ui, "UiUiD*Ui", "n", "satom") -BUILTIN(__nvvm_atom_min_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_min_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ui, "UiUiD*Ui", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ui, "UiUiD*Ui", "n", SM_60) BUILTIN(__nvvm_atom_min_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_min_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_min_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_min_g_ul, "ULiULiD*1ULi", "n") -BUILTIN(__nvvm_atom_min_s_ul, "ULiULiD*3ULi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_min_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_min_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_min_gen_ul, "ULiULiD*ULi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ul, "ULiULiD*ULi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ul, "ULiULiD*ULi", "n", "satom") -BUILTIN(__nvvm_atom_min_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_min_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ul, "ULiULiD*ULi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ul, "ULiULiD*ULi", "n", SM_60) BUILTIN(__nvvm_atom_min_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ll, "LLiLLiD*LLi", "n", "satom") -BUILTIN(__nvvm_atom_min_g_ull, "ULLiULLiD*1ULLi", "n") -BUILTIN(__nvvm_atom_min_s_ull, "ULLiULLiD*3ULLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ll, "LLiLLiD*LLi", "n", SM_60) BUILTIN(__nvvm_atom_min_gen_ull, "ULLiULLiD*ULLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ull, "ULLiULLiD*ULLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ull, "ULLiULLiD*ULLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_min_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_min_gen_ull, "ULLiULLiD*ULLi", "n", SM_60) -BUILTIN(__nvvm_atom_inc_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_inc_s_ui, "UiUiD*3Ui", "n") BUILTIN(__nvvm_atom_inc_gen_ui, "UiUiD*Ui", "n") -TARGET_BUILTIN(__nvvm_atom_cta_inc_gen_ui, "UiUiD*Ui", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_inc_gen_ui, "UiUiD*Ui", "n", "satom") -BUILTIN(__nvvm_atom_dec_g_ui, "UiUiD*1Ui", "n") -BUILTIN(__nvvm_atom_dec_s_ui, "UiUiD*3Ui", "n") +TARGET_BUILTIN(__nvvm_atom_cta_inc_gen_ui, "UiUiD*Ui", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_inc_gen_ui, "UiUiD*Ui", "n", SM_60) BUILTIN(__nvvm_atom_dec_gen_ui, "UiUiD*Ui", "n") -TARGET_BUILTIN(__nvvm_atom_cta_dec_gen_ui, "UiUiD*Ui", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_dec_gen_ui, "UiUiD*Ui", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_dec_gen_ui, "UiUiD*Ui", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_dec_gen_ui, "UiUiD*Ui", "n", SM_60) -BUILTIN(__nvvm_atom_and_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_and_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_and_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_and_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_and_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_and_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_and_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_and_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_and_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_and_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_and_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_and_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_and_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_and_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_and_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_and_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_and_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_and_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_and_gen_ll, "LLiLLiD*LLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_and_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_and_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_or_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_or_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_or_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_or_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_or_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_or_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_or_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_or_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_or_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_or_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_or_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_or_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_or_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_or_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_or_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_or_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_or_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_or_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_or_gen_ll, "LLiLLiD*LLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_or_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_or_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_xor_g_i, "iiD*1i", "n") -BUILTIN(__nvvm_atom_xor_s_i, "iiD*3i", "n") BUILTIN(__nvvm_atom_xor_gen_i, "iiD*i", "n") -TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_i, "iiD*i", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_i, "iiD*i", "n", "satom") -BUILTIN(__nvvm_atom_xor_g_l, "LiLiD*1Li", "n") -BUILTIN(__nvvm_atom_xor_s_l, "LiLiD*3Li", "n") +TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_i, "iiD*i", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_i, "iiD*i", "n", SM_60) BUILTIN(__nvvm_atom_xor_gen_l, "LiLiD*Li", "n") -TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_l, "LiLiD*Li", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_l, "LiLiD*Li", "n", "satom") -BUILTIN(__nvvm_atom_xor_g_ll, "LLiLLiD*1LLi", "n") -BUILTIN(__nvvm_atom_xor_s_ll, "LLiLLiD*3LLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_l, "LiLiD*Li", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_l, "LiLiD*Li", "n", SM_60) BUILTIN(__nvvm_atom_xor_gen_ll, "LLiLLiD*LLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_ll, "LLiLLiD*LLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_ll, "LLiLLiD*LLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_xor_gen_ll, "LLiLLiD*LLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_xor_gen_ll, "LLiLLiD*LLi", "n", SM_60) -BUILTIN(__nvvm_atom_cas_g_i, "iiD*1ii", "n") -BUILTIN(__nvvm_atom_cas_s_i, "iiD*3ii", "n") BUILTIN(__nvvm_atom_cas_gen_i, "iiD*ii", "n") -TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_i, "iiD*ii", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_i, "iiD*ii", "n", "satom") -BUILTIN(__nvvm_atom_cas_g_l, "LiLiD*1LiLi", "n") -BUILTIN(__nvvm_atom_cas_s_l, "LiLiD*3LiLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_i, "iiD*ii", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_i, "iiD*ii", "n", SM_60) BUILTIN(__nvvm_atom_cas_gen_l, "LiLiD*LiLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_l, "LiLiD*LiLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_l, "LiLiD*LiLi", "n", "satom") -BUILTIN(__nvvm_atom_cas_g_ll, "LLiLLiD*1LLiLLi", "n") -BUILTIN(__nvvm_atom_cas_s_ll, "LLiLLiD*3LLiLLi", "n") +TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_l, "LiLiD*LiLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_l, "LiLiD*LiLi", "n", SM_60) BUILTIN(__nvvm_atom_cas_gen_ll, "LLiLLiD*LLiLLi", "n") -TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_ll, "LLiLLiD*LLiLLi", "n", "satom") -TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_ll, "LLiLLiD*LLiLLi", "n", "satom") +TARGET_BUILTIN(__nvvm_atom_cta_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60) +TARGET_BUILTIN(__nvvm_atom_sys_cas_gen_ll, "LLiLLiD*LLiLLi", "n", SM_60) // Compiler Error Warn BUILTIN(__nvvm_compiler_error, "vcC*4", "n") @@ -692,17 +631,46 @@ BUILTIN(__nvvm_ldg_f4, "E4fE4fC*", "") BUILTIN(__nvvm_ldg_d2, "E2dE2dC*", "") // Builtins to support WMMA instructions on sm_70 -TARGET_BUILTIN(__hmma_m16n16k16_ld_a, "vi*iC*UiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_ld_b, "vi*iC*UiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f16, "vi*iC*UiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f32, "vf*fC*UiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_st_c_f16, "vi*i*UiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_st_c_f32, "vf*f*UiIi", "", "ptx60") - -TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", "ptx60") -TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", "ptx60") +TARGET_BUILTIN(__hmma_m16n16k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_ld_b, "vi*iC*UiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f16, "vi*iC*UiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_ld_c_f32, "vf*fC*UiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_st_c_f16, "vi*i*UiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_st_c_f32, "vf*f*UiIi", "", AND(SM_70,PTX60)) + +TARGET_BUILTIN(__hmma_m32n8k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_ld_b, "vi*iC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_ld_c_f16, "vi*iC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_ld_c_f32, "vf*fC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_st_c_f16, "vi*i*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_st_c_f32, "vf*f*UiIi", "", AND(SM_70,PTX61)) + +TARGET_BUILTIN(__hmma_m8n32k16_ld_a, "vi*iC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_ld_b, "vi*iC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_ld_c_f16, "vi*iC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_ld_c_f32, "vf*fC*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_st_c_f16, "vi*i*UiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_st_c_f32, "vf*f*UiIi", "", AND(SM_70,PTX61)) + +TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", AND(SM_70,PTX60)) +TARGET_BUILTIN(__hmma_m16n16k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX60)) + +TARGET_BUILTIN(__hmma_m32n8k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m32n8k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX61)) + +TARGET_BUILTIN(__hmma_m8n32k16_mma_f16f16, "vi*iC*iC*iC*IiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_mma_f32f16, "vf*iC*iC*iC*IiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_mma_f32f32, "vf*iC*iC*fC*IiIi", "", AND(SM_70,PTX61)) +TARGET_BUILTIN(__hmma_m8n32k16_mma_f16f32, "vi*iC*iC*fC*IiIi", "", AND(SM_70,PTX61)) #undef BUILTIN #undef TARGET_BUILTIN +#pragma pop_macro("AND") +#pragma pop_macro("SM_60") +#pragma pop_macro("SM_70") +#pragma pop_macro("PTX60") +#pragma pop_macro("PTX61") diff --git a/include/clang/Basic/BuiltinsPPC.def b/include/clang/Basic/BuiltinsPPC.def index faa70a48edc3c..8cd8a2be20030 100644 --- a/include/clang/Basic/BuiltinsPPC.def +++ b/include/clang/Basic/BuiltinsPPC.def @@ -423,6 +423,15 @@ BUILTIN(__builtin_vsx_extractuword, "V2ULLiV16UcIi", "") BUILTIN(__builtin_vsx_xxpermdi, "v.", "t") BUILTIN(__builtin_vsx_xxsldwi, "v.", "t") +// Float 128 built-ins +BUILTIN(__builtin_sqrtf128_round_to_odd, "LLdLLd", "") +BUILTIN(__builtin_addf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_subf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_mulf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_divf128_round_to_odd, "LLdLLdLLd", "") +BUILTIN(__builtin_fmaf128_round_to_odd, "LLdLLdLLdLLd", "") +BUILTIN(__builtin_truncf128_round_to_odd, "dLLd", "") + // HTM builtins BUILTIN(__builtin_tbegin, "UiUIi", "") BUILTIN(__builtin_tend, "UiUIi", "") diff --git a/include/clang/Basic/BuiltinsWebAssembly.def b/include/clang/Basic/BuiltinsWebAssembly.def index 19318dcebb9ec..b3d877dcedf38 100644 --- a/include/clang/Basic/BuiltinsWebAssembly.def +++ b/include/clang/Basic/BuiltinsWebAssembly.def @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines the WebAssembly-specific builtin function database. +/// This file defines the WebAssembly-specific builtin function database. /// Users of this file must define the BUILTIN macro to make use of this /// information. /// @@ -16,8 +16,17 @@ // The format of this database matches clang/Basic/Builtins.def. -// Note that current_memory is not "c" (readnone) because it must be sequenced -// with respect to grow_memory calls. +// Query the current memory size, and increase the current memory size. +// Note that memory.size is not "c" (readnone) because it must be sequenced +// with respect to memory.grow calls. +BUILTIN(__builtin_wasm_memory_size, "zIi", "n") +BUILTIN(__builtin_wasm_memory_grow, "zIiz", "n") + +// These are the old names. +BUILTIN(__builtin_wasm_mem_size, "zIi", "n") +BUILTIN(__builtin_wasm_mem_grow, "zIiz", "n") + +// These are the old old names. They also lack the immediate field. BUILTIN(__builtin_wasm_current_memory, "z", "n") BUILTIN(__builtin_wasm_grow_memory, "zz", "n") diff --git a/include/clang/Basic/BuiltinsX86.def b/include/clang/Basic/BuiltinsX86.def index 465551be77427..e98f7d612c3c6 100644 --- a/include/clang/Basic/BuiltinsX86.def +++ b/include/clang/Basic/BuiltinsX86.def @@ -27,8 +27,6 @@ # define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANG, FEATURE) BUILTIN(ID, TYPE, ATTRS) #endif -// FIXME: Are these nothrow/const? - // Miscellaneous builtin for checking x86 cpu features. // TODO: Make this somewhat generic so that other backends // can use it? @@ -38,9 +36,9 @@ BUILTIN(__builtin_cpu_is, "bcC*", "nc") // Undefined Values // -TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "nc", "") -TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "nc", "") -TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "nc", "") +TARGET_BUILTIN(__builtin_ia32_undef128, "V2d", "ncV:128:", "") +TARGET_BUILTIN(__builtin_ia32_undef256, "V4d", "ncV:256:", "") +TARGET_BUILTIN(__builtin_ia32_undef512, "V8d", "ncV:512:", "") // FLAGS // @@ -49,33 +47,33 @@ TARGET_BUILTIN(__builtin_ia32_writeeflags_u32, "vUi", "n", "") // 3DNow! // -TARGET_BUILTIN(__builtin_ia32_femms, "v", "", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "nc", "3dnow") -TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "nc", "3dnow") +TARGET_BUILTIN(__builtin_ia32_femms, "v", "n", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pavgusb, "V8cV8cV8c", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pf2id, "V2iV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfacc, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfadd, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfcmpeq, "V2iV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfcmpge, "V2iV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfcmpgt, "V2iV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfmax, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfmin, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfmul, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrcp, "V2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrcpit1, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrcpit2, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrsqrt, "V2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfrsqit1, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfsub, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pfsubr, "V2fV2fV2f", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pi2fd, "V2fV2i", "ncV:64:", "3dnow") +TARGET_BUILTIN(__builtin_ia32_pmulhrw, "V4sV4sV4s", "ncV:64:", "3dnow") // 3DNow! Extensions (3dnowa). -TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "nc", "3dnowa") -TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pf2iw, "V2iV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pfnacc, "V2fV2fV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pfpnacc, "V2fV2fV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pi2fw, "V2fV2i", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pswapdsf, "V2fV2f", "ncV:64:", "3dnowa") +TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "ncV:64:", "3dnowa") // MMX // @@ -86,1808 +84,1758 @@ TARGET_BUILTIN(__builtin_ia32_pswapdsi, "V2iV2i", "nc", "3dnowa") // argument and our prior approach of using a #define to the current built-in // doesn't work in the presence of re-declaration of _mm_prefetch for windows. TARGET_BUILTIN(_mm_prefetch, "vcC*i", "nc", "mmx") -TARGET_BUILTIN(__builtin_ia32_emms, "v", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "", "mmx") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "", "mmx") +TARGET_BUILTIN(__builtin_ia32_emms, "v", "n", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddsb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddsw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddusb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_paddusw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubsb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubsw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubusb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psubusw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pmulhw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pmullw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pmaddwd, "V2iV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pand, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pandn, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_por, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pxor, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllw, "V4sV4sV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pslld, "V2iV2iV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlw, "V4sV4sV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrld, "V2iV2iV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psraw, "V4sV4sV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrad, "V2iV2iV1LLi", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllwi, "V4sV4si", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pslldi, "V2iV2ii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psllqi, "V1LLiV1LLii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlwi, "V4sV4si", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrldi, "V2iV2ii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrlqi, "V1LLiV1LLii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psrawi, "V4sV4si", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_psradi, "V2iV2ii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_packsswb, "V8cV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_packssdw, "V4sV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_packuswb, "V8cV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckhbw, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckhwd, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckhdq, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpcklbw, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpcklwd, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_punpckldq, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpeqb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpeqw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpeqd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpgtb, "V8cV8cV8c", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpgtw, "V4sV4sV4s", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_pcmpgtd, "V2iV2iV2i", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_maskmovq, "vV8cV8cc*", "nV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_movntq, "vV1LLi*V1LLi", "nV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_init_v2si, "V2iii", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_init_v4hi, "V4sssss", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_init_v8qi, "V8ccccccccc", "ncV:64:", "mmx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2si, "iV2ii", "ncV:64:", "mmx") // MMX2 (MMX+SSE) intrinsics -TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "", "sse") -TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "", "sse") -TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "", "sse") -TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "", "sse") -TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "", "sse") +TARGET_BUILTIN(__builtin_ia32_cvtpi2ps, "V4fV4fV2i", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvtps2pi, "V2iV4f", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_cvttps2pi, "V2iV4f", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pavgb, "V8cV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pavgw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmaxsw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmaxub, "V8cV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pminsw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pminub, "V8cV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmovmskb, "iV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pmulhuw, "V4sV4sV4s", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_psadbw, "V4sV8cV8c", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_pshufw, "V4sV4sIc", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4hi, "iV4sIi", "ncV:64:", "mmx,sse") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4hi, "V4sV4siIi", "ncV:64:", "mmx,sse") // MMX+SSE2 -TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2pi, "V2iV2d", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpi2pd, "V2dV2i", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_cvttpd2pi, "V2iV2d", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_paddq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_pmuludq, "V1LLiV2iV2i", "ncV:64:", "mmx,sse2") +TARGET_BUILTIN(__builtin_ia32_psubq, "V1LLiV1LLiV1LLi", "ncV:64:", "mmx,sse2") // MMX+SSSE3 -TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsb, "V8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsd, "V2iV2i", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsw, "V4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_palignr, "V8cV8cV8cIc", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw, "V8cV8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_pshufb, "V8cV8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignw, "V4sV4sV4s", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignb, "V8cV8cV8c", "ncV:64:", "mmx,ssse3") +TARGET_BUILTIN(__builtin_ia32_psignd, "V2iV2iV2i", "ncV:64:", "mmx,ssse3") // SSE intrinsics. -TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "", "sse") - -TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "", "sse2") - -TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "", "sse") - -TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "", "sse2") - -TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "", "ssse3") -TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "", "ssse3") - -TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "", "sse") -TARGET_HEADER_BUILTIN(_mm_setcsr, "vUi", "h","xmmintrin.h", ALL_LANGUAGES, "sse") -TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "", "sse") -TARGET_HEADER_BUILTIN(_mm_getcsr, "Ui", "h", "xmmintrin.h", ALL_LANGUAGES, "sse") -TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_sfence, "v", "", "sse") -TARGET_HEADER_BUILTIN(_mm_sfence, "v", "h", "xmmintrin.h", ALL_LANGUAGES, "sse") -TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "", "sse") - -TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtdq2ps, "V4fV4i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "", "sse2") -TARGET_HEADER_BUILTIN(_mm_clflush, "vvC*", "h", "emmintrin.h", ALL_LANGUAGES, "sse2") -TARGET_BUILTIN(__builtin_ia32_lfence, "v", "", "sse2") -TARGET_HEADER_BUILTIN(_mm_lfence, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2") -TARGET_BUILTIN(__builtin_ia32_mfence, "v", "", "sse2") -TARGET_HEADER_BUILTIN(_mm_mfence, "v", "h", "emmintrin.h", ALL_LANGUAGES, "sse2") -TARGET_BUILTIN(__builtin_ia32_pause, "v", "", "") -TARGET_HEADER_BUILTIN(_mm_pause, "v", "h", "emmintrin.h", ALL_LANGUAGES, "") -TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "", "sse2") - -TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "", "sse3") -TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "", "sse3") - -TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "", "ssse3") - -TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "", "sse4.1") - -TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "", "sse4.1") -TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_comieq, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comilt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comile, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comigt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comige, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_comineq, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomieq, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomilt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomile, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomigt, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomige, "iV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_ucomineq, "iV4fV4f", "ncV:128:", "sse") + +TARGET_BUILTIN(__builtin_ia32_comisdeq, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdlt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdle, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdgt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdge, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_comisdneq, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdeq, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdlt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdle, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdgt, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdge, "iV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_ucomisdneq, "iV2dV2d", "ncV:128:", "sse2") + +TARGET_BUILTIN(__builtin_ia32_cmpeqps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpltps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpleps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpunordps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpneqps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnltps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnleps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpordps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpeqss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpltss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpless, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpunordss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpneqss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnltss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpnless, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cmpordss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_minps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_maxps, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_minss, "V4fV4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_maxss, "V4fV4fV4f", "ncV:128:", "sse") + +TARGET_BUILTIN(__builtin_ia32_cmpeqpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpltpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmplepd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpunordpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpneqpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnltpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnlepd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpordpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpeqsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpltsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmplesd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpunordsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpneqsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnltsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpnlesd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cmpordsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_minpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_maxpd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_minsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_maxsd, "V2dV2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddsb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubsb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddusb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_paddusw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubusb128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psubusw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmulhw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmaxub128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmaxsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pminub128, "V16cV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pminsw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_packsswb128, "V16cV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_packssdw128, "V8sV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_packuswb128, "V16cV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmulhuw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4si, "iV4iIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4sf, "fV4fIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v8hi, "sV8sIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_set_v8hi, "V8sV8ssIi", "ncV:128:", "sse2") + +TARGET_BUILTIN(__builtin_ia32_addsubps, "V4fV4fV4f", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_addsubpd, "V2dV2dV2d", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_haddps, "V4fV4fV4f", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_haddpd, "V2dV2dV2d", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_hsubps, "V4fV4fV4f", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_hsubpd, "V2dV2dV2d", "ncV:128:", "sse3") +TARGET_BUILTIN(__builtin_ia32_phaddw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddd128, "V4iV4iV4i", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phaddsw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubd128, "V4iV4iV4i", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_phsubsw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw128, "V8sV16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pshufb128, "V16cV16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_psignb128, "V16cV16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_psignw128, "V8sV8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_psignd128, "V4iV4iV4i", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsb128, "V16cV16c", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsw128, "V8sV8s", "ncV:128:", "ssse3") +TARGET_BUILTIN(__builtin_ia32_pabsd128, "V4iV4i", "ncV:128:", "ssse3") + +TARGET_BUILTIN(__builtin_ia32_ldmxcsr, "vUi", "n", "sse") +TARGET_HEADER_BUILTIN(_mm_setcsr, "vUi", "nh","xmmintrin.h", ALL_LANGUAGES, "sse") +TARGET_BUILTIN(__builtin_ia32_stmxcsr, "Ui", "n", "sse") +TARGET_HEADER_BUILTIN(_mm_getcsr, "Ui", "nh", "xmmintrin.h", ALL_LANGUAGES, "sse") +TARGET_BUILTIN(__builtin_ia32_cvtss2si, "iV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cvttss2si, "iV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_storehps, "vV2i*V4f", "nV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_storelps, "vV2i*V4f", "nV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_movmskps, "iV4f", "nV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_sfence, "v", "n", "sse") +TARGET_HEADER_BUILTIN(_mm_sfence, "v", "nh", "xmmintrin.h", ALL_LANGUAGES, "sse") +TARGET_BUILTIN(__builtin_ia32_rcpps, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_rcpss, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_rsqrtps, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_rsqrtss, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_sqrtps, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_sqrtss, "V4fV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_shufps, "V4fV4fV4fIi", "ncV:128:", "sse") + +TARGET_BUILTIN(__builtin_ia32_maskmovdqu, "vV16cV16cc*", "nV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_movmskpd, "iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmovmskb128, "iV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_movnti, "vi*i", "n", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshufd, "V4iV4iIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshuflw, "V8sV8sIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pshufhw, "V8sV8sIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psadbw128, "V2LLiV16cV16c", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_sqrtpd, "V2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_sqrtsd, "V2dV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_shufpd, "V2dV2dV2dIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq, "V2LLiV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps, "V4fV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq, "V4iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtsd2si, "iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttsd2si, "iV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtsd2ss, "V4fV4fV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvtps2dq, "V4iV4f", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttps2dq, "V4iV4f", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_clflush, "vvC*", "n", "sse2") +TARGET_HEADER_BUILTIN(_mm_clflush, "vvC*", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2") +TARGET_BUILTIN(__builtin_ia32_lfence, "v", "n", "sse2") +TARGET_HEADER_BUILTIN(_mm_lfence, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2") +TARGET_BUILTIN(__builtin_ia32_mfence, "v", "n", "sse2") +TARGET_HEADER_BUILTIN(_mm_mfence, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "sse2") +TARGET_BUILTIN(__builtin_ia32_pause, "v", "n", "") +TARGET_HEADER_BUILTIN(_mm_pause, "v", "nh", "emmintrin.h", ALL_LANGUAGES, "") +TARGET_BUILTIN(__builtin_ia32_pmuludq128, "V2LLiV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psraw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrad128, "V4iV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrld128, "V4iV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlq128, "V2LLiV2LLiV2LLi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllw128, "V8sV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslld128, "V4iV4iV4i", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllq128, "V2LLiV2LLiV2LLi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllwi128, "V8sV8si", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslldi128, "V4iV4ii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psllqi128, "V2LLiV2LLii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlwi128, "V8sV8si", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrldi128, "V4iV4ii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrlqi128, "V2LLiV2LLii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrawi128, "V8sV8si", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psradi128, "V4iV4ii", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pmaddwd128, "V4iV8sV8s", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_pslldqi128_byteshift, "V2LLiV2LLiIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_psrldqi128_byteshift, "V2LLiV2LLiIi", "ncV:128:", "sse2") + +TARGET_BUILTIN(__builtin_ia32_monitor, "vv*UiUi", "n", "sse3") +TARGET_BUILTIN(__builtin_ia32_mwait, "vUiUi", "n", "sse3") +TARGET_BUILTIN(__builtin_ia32_lddqu, "V16ccC*", "nV:128:", "sse3") + +TARGET_BUILTIN(__builtin_ia32_palignr128, "V16cV16cV16cIi", "ncV:128:", "ssse3") + +TARGET_BUILTIN(__builtin_ia32_insertps128, "V4fV4fV4fIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pblendvb128, "V16cV16cV16cV16c", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pblendw128, "V8sV8sV8sIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendpd, "V2dV2dV2dIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendps, "V4fV4fV4fIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendvpd, "V2dV2dV2dV2d", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_blendvps, "V4fV4fV4fV4f", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_packusdw128, "V8sV4iV4i", "ncV:128:", "sse4.1") + +TARGET_BUILTIN(__builtin_ia32_pmaxsb128, "V16cV16cV16c", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmaxsd128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmaxud128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmaxuw128, "V8sV8sV8s", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminsb128, "V16cV16cV16c", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminsd128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminud128, "V4iV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pminuw128, "V8sV8sV8s", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_pmuldq128, "V2LLiV4iV4i", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundps, "V4fV4fIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundss, "V4fV4fV4fIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundsd, "V2dV2dV2dIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_roundpd, "V2dV2dIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_dpps, "V4fV4fV4fIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_dppd, "V2dV2dV2dIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_ptestz128, "iV2LLiV2LLi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_ptestc128, "iV2LLiV2LLi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_ptestnzc128, "iV2LLiV2LLi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_mpsadbw128, "V16cV16cV16cIc", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_phminposuw128, "V8sV8s", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v16qi, "cV16cIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v16qi, "V16cV16ccIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4si, "V4iV4iiIi", "ncV:128:", "sse4.1") // SSE 4.2 -TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","", "sse4.2") - -TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","", "sse4.2") - -TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistrm128, "V16cV16cV16cIc", "ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistri128, "iV16cV16cIc", "ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestrm128, "V16cV16ciV16ciIc", "ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestri128, "iV16ciV16ciIc","ncV:128:", "sse4.2") + +TARGET_BUILTIN(__builtin_ia32_pcmpistria128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistric128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistrio128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistris128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpistriz128, "iV16cV16cIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestria128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestric128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestrio128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestris128, "iV16ciV16ciIc","ncV:128:", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_pcmpestriz128, "iV16ciV16ciIc","ncV:128:", "sse4.2") + +TARGET_BUILTIN(__builtin_ia32_crc32qi, "UiUiUc", "nc", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_crc32hi, "UiUiUs", "nc", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_crc32si, "UiUiUi", "nc", "sse4.2") // SSE4a -TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "", "sse4a") -TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "", "sse4a") -TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "", "sse4a") -TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "", "sse4a") -TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "", "sse4a") -TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "", "sse4a") +TARGET_BUILTIN(__builtin_ia32_extrqi, "V2LLiV2LLiIcIc", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_extrq, "V2LLiV2LLiV16c", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_insertqi, "V2LLiV2LLiV2LLiIcIc", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_insertq, "V2LLiV2LLiV2LLi", "ncV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_movntsd, "vd*V2d", "nV:128:", "sse4a") +TARGET_BUILTIN(__builtin_ia32_movntss, "vf*V4f", "nV:128:", "sse4a") // AES -TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "", "aes") -TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "", "aes") -TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "", "aes") -TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "", "aes") -TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "", "aes") -TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "", "aes") +TARGET_BUILTIN(__builtin_ia32_aesenc128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesenclast128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesdec128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesdeclast128, "V2LLiV2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aesimc128, "V2LLiV2LLi", "ncV:128:", "aes") +TARGET_BUILTIN(__builtin_ia32_aeskeygenassist128, "V2LLiV2LLiIc", "ncV:128:", "aes") // VAES -TARGET_BUILTIN(__builtin_ia32_aesenc256, "V4LLiV4LLiV4LLi", "", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesenc512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes") -TARGET_BUILTIN(__builtin_ia32_aesenclast256, "V4LLiV4LLiV4LLi", "", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesenclast512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes") -TARGET_BUILTIN(__builtin_ia32_aesdec256, "V4LLiV4LLiV4LLi", "", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesdec512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes") -TARGET_BUILTIN(__builtin_ia32_aesdeclast256, "V4LLiV4LLiV4LLi", "", "vaes") -TARGET_BUILTIN(__builtin_ia32_aesdeclast512, "V8LLiV8LLiV8LLi", "", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesenc256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesenc512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesenclast256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesenclast512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesdec256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesdec512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") +TARGET_BUILTIN(__builtin_ia32_aesdeclast256, "V4LLiV4LLiV4LLi", "ncV:256:", "vaes") +TARGET_BUILTIN(__builtin_ia32_aesdeclast512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f,vaes") // GFNI -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v16qi, "V16cV16cV16cIc", "", "gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v32qi, "V32cV32cV32cIc", "", "avx,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v64qi, "V64cV64cV64cIc", "", "avx512bw,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v16qi, "V16cV16cV16cIc", "", "gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v32qi, "V32cV32cV32cIc", "", "avx,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v64qi, "V64cV64cV64cIc", "", "avx512bw,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v16qi, "V16cV16cV16c", "", "gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v32qi, "V32cV32cV32c", "", "avx,gfni") -TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v64qi, "V64cV64cV64c", "", "avx512bw,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v16qi, "V16cV16cV16cIc", "ncV:128:", "gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v32qi, "V32cV32cV32cIc", "ncV:256:", "avx,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineinvqb_v64qi, "V64cV64cV64cIc", "ncV:512:", "avx512bw,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v16qi, "V16cV16cV16cIc", "ncV:128:", "gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v32qi, "V32cV32cV32cIc", "ncV:256:", "avx,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8affineqb_v64qi, "V64cV64cV64cIc", "ncV:512:", "avx512bw,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v16qi, "V16cV16cV16c", "ncV:128:", "gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v32qi, "V32cV32cV32c", "ncV:256:", "avx,gfni") +TARGET_BUILTIN(__builtin_ia32_vgf2p8mulb_v64qi, "V64cV64cV64c", "ncV:512:", "avx512bw,gfni") // CLMUL -TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "", "pclmul") +TARGET_BUILTIN(__builtin_ia32_pclmulqdq128, "V2LLiV2LLiV2LLiIc", "ncV:128:", "pclmul") // VPCLMULQDQ -TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4LLiV4LLiV4LLiIc", "", "vpclmulqdq") -TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8LLiV8LLiV8LLiIc", "", "avx512f,vpclmulqdq") +TARGET_BUILTIN(__builtin_ia32_pclmulqdq256, "V4LLiV4LLiV4LLiIc", "ncV:256:", "vpclmulqdq") +TARGET_BUILTIN(__builtin_ia32_pclmulqdq512, "V8LLiV8LLiV8LLiIc", "ncV:512:", "avx512f,vpclmulqdq") // AVX -TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "", "avx") -TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256, "V8fV8i", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIc", "", "avx") -TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_pd256, "V4dV2dC*", "", "avx") -TARGET_BUILTIN(__builtin_ia32_vbroadcastf128_ps256, "V8fV4fC*", "", "avx") -TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "", "avx") -TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "", "avx") +TARGET_BUILTIN(__builtin_ia32_addsubpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_addsubps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_haddpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_hsubps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_hsubpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_haddps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maxpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maxps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_minpd256, "V4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_minps256, "V8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarpd, "V2dV2dV2LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarps, "V4fV4fV4i", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarpd256, "V4dV4dV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilvarps256, "V8fV8fV8i", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendpd256, "V4dV4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendps256, "V8fV8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendvpd256, "V4dV4dV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_blendvps256, "V8fV8fV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_shufpd256, "V4dV4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_shufps256, "V8fV8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_dpps256, "V8fV8fV8fIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmppd, "V2dV2dV2dIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmppd256, "V4dV4dV4dIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpps, "V4fV4fV4fIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpps256, "V8fV8fV8fIc", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpsd, "V2dV2dV2dIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_cmpss, "V4fV4fV4fIc", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_pd256, "V2dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_ps256, "V4fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vextractf128_si256, "V4iV8iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256, "V4fV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvtps2dq256, "V8iV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256, "V4iV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256, "V4iV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_cvttps2dq256, "V8iV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_pd256, "V4dV4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_ps256, "V8fV8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vperm2f128_si256, "V8iV8iV8iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilpd, "V2dV2dIi", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilps, "V4fV4fIi", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilpd256, "V4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vpermilps256, "V8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_pd256, "V4dV4dV2dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_ps256, "V8fV8fV4fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vinsertf128_si256, "V8iV8iV4iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_sqrtpd256, "V4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_sqrtps256, "V8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_rsqrtps256, "V8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_rcpps256, "V8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_roundpd256, "V4dV4dIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_roundps256, "V8fV8fIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzpd, "iV2dV2d", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcpd, "iV2dV2d", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcpd, "iV2dV2d", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzps, "iV4fV4f", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcps, "iV4fV4f", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcps, "iV4fV4f", "ncV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzpd256, "iV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcpd256, "iV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcpd256, "iV4dV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestzps256, "iV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestcps256, "iV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vtestnzcps256, "iV8fV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_ptestz256, "iV4LLiV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_ptestc256, "iV4LLiV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_ptestnzc256, "iV4LLiV4LLi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_movmskpd256, "iV4d", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_movmskps256, "iV8f", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vzeroall, "v", "n", "avx") +TARGET_BUILTIN(__builtin_ia32_vzeroupper, "v", "n", "avx") +TARGET_BUILTIN(__builtin_ia32_lddqu256, "V32ccC*", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadpd, "V2dV2dC*V2LLi", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadps, "V4fV4fC*V4i", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadpd256, "V4dV4dC*V4LLi", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskloadps256, "V8fV8fC*V8i", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstorepd, "vV2d*V2LLiV2d", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstoreps, "vV4f*V4iV4f", "nV:128:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstorepd256, "vV4d*V4LLiV4d", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_maskstoreps256, "vV8f*V8iV8f", "nV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v32qi, "cV32cIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v16hi, "sV16sIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v8si, "iV8iIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v32qi, "V32cV32ccIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v16hi, "V16sV16ssIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v8si, "V8iV8iiIi", "ncV:256:", "avx") // AVX2 -TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "", "avx2") +TARGET_BUILTIN(__builtin_ia32_mpsadbw256, "V32cV32cV32cIc", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pabsb256, "V32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pabsw256, "V16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pabsd256, "V8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packsswb256, "V32cV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packssdw256, "V16sV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packuswb256, "V32cV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_packusdw256, "V16sV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddusb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_paddusw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubusb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psubusw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_palignr256, "V32cV32cV32cIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendvb256, "V32cV32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendw256, "V16sV16sV16sIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phaddw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phaddd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phaddsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phsubw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phsubd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_phsubsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaddubsw256, "V16sV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaddwd256, "V8iV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxub256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxuw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxud256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmaxsd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminub256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminuw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminud256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminsb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pminsd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmovmskb256, "iV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmuldq256, "V4LLiV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmulhrsw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmulhuw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmulhw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pmuludq256, "V4LLiV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psadbw256, "V4LLiV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufd256, "V8iV8iIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshuflw256, "V16sV16sIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pshufhw256, "V16sV16sIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psignb256, "V32cV32cV32c", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psignw256, "V16sV16sV16s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psignd256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllwi256, "V16sV16si", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllw256, "V16sV16sV8s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslldqi256_byteshift, "V4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslldi256, "V8iV8ii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pslld256, "V8iV8iV4i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllqi256, "V4LLiV4LLii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrawi256, "V16sV16si", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psraw256, "V16sV16sV8s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psradi256, "V8iV8ii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrad256, "V8iV8iV4i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrldqi256_byteshift, "V4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlwi256, "V16sV16si", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlw256, "V16sV16sV8s", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrldi256, "V8iV8ii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrld256, "V8iV8iV4i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlqi256, "V4LLiV4LLii", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendd128, "V4iV4iV4iIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_pblendd256, "V8iV8iV8iIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permvarsi256, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permdf256, "V4dV4dIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permvarsf256, "V8fV8fV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permti256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_permdi256, "V4LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_extract128i256, "V2LLiV4LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_insert128i256, "V4LLiV4LLiV2LLiIi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadd256, "V8iV8iC*V8i", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadq256, "V4LLiV4LLiC*V4LLi", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadd, "V4iV4iC*V4i", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskloadq, "V2LLiV2LLiC*V2LLi", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstored256, "vV8i*V8iV8i", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstoreq256, "vV4LLi*V4LLiV4LLi", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstored, "vV4i*V4iV4i", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_maskstoreq, "vV2LLi*V2LLiV2LLi", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv8si, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv4si, "V4iV4iV4i", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv4di, "V4LLiV4LLiV4LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psllv2di, "V2LLiV2LLiV2LLi", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrav8si, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrav4si, "V4iV4iV4i", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv8si, "V8iV8iV8i", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv4si, "V4iV4iV4i", "ncV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv4di, "V4LLiV4LLiV4LLi", "ncV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_psrlv2di, "V2LLiV2LLiV2LLi", "ncV:128:", "avx2") // GATHER -TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "", "avx2") - -TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "", "avx2") -TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_pd, "V2dV2ddC*V4iV2dIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_pd256, "V4dV4ddC*V4iV4dIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_pd, "V2dV2ddC*V2LLiV2dIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_pd256, "V4dV4ddC*V4LLiV4dIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_ps, "V4fV4ffC*V4iV4fIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_ps256, "V8fV8ffC*V8iV8fIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_ps, "V4fV4ffC*V2LLiV4fIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_ps256, "V4fV4ffC*V4LLiV4fIc", "nV:256:", "avx2") + +TARGET_BUILTIN(__builtin_ia32_gatherd_q, "V2LLiV2LLiLLiC*V4iV2LLiIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_q256, "V4LLiV4LLiLLiC*V4iV4LLiIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_q, "V2LLiV2LLiLLiC*V2LLiV2LLiIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_q256, "V4LLiV4LLiLLiC*V4LLiV4LLiIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_d, "V4iV4iiC*V4iV4iIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherd_d256, "V8iV8iiC*V8iV8iIc", "nV:256:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_d, "V4iV4iiC*V2LLiV4iIc", "nV:128:", "avx2") +TARGET_BUILTIN(__builtin_ia32_gatherq_d256, "V4iV4iiC*V4LLiV4iIc", "nV:256:", "avx2") // F16C -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "", "f16c") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "", "f16c") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "", "f16c") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph, "V8sV4fIi", "ncV:128:", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256, "V8sV8fIi", "ncV:256:", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps, "V4fV8s", "ncV:128:", "f16c") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256, "V8fV8s", "ncV:256:", "f16c") // RDRAND -TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "", "rdrnd") -TARGET_BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "", "rdrnd") -TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "", "rdrnd") - -// FSGSBASE -TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_rdrand16_step, "UiUs*", "n", "rdrnd") +TARGET_BUILTIN(__builtin_ia32_rdrand32_step, "UiUi*", "n", "rdrnd") // FXSR -TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "", "fxsr") -TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "", "fxsr") +TARGET_BUILTIN(__builtin_ia32_fxrstor, "vv*", "n", "fxsr") +TARGET_BUILTIN(__builtin_ia32_fxsave, "vv*", "n", "fxsr") // XSAVE -TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "", "xsave") -TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "", "xsave") -TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "", "xsaveopt") -TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "", "xsaves") -TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "", "xsavec") -TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "", "xsaves") +TARGET_BUILTIN(__builtin_ia32_xsave, "vv*ULLi", "n", "xsave") +TARGET_BUILTIN(__builtin_ia32_xrstor, "vv*ULLi", "n", "xsave") +TARGET_BUILTIN(__builtin_ia32_xsaveopt, "vv*ULLi", "n", "xsaveopt") +TARGET_BUILTIN(__builtin_ia32_xrstors, "vv*ULLi", "n", "xsaves") +TARGET_BUILTIN(__builtin_ia32_xsavec, "vv*ULLi", "n", "xsavec") +TARGET_BUILTIN(__builtin_ia32_xsaves, "vv*ULLi", "n", "xsaves") // SHSTK -TARGET_BUILTIN(__builtin_ia32_incsspd, "vUi", "u", "shstk") -TARGET_BUILTIN(__builtin_ia32_rdsspd, "UiUi", "Un", "shstk") -TARGET_BUILTIN(__builtin_ia32_saveprevssp, "v", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_rstorssp, "vv*", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_wrssd, "vUiv*", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_wrussd, "vUiv*", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_setssbsy, "v", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_clrssbsy, "vv*", "", "shstk") +TARGET_BUILTIN(__builtin_ia32_incsspd, "vUi", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_rdsspd, "UiUi", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_saveprevssp, "v", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_rstorssp, "vv*", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_wrssd, "vUiv*", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_wrussd, "vUiv*", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_setssbsy, "v", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_clrssbsy, "vv*", "n", "shstk") //CLFLUSHOPT -TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "", "clflushopt") +TARGET_BUILTIN(__builtin_ia32_clflushopt, "vvC*", "n", "clflushopt") //CLWB -TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "", "clwb") +TARGET_BUILTIN(__builtin_ia32_clwb, "vvC*", "n", "clwb") + +//WB[NO]INVD +TARGET_BUILTIN(__builtin_ia32_wbinvd, "v", "n", "") +TARGET_BUILTIN(__builtin_ia32_wbnoinvd, "v", "n", "wbnoinvd") // ADX -TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "", "adx") -TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "", "") -TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "", "") +TARGET_BUILTIN(__builtin_ia32_addcarryx_u32, "UcUcUiUiUi*", "n", "adx") +TARGET_BUILTIN(__builtin_ia32_addcarry_u32, "UcUcUiUiUi*", "n", "") +TARGET_BUILTIN(__builtin_ia32_subborrow_u32, "UcUcUiUiUi*", "n", "") // RDSEED -TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "", "rdseed") -TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "", "rdseed") +TARGET_BUILTIN(__builtin_ia32_rdseed16_step, "UiUs*", "n", "rdseed") +TARGET_BUILTIN(__builtin_ia32_rdseed32_step, "UiUi*", "n", "rdseed") // BMI -TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "", "bmi") +TARGET_BUILTIN(__builtin_ia32_bextr_u32, "UiUiUi", "nc", "bmi") // BMI2 -TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "", "bmi2") -TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "", "bmi2") -TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "", "bmi2") +TARGET_BUILTIN(__builtin_ia32_bzhi_si, "UiUiUi", "nc", "bmi2") +TARGET_BUILTIN(__builtin_ia32_pdep_si, "UiUiUi", "nc", "bmi2") +TARGET_BUILTIN(__builtin_ia32_pext_si, "UiUiUi", "nc", "bmi2") // TBM -TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "", "tbm") +TARGET_BUILTIN(__builtin_ia32_bextri_u32, "UiUiIUi", "nc", "tbm") // LWP -TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "", "lwp") -TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "", "lwp") -TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "", "lwp") -TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "", "lwp") +TARGET_BUILTIN(__builtin_ia32_llwpcb, "vv*", "n", "lwp") +TARGET_BUILTIN(__builtin_ia32_slwpcb, "v*", "n", "lwp") +TARGET_BUILTIN(__builtin_ia32_lwpins32, "UcUiUiUi", "n", "lwp") +TARGET_BUILTIN(__builtin_ia32_lwpval32, "vUiUiUi", "n", "lwp") // SHA -TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "", "sha") -TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "", "sha") -TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "", "sha") -TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "", "sha") -TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "", "sha") -TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "", "sha") -TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1rnds4, "V4iV4iV4iIc", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1nexte, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1msg1, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha1msg2, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha256rnds2, "V4iV4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha256msg1, "V4iV4iV4i", "ncV:128:", "sha") +TARGET_BUILTIN(__builtin_ia32_sha256msg2, "V4iV4iV4i", "ncV:128:", "sha") // FMA -TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3, "V4fV4fV4fV4f", "", "fma") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3, "V2dV2dV2dV2d", "", "fma") -TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "", "fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "", "fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmaddps256, "V8fV8fV8fV8f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256, "V4dV4dV4dV4d", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "", "fma|fma4") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "", "fma|fma4") - -TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd128_maskz, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256_maskz, "V4dV4dV4dV4dUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps128_maskz, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256_maskz, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfmsubaddps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfmsubaddps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfnmaddpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmaddpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfnmaddpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfnmaddps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmaddps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfnmaddps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd128_mask3, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd256_mask3, "V4dV4dV4dV4dUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfnmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmsubps128_mask3, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vfnmsubps256_mask3, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfnmsubps512_mask3, "V16fV16fV16fV16fUsIi", "", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps, "V4fV4fV4fV4f", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd, "V2dV2dV2dV2d", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3, "V4fV4fV4fV4f", "ncV:128:", "fma") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3, "V2dV2dV2dV2d", "ncV:128:", "fma") +TARGET_BUILTIN(__builtin_ia32_vfmaddss, "V4fV4fV4fV4f", "ncV:128:", "fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd, "V2dV2dV2dV2d", "ncV:128:", "fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps, "V4fV4fV4fV4f", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd, "V2dV2dV2dV2d", "ncV:128:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddps256, "V8fV8fV8fV8f", "ncV:256:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd256, "V4dV4dV4dV4d", "ncV:256:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps256, "V8fV8fV8fV8f", "ncV:256:", "fma|fma4") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd256, "V4dV4dV4dV4d", "ncV:256:", "fma|fma4") + +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_maskz, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_maskz, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_maskz, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubaddpd512_mask3, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_maskz, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsubps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubaddps512_mask3, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") // XOP -TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "", "xop") - -TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "", "xop") -TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "", "xop") - -TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "", "rtm") -TARGET_BUILTIN(__builtin_ia32_xend, "v", "", "rtm") -TARGET_BUILTIN(__builtin_ia32_xabort, "vIc", "", "rtm") -TARGET_BUILTIN(__builtin_ia32_xtest, "i", "", "rtm") +TARGET_BUILTIN(__builtin_ia32_vpmacssww, "V8sV8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsww, "V8sV8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsswd, "V4iV8sV8sV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacswd, "V4iV8sV8sV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssdd, "V4iV4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsdd, "V4iV4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssdql, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsdql, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacssdqh, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmacsdqh, "V2LLiV4iV4iV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmadcsswd, "V4iV8sV8sV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpmadcswd, "V4iV8sV8sV4i", "ncV:128:", "xop") + +TARGET_BUILTIN(__builtin_ia32_vphaddbw, "V8sV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddbd, "V4iV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddbq, "V2LLiV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddwd, "V4iV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddwq, "V2LLiV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphadddq, "V2LLiV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddubw, "V8sV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddubd, "V4iV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddubq, "V2LLiV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphadduwd, "V4iV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphadduwq, "V2LLiV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphaddudq, "V2LLiV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphsubbw, "V8sV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphsubwd, "V4iV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vphsubdq, "V2LLiV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpperm, "V16cV16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotb, "V16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotw, "V8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotd, "V4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotbi, "V16cV16cIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotwi, "V8sV8sIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotdi, "V4iV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vprotqi, "V2LLiV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshlb, "V16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshlw, "V8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshld, "V4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshlq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshab, "V16cV16cV16c", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshaw, "V8sV8sV8s", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshad, "V4iV4iV4i", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpshaq, "V2LLiV2LLiV2LLi", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomub, "V16cV16cV16cIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomuw, "V8sV8sV8sIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomud, "V4iV4iV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomuq, "V2LLiV2LLiV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomb, "V16cV16cV16cIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomw, "V8sV8sV8sIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomd, "V4iV4iV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpcomq, "V2LLiV2LLiV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2pd, "V2dV2dV2dV2LLiIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2pd256, "V4dV4dV4dV4LLiIc", "ncV:256:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2ps, "V4fV4fV4fV4iIc", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vpermil2ps256, "V8fV8fV8fV8iIc", "ncV:256:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczss, "V4fV4f", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczsd, "V2dV2d", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczps, "V4fV4f", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczpd, "V2dV2d", "ncV:128:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczps256, "V8fV8f", "ncV:256:", "xop") +TARGET_BUILTIN(__builtin_ia32_vfrczpd256, "V4dV4d", "ncV:256:", "xop") + +TARGET_BUILTIN(__builtin_ia32_xbegin, "i", "n", "rtm") +TARGET_BUILTIN(__builtin_ia32_xend, "v", "n", "rtm") +TARGET_BUILTIN(__builtin_ia32_xabort, "vIc", "n", "rtm") +TARGET_BUILTIN(__builtin_ia32_xtest, "i", "n", "rtm") BUILTIN(__builtin_ia32_rdpmc, "ULLii", "") BUILTIN(__builtin_ia32_rdtsc, "ULLi", "") BUILTIN(__rdtsc, "ULLi", "") BUILTIN(__builtin_ia32_rdtscp, "ULLiUi*", "") + +TARGET_BUILTIN(__builtin_ia32_rdpid, "Ui", "n", "rdpid") + // PKU -TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "", "pku") -TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "", "pku") +TARGET_BUILTIN(__builtin_ia32_rdpkru, "Ui", "n", "pku") +TARGET_BUILTIN(__builtin_ia32_wrpkru, "vUi", "n", "pku") // AVX-512 -TARGET_BUILTIN(__builtin_ia32_sqrtpd512_mask, "V8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_sqrtps512_mask, "V16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "", "avx512er") - -TARGET_BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_rcp28sd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rcp28ss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "", "avx512er") -TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "", "avx512er") - -TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pabsd512_mask, "V16iV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pabsq512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxud512_mask, "V16iV16iV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmaxuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminsd512_mask, "V16iV16iV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminsq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminud512_mask, "V16iV16iV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pminuq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16ffC*V16fUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fV16fC*V16fUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8ddC*V8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dV8dC*V8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vLLi*V8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vi*V16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_mask, "V16iV16iV16iV16iUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_mask, "V16fV16iV16fV16fUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_mask, "V8dV8LLiV8dV8dUc", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_vpdpbusd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds512_mask, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpbusds512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vnni") -TARGET_BUILTIN(__builtin_ia32_vpdpwssds512_maskz, "V16iV16iV16iV16iUs", "", "avx512vnni") - -TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "", "avx512pf") -TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "", "avx512pf") - -TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_pabsb512_mask, "V64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pabsw512_mask, "V32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaxuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminub512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pminuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermt2varhi512_maskz, "V32sV32sV32sV32sUi", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictsi_128_mask, "V4iV4iV4iUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictsi_256_mask, "V8iV8iV8iUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd") -TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "", "avx512cd") -TARGET_BUILTIN(__builtin_ia32_vplzcntd_512_mask, "V16iV16iV16iUs", "", "avx512cd") -TARGET_BUILTIN(__builtin_ia32_vplzcntq_512_mask, "V8LLiV8LLiV8LLiUc", "", "avx512cd") - -TARGET_BUILTIN(__builtin_ia32_vpopcntd_128, "V4iV4i", "", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntq_128, "V2LLiV2LLi", "", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntd_256, "V8iV8i", "", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntq_256, "V4LLiV4LLi", "", "avx512vpopcntdq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "", "avx512vpopcntdq") -TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "", "avx512vpopcntdq") - -TARGET_BUILTIN(__builtin_ia32_vpopcntb_128, "V16cV16c", "", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntw_128, "V8sV8s", "", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntb_256, "V32cV32c", "", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntw_256, "V16sV16s", "", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntb_512, "V64cV64c", "", "avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpopcntw_512, "V32sV32s", "", "avx512bitalg") - -TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb128_mask, "UsV16cV16cUs", "", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb256_mask, "UiV32cV32cUi", "", "avx512vl,avx512bitalg") -TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb512_mask, "ULLiV64cV64cULLi", "", "avx512bitalg") - -TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermt2varhi128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_vpermt2varhi256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512bw") - -TARGET_BUILTIN(__builtin_ia32_pmulhrsw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmulhuw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmulhw512_mask, "V32sV32sV32sV32sUi", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_addpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_addps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subpd512_mask, "V8dV8dV8dV8dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subps512_mask, "V16fV16fV16fV16fUsIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_pmaddubsw512_mask, "V32sV64cV64cV32sUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmaddwd512_mask, "V16iV32sV32sV16iUs", "", "avx512bw") - -TARGET_BUILTIN(__builtin_ia32_addss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minss_round_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_addsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_divsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_mulsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_subsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_maxsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_minsd_round_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") - -TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_compresshi128_mask, "V8sV8sV8sUc","","avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compresshi256_mask, "V16sV16sV16sUs","","avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressqi128_mask, "V16cV16cV16cUs","","avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressqi256_mask, "V32cV32cV32cUi","","avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_compressstorehi128_mask, "vV8s*V8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstorehi256_mask, "vV16s*V16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoreqi128_mask, "vV16c*V16cUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoreqi256_mask, "vV32c*V32cUi", "", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtdq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtdq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2ps256_mask, "V4fV4dV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2pd128_mask, "V2dV4fV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2pd256_mask, "V4dV4fV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2dq256_mask, "V4iV4dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttps2dq128_mask, "V4iV4fV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttps2dq256_mask, "V8iV8fV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtudq2ps128_mask, "V4fV4iV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtudq2ps256_mask, "V8fV8iV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_expandhi128_mask, "V8sV8sV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandhi256_mask, "V16sV16sV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandqi128_mask, "V16cV16cV16cUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandqi256_mask, "V32cV32cV32cUi", "", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2d*V2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4d*V4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLi*V2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLi*V4LLiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_expandloadhi128_mask, "V8sV8sC*V8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadhi256_mask, "V16sV16sC*V16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadqi128_mask, "V16cV16cC*V16cUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadqi256_mask, "V32cV32cC*V32cUi", "", "avx512vl,avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4f*V4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8f*V8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4i*V4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8i*V8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pabsq128_mask, "V2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pabsq256_mask, "V4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmaxuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminsq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminsq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminuq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_pminuq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vpermi2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128_mask, "V2dV2dV2LLiV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256_mask, "V4dV4dV4LLiV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varps128_mask, "V4fV4fV4iV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varps256_mask, "V8fV8fV8iV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_mask, "V4iV4iV4iV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2vard128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_mask, "V8iV8iV8iV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2vard256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_mask, "V2dV2LLiV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varpd128_maskz, "V2dV2LLiV2dV2dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_mask, "V4dV4LLiV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varpd256_maskz, "V4dV4LLiV4dV4dUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_mask, "V4fV4iV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varps128_maskz, "V4fV4iV4fV4fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_mask, "V8fV8iV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varps256_maskz, "V8fV8iV8fV8fUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl") - -TARGET_BUILTIN(__builtin_ia32_vpshldd128_mask, "V4iV4iV4iIiV4iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldd256_mask, "V8iV8iV8iIiV8iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldd512_mask, "V16iV16iV16iIiV16iUs", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq128_mask, "V2LLiV2LLiV2LLiIiV2LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldq512_mask, "V8LLiV8LLiV8LLiIiV8LLiUc", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw128_mask, "V8sV8sV8sIiV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw256_mask, "V16sV16sV16sIiV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldw512_mask, "V32sV32sV32sIiV32sUi", "", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_vpshrdd128_mask, "V4iV4iV4iiV4iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd256_mask, "V8iV8iV8iiV8iUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdd512_mask, "V16iV16iV16iiV16iUs", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq128_mask, "V2LLiV2LLiV2LLiiV2LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq256_mask, "V4LLiV4LLiV4LLiiV4LLiUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdq512_mask, "V8LLiV8LLiV8LLiiV8LLiUc", "", "avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw128_mask, "V8sV8sV8siV8sUc", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw256_mask, "V16sV16sV16siV16sUs", "", "avx512vl,avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_vpshrdw512_mask, "V32sV32sV32siV32sUi", "", "avx512vbmi2") - -TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "", "avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd128_mask, "V2dV2LLiV2dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd256_mask, "V4dV4LLiV4dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangesd128_round_mask, "V2dV2dV2dV2dUcIiIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangess128_round_mask, "V4fV4fV4fV4fUcIiIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "", "avx512vl,avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducesd_mask, "V2dV2dV2dV2dUcIiIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducess_mask, "V4fV4fV4fV4fUcIiIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovwb256_mask, "V16cV16sV16cUs", "", "avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "", "avx512dq") -TARGET_BUILTIN(__builtin_ia32_prold512_mask, "V16iV16iIiV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prolq512_mask, "V8LLiV8LLiIiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prold128_mask, "V4iV4iIiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prold256_mask, "V8iV8iIiV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolq128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolq256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvd512_mask, "V16iV16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prolvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prord512_mask, "V16iV16iiV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prorq512_mask, "V8LLiV8LLiiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prolvd128_mask, "V4iV4iV4iV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvd256_mask, "V8iV8iV8iV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prolvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prord128_mask, "V4iV4iIiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prord256_mask, "V8iV8iIiV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorq128_mask, "V2LLiV2LLiIiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorq256_mask, "V4LLiV4LLiIiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvd512_mask, "V16iV16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prorvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_prorvd128_mask, "V4iV4iV4iV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvd256_mask, "V8iV8iV8iV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_prorvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psllv16hi, "V16sV16sV16s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psllv8hi, "V8sV8sV8s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pslldi512, "V16iV16ii","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psllqi512, "V8LLiV8LLii","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlv32hi, "V32sV32sV32s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrlv16hi, "V16sV16sV16s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psrlv8hi, "V8sV8sV8s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psrldi512, "V16iV16ii","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlqi512, "V8LLiV8LLii","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrav32hi, "V32sV32sV32s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrav16hi, "V16sV16sV16s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psrav8hi, "V8sV8sV8s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_psravq128, "V2LLiV2LLiV2LLi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_psravq256, "V4LLiV4LLiV4LLi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8LLiV8LLiC*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa64store512_mask, "vV8LLi*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32store128_mask, "vV4i*V4iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa32store256_mask, "vV8i*V8iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa64load256_mask, "V4LLiV4LLiC*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_movdqa64store128_mask, "vV2LLi*V2LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_movdqa64store256_mask, "vV4LLi*V4LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512ifma") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128_mask, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc","","avx512ifma,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varqi512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpermt2varqi512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpermt2varqi512_maskz, "V64cV64cV64cV64cULLi","","avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpermi2varqi128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermi2varqi256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varqi128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varqi128_maskz, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varqi256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpermt2varqi256_maskz, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kunpckdi, "ULLiULLiULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_kunpcksi, "UiUiUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cULLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8LLiIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8LLiIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmps512_maskz, "V16fV16fV16fV16iIiUsIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmsd_mask, "V2dV2dV2dV2LLiIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmsd_maskz, "V2dV2dV2dV2LLiIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmss_mask, "V4fV4fV4fV4iIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_fixupimmss_maskz, "V4fV4fV4fV4iIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_maskz, "V4dV4dV4dV4LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V8dV8d*V8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V16fV16f*V16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2LLiV2LLi*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4LLiV4LLi*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquqi128_mask, "vV16c*V16cUs","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storedquqi256_mask, "vV32c*V32cUi","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_storeapd128_mask, "vV2d*V2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storesd128_mask, "vV8d*V8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_storeapd256_mask, "vV4d*V4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeaps128_mask, "vV4f*V4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storess128_mask, "vV16f*V16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_storeaps256_mask, "vV8f*V8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqudi128_mask, "vV2LLi*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqudi256_mask, "vV4LLi*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqusi128_mask, "vV4i*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storedqusi256_mask, "vV8i*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeupd128_mask, "vV2d*V2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeupd256_mask, "vV4d*V4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeups128_mask, "vV4f*V4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_storeups256_mask, "vV8f*V8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14pd128_mask, "V2dV2dV2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14pd256_mask, "V4dV4dV4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14ps128_mask, "V4fV4fV4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rcp14ps256_mask, "V8fV8fV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntd_128_mask, "V4iV4iV4iUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntd_256_mask, "V8iV8iV8iUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntq_128_mask, "V2LLiV2LLiV2LLiUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vplzcntq_256_mask, "V4LLiV4LLiV4LLiUc","","avx512cd,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2vard512_mask, "V16iV16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varpd512_mask, "V8dV8dV8LLiV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varps512_mask, "V16fV16fV16iV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermi2varq512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2vard512_maskz, "V16iV16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2varpd512_maskz, "V8dV8LLiV8dV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2varps512_maskz, "V16fV16iV16fV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpermt2varq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefps512_mask, "V16fV16fV16fV16fUsIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefsd_round_mask, "V2dV2dV2dV2dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_scalefss_round_mask, "V4fV4fV4fV4fUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psradi512, "V16iV16ii","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psraqi512, "V8LLiV8LLii","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psraq128, "V2LLiV2LLiV2LLi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraq256, "V4LLiV4LLiV2LLi","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraqi128, "V2LLiV2LLii","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_psraqi256, "V4LLiV4LLii","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pslld512, "V16iV16iV4i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psllq512, "V8LLiV8LLiV2LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psllv16si, "V16iV16iV16i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psllv8di, "V8LLiV8LLiV8LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrad512, "V16iV16iV4i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psraq512, "V8LLiV8LLiV2LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrav16si, "V16iV16iV16i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrav8di, "V8LLiV8LLiV8LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrld512, "V16iV16iV4i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlq512, "V8LLiV8LLiV2LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlv16si, "V16iV16iV16i","","avx512f") -TARGET_BUILTIN(__builtin_ia32_psrlv8di, "V8LLiV8LLiV8LLi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogd512_mask, "V16iV16iV16iV16iIiUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogd512_maskz, "V16iV16iV16iV16iIiUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogq512_mask, "V8LLiV8LLiV8LLiV8LLiIiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogq512_maskz, "V8LLiV8LLiV8LLiV8LLiIiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pternlogd128_mask, "V4iV4iV4iV4iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogd128_maskz, "V4iV4iV4iV4iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogd256_mask, "V8iV8iV8iV8iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogd256_maskz, "V8iV8iV8iV8iIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_mask, "V16fV16fV16fIiV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_mask, "V8dV8dV8dIiV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_mask, "V16iV16iV16iIiV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_mask, "V8LLiV8LLiV8LLiIiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256_mask, "V8fV8fV8fIiV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256_mask, "V4dV4dV4dIiV4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256_mask, "V8iV8iV8iIiV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256_mask, "V4LLiV4LLiV4LLiIiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rsqrt14pd256_mask, "V4dV4dV4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ps128_mask, "V4fV4fV4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_rsqrt14ps256_mask, "V8fV8fV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtb2mask512, "ULLiV64c","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtmask2b512, "V64cULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtmask2w512, "V32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtd2mask512, "UsV16i","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtmask2d512, "V16iUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtmask2q512, "V8LLiUc","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtq2mask512, "UcV8LLi","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_cvtb2mask128, "UsV16c","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtb2mask256, "UiV32c","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2b128, "V16cUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2b256, "V32cUi","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2w128, "V8sUc","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2w256, "V16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtd2mask128, "UcV4i","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtd2mask256, "UcV8i","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2d128, "V4iUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2d256, "V8iUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2q128, "V2LLiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtmask2q256, "V4LLiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdb512_mask, "V16cV16iV16cUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovsdw512_mask, "V16sV16iV16sUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsdw512mem_mask, "vV16s*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqb512_mask, "V16cV8LLiV16cUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqb512mem_mask, "vV16c*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqd512_mask, "V8iV8LLiV8iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqd512mem_mask, "vV8i*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqw512_mask, "V8sV8LLiV8sUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsqw512mem_mask, "vV8s*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovsdb128_mask, "V16cV4iV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdb128mem_mask, "vV16c*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovswb128mem_mask, "vV16c*V8sUc","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovsdb256_mask, "V16cV8iV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdb256mem_mask, "vV16c*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovswb256mem_mask, "vV16c*V16sUs","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovsdw128_mask, "V8sV4iV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdw128mem_mask, "vV8s*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdw256_mask, "V8sV8iV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsdw256mem_mask, "vV8s*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb128_mask, "V16cV2LLiV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb128mem_mask, "vV16c*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb256_mask, "V16cV4LLiV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqb256mem_mask, "vV16c*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd128_mask, "V4iV2LLiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd128mem_mask, "vV4i*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd256_mask, "V4iV4LLiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqd256mem_mask, "vV4i*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw128_mask, "V8sV2LLiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw128mem_mask, "vV8s*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw256_mask, "V8sV4LLiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovsqw256mem_mask, "vV8s*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdb512_mask, "V16cV16iV16cUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusdb512mem_mask, "vV16c*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovuswb512mem_mask, "vV32c*V32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovusdw512_mask, "V16sV16iV16sUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusdw512mem_mask, "vV16s*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqb512_mask, "V16cV8LLiV16cUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqb512mem_mask, "vV16c*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqd512_mask, "V8iV8LLiV8iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqd512mem_mask, "vV8i*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqw512_mask, "V8sV8LLiV8sUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusqw512mem_mask, "vV8s*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovusdb128_mask, "V16cV4iV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdb128mem_mask, "vV16c*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovuswb128mem_mask, "vV16c*V8sUc","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovusdb256_mask, "V16cV8iV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdb256mem_mask, "vV16c*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovuswb256mem_mask, "vV16c*V16sUs","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovusdw128_mask, "V8sV4iV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdw128mem_mask, "vV8s*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdw256_mask, "V8sV8iV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusdw256mem_mask, "vV8s*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb128_mask, "V16cV2LLiV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb128mem_mask, "vV16c*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb256_mask, "V16cV4LLiV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqb256mem_mask, "vV16c*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd128_mask, "V4iV2LLiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd128mem_mask, "vV4i*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd256_mask, "V4iV4LLiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqd256mem_mask, "vV4i*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw128_mask, "V8sV2LLiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw128mem_mask, "vV8s*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw256_mask, "V8sV4LLiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovusqw256mem_mask, "vV8s*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdb512_mask, "V16cV16iV16cUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovdb512mem_mask, "vV16c*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovwb512mem_mask, "vV32c*V32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_pmovdb128_mask, "V16cV4iV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovwb128mem_mask, "vV16c*V8sUc","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovdb128mem_mask, "vV16c*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdb256_mask, "V16cV8iV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdb256mem_mask, "vV16c*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovwb256mem_mask, "vV16c*V16sUs","","avx512vl,avx512bw") -TARGET_BUILTIN(__builtin_ia32_pmovdw128_mask, "V8sV4iV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdw128mem_mask, "vV8s*V4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdw256_mask, "V8sV8iV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovdw256mem_mask, "vV8s*V8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb128_mask, "V16cV2LLiV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb128mem_mask, "vV16c*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb256_mask, "V16cV4LLiV16cUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqb256mem_mask, "vV16c*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd128_mask, "V4iV2LLiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd128mem_mask, "vV4i*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd256_mask, "V4iV4LLiV4iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqd256mem_mask, "vV4i*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2diV2dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4diV4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fiV4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantps256_mask, "V8fV8fiV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_getmantpd512_mask, "V8dV8diV8dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getmantps512_mask, "V16fV16fiV16fUsIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getexppd512_mask, "V8dV8dV8dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_getexpps512_mask, "V16fV16fV16fUsIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3_maskz, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask3, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfnmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_vfnmsubss3_mask3, "V4fV4fV4fV4fUcIi", "", "avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarhi512_mask, "V32sV32sV32sV32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_permvardf512_mask, "V8dV8dV8LLiV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_permvardi512_mask, "V8LLiV8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarsf512_mask, "V16fV16fV16iV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarsi512_mask, "V16iV16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_permvarqi512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_permvarqi128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarqi256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarhi128_mask, "V8sV8sV8sV8sUc","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarhi256_mask, "V16sV16sV16sV16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvardf256_mask, "V4dV4dV4LLiV4dUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvardi256_mask, "V4LLiV4LLiV4LLiV4LLiUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarsf256_mask, "V8fV8fV8iV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_permvarsi256_mask, "V8iV8iV8iV8iUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclasspd128_mask, "UcV2dIiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclasspd256_mask, "UcV4dIiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclassps128_mask, "UcV4fIiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclassps256_mask, "UcV8fIiUc","","avx512dq,avx512vl") -TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc","","avx512dq") -TARGET_BUILTIN(__builtin_ia32_kandhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kandnhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_korhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kortestchi, "iUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_palignr512_mask, "V64cV64cV64cIiV64cULLi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw128_mask, "V8sV16cV16cIiV8sUc","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw256_mask, "V16sV32cV32cIiV16sUs","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_dbpsadbw512_mask, "V32sV64cV64cIiV32sUi","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compresshi512_mask, "V32sV32sV32sUi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressqi512_mask, "V64cV64cV64cULLi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandqi512_mask, "V64cV64cV64cULLi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloaddf512_mask, "V8dV8dC*V8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expandloaddi512_mask, "V8LLiV8LLiC*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expandloadhi512_mask, "V32sV32sC*V32sUi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadqi512_mask, "V64cV64cC*V64cULLi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_expandloadsf512_mask, "V16fV16fC*V16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expandloadsi512_mask, "V16iV16iC*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expandsf512_mask, "V16fV16fV16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_expandsi512_mask, "V16iV16iV16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtps2pd512_mask, "V8dV8fV8dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstoredf512_mask, "vV8d*V8dUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstoredi512_mask, "vV8LLi*V8LLiUc","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstorehi512_mask, "vV32s*V32sUi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoreqi512_mask, "vV64c*V64cULLi","","avx512vbmi2") -TARGET_BUILTIN(__builtin_ia32_compressstoresf512_mask, "vV16f*V16fUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_compressstoresi512_mask, "vV16i*V16iUs","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps_mask, "V4fV8sV4fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256_mask, "V8fV8sV8fUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph_mask, "V8sV4fIiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256_mask, "V8sV8fIiV8sUc","","avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtw2mask512, "UiV32s","","avx512bw") -TARGET_BUILTIN(__builtin_ia32_cvtw2mask128, "UcV8s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtw2mask256, "UsV16s","","avx512bw,avx512vl") -TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2sd32, "V2dV2dUi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi","","avx512vbmi") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs","","avx512vbmi,avx512vl") -TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi","","avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_sqrtpd512, "V8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_sqrtps512, "V16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14sd_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ss_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14pd512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ps512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_rsqrt28sd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rsqrt28ss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rsqrt28pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rsqrt28ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er") + +TARGET_BUILTIN(__builtin_ia32_rcp14sd_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rcp14ss_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rcp14pd512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rcp14ps512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_rcp28sd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rcp28ss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rcp28pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_rcp28ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_exp2pd_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512er") +TARGET_BUILTIN(__builtin_ia32_exp2ps_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512er") + +TARGET_BUILTIN(__builtin_ia32_cvttps2dq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvttps2udq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvttpd2udq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_cmpps512_mask, "UsV16fV16fIiUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpps256_mask, "UcV8fV8fIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpps128_mask, "UcV4fV4fIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmppd512_mask, "UcV8dV8dIiUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmppd256_mask, "UcV4dV4dIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmppd128_mask, "UcV2dV2dIiUc", "ncV:128:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_rndscaleps_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rndscalepd_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtps2dq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtps2udq512_mask, "V16iV16fV16iUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtpd2udq512_mask, "V8iV8dV8iUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtdq2ps512_mask, "V16fV16iV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtudq2ps512_mask, "V16fV16iV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps512_mask, "V8fV8dV8fUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph512_mask, "V16sV16fIiV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps512_mask, "V16fV16sV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pabsd512, "V16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pabsq512, "V8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxsd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxsq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxud512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmaxuq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminsd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminsq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminud512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pminuq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmuldq512, "V8LLiV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmuludq512, "V8LLiV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loaddqusi512_mask, "V16iiC*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loaddqudi512_mask, "V8LLiLLiC*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadups512_mask, "V16ffC*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadaps512_mask, "V16fV16fC*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadupd512_mask, "V8ddC*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadapd512_mask, "V8dV8dC*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storedqudi512_mask, "vLLi*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storedqusi512_mask, "vi*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeupd512_mask, "vd*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeapd512_mask, "vV8d*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeups512_mask, "vf*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeaps512_mask, "vV16f*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignd512, "V16iV16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_alignd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_alignq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf64x4_mask, "V4dV8dIiV4dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_mask, "V4fV16fIiV4fUc", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_vpdpbusd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusds128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpbusds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssd128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssd256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssd512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssds128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssds256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl,avx512vnni") +TARGET_BUILTIN(__builtin_ia32_vpdpwssds512, "V16iV16iV16iV16i", "ncV:512:", "avx512vnni") + +TARGET_BUILTIN(__builtin_ia32_gather3div2df, "V2dV2ddC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div2di, "V2LLiV2LLiLLiC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4df, "V4dV4ddC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4di, "V4LLiV4LLiLLiC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4sf, "V4fV4ffC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div4si, "V4iV4iiC*V2LLiUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8sf, "V4fV4ffC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3div8si, "V4iV4iiC*V4LLiUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2df, "V2dV2ddC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv2di, "V2LLiV2LLiLLiC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4df, "V4dV4ddC*V4iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4di, "V4LLiV4LLiLLiC*V4iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4sf, "V4fV4ffC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv4si, "V4iV4iiC*V4iUcIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8sf, "V8fV8ffC*V8iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gather3siv8si, "V8iV8iiC*V8iUcIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_gathersiv8df, "V8dV8ddC*V8iUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv16sf, "V16fV16ffC*V16fUsIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv8df, "V8dV8ddC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv16sf, "V8fV8ffC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv8di, "V8LLiV8LLiLLiC*V8iUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gathersiv16si, "V16iV16iiC*V16iUsIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv8di, "V8LLiV8LLiLLiC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_gatherdiv16si, "V8iV8iiC*V8LLiUcIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv8df, "vd*UcV8iV8dIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv16sf, "vf*UsV16iV16fIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8df, "vd*UcV8LLiV8dIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv16sf, "vf*UcV8LLiV8fIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv8di, "vLLi*UcV8iV8LLiIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scattersiv16si, "vi*UsV16iV16iIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8di, "vLLi*UcV8LLiV8LLiIi", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scatterdiv16si, "vi*UcV8LLiV8iIi", "nV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_gatherpfdpd, "vUcV8iLLiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfdps, "vUsV16iiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfqpd, "vUcV8LLiLLiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_gatherpfqps, "vUcV8LLiiC*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfdpd, "vUcV8iLLi*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfdps, "vUsV16ii*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfqpd, "vUcV8LLiLLi*IiIi", "nV:512:", "avx512pf") +TARGET_BUILTIN(__builtin_ia32_scatterpfqps, "vUcV8LLii*IiIi", "nV:512:", "avx512pf") + +TARGET_BUILTIN(__builtin_ia32_knothi, "UsUs", "nc", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_cmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpq128_mask, "UcV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpw128_mask, "UcV8sV8sIiUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpb256_mask, "UiV32cV32cIiUi", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpd256_mask, "UcV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpq256_mask, "UcV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cmpw256_mask, "UsV16sV16sIiUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpb512_mask, "ULLiV64cV64cIiULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cmpd512_mask, "UsV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpq512_mask, "UcV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpw512_mask, "UiV32sV32sIiUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpb128_mask, "UsV16cV16cIiUs", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpd128_mask, "UcV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpq128_mask, "UcV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpw128_mask, "UcV8sV8sIiUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpb256_mask, "UiV32cV32cIiUi", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpd256_mask, "UcV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpq256_mask, "UcV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_ucmpw256_mask, "UsV16sV16sIiUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpb512_mask, "ULLiV64cV64cIiULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_ucmpd512_mask, "UsV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_ucmpq512_mask, "UcV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_ucmpw512_mask, "UiV32sV32sIiUi", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_pabsb512, "V64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pabsw512, "V32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packssdw512, "V32sV16iV16i", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packsswb512, "V64cV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packusdw512, "V32sV16iV16i", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_packuswb512, "V64cV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_paddusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxsb512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxsw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxub512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaxuw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminsb512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminsw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminub512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pminuw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pshufb512, "V64cV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubsb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubsw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubusb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psubusw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_vpconflictdi_128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictdi_256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictsi_128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictsi_256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpconflictdi_512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512cd") +TARGET_BUILTIN(__builtin_ia32_vpconflictsi_512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512cd") +TARGET_BUILTIN(__builtin_ia32_vplzcntd_512, "V16iV16i", "ncV:512:", "avx512cd") +TARGET_BUILTIN(__builtin_ia32_vplzcntq_512, "V8LLiV8LLi", "ncV:512:", "avx512cd") + +TARGET_BUILTIN(__builtin_ia32_vpopcntd_128, "V4iV4i", "ncV:128:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntq_128, "V2LLiV2LLi", "ncV:128:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntd_256, "V8iV8i", "ncV:256:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntq_256, "V4LLiV4LLi", "ncV:256:", "avx512vpopcntdq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpopcntd_512, "V16iV16i", "ncV:512:", "avx512vpopcntdq") +TARGET_BUILTIN(__builtin_ia32_vpopcntq_512, "V8LLiV8LLi", "ncV:512:", "avx512vpopcntdq") + +TARGET_BUILTIN(__builtin_ia32_vpopcntb_128, "V16cV16c", "ncV:128:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntw_128, "V8sV8s", "ncV:128:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntb_256, "V32cV32c", "ncV:256:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntw_256, "V16sV16s", "ncV:256:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntb_512, "V64cV64c", "ncV:512:", "avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpopcntw_512, "V32sV32s", "ncV:512:", "avx512bitalg") + +TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb128_mask, "UsV16cV16cUs", "ncV:128:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb256_mask, "UiV32cV32cUi", "ncV:256:", "avx512vl,avx512bitalg") +TARGET_BUILTIN(__builtin_ia32_vpshufbitqmb512_mask, "ULLiV64cV64cULLi", "ncV:512:", "avx512bitalg") + +TARGET_BUILTIN(__builtin_ia32_pmulhrsw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmulhuw512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmulhw512, "V32sV32sV32s", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_addpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_addps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_pmaddubsw512, "V32sV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmaddwd512, "V16iV32sV32s", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_addss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_addsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_divsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_mulsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_subsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_maxsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_minsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") + +TARGET_BUILTIN(__builtin_ia32_compressdf128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressdf256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressdi128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressdi256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_compresshi128_mask, "V8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compresshi256_mask, "V16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressqi128_mask, "V16cV16cV16cUs", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressqi256_mask, "V32cV32cV32cUi", "ncV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_compresssf128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compresssf256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compresssi128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compresssi256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredf128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredf256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredi128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoredi256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_compressstorehi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstorehi256_mask, "vV16s*V16sUs", "nV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoreqi128_mask, "vV16c*V16cUs", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoreqi256_mask, "vV32c*V32cUi", "nV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_compressstoresf128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoresf256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoresi128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_compressstoresi256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2dq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2ps_mask, "V4fV2dV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2udq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtpd2udq256_mask, "V4iV4dV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtps2udq128_mask, "V4iV4fV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtps2udq256_mask, "V8iV8fV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttpd2dq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttpd2udq128_mask, "V4iV2dV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttpd2udq256_mask, "V4iV4dV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttps2udq128_mask, "V4iV4fV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvttps2udq256_mask, "V8iV8fV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddf128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddf256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddi128_mask, "V2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expanddi256_mask, "V4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_expandhi128_mask, "V8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandhi256_mask, "V16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandqi128_mask, "V16cV16cV16cUs", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandqi256_mask, "V32cV32cV32cUi", "ncV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_expandloaddf128_mask, "V2dV2dC*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloaddf256_mask, "V4dV4dC*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloaddi128_mask, "V4iV2LLiC*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloaddi256_mask, "V4LLiV4LLiC*V4LLiUc", "nV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_expandloadhi128_mask, "V8sV8sC*V8sUc", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadhi256_mask, "V16sV16sC*V16sUs", "nV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadqi128_mask, "V16cV16cC*V16cUs", "nV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadqi256_mask, "V32cV32cC*V32cUi", "nV:256:", "avx512vl,avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_expandloadsf128_mask, "V4fV4fC*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloadsf256_mask, "V8fV8fC*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloadsi128_mask, "V4iV4iC*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandloadsi256_mask, "V8iV8iC*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsf128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsf256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsi128_mask, "V4iV4iV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_expandsi256_mask, "V8iV8iV8iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexppd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexppd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexpps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getexpps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pabsq128, "V2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pabsq256, "V4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxsq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxsq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxuq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmaxuq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminsq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminsq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminuq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pminuq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscalepd_128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscalepd_256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscaleps_128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rndscaleps_256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefpd128_mask, "V2dV2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefpd256_mask, "V4dV4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefps128_mask, "V4fV4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scalefps256_mask, "V8fV8fV8fV8fUc", "ncV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_scatterdiv2df, "vd*UcV2LLiV2dIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv2di, "vLLi*UcV2LLiV2LLiIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4df, "vd*UcV4LLiV4dIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4di, "vLLi*UcV4LLiV4LLiIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4sf, "vf*UcV2LLiV4fIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv4si, "vi*UcV2LLiV4iIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8sf, "vf*UcV4LLiV4fIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scatterdiv8si, "vi*UcV4LLiV4iIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv2df, "vd*UcV4iV2dIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv2di, "vLLi*UcV4iV2LLiIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4df, "vd*UcV4iV4dIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4di, "vLLi*UcV4iV4LLiIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4sf, "vf*UcV4iV4fIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv4si, "vi*UcV4iV4iIi", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv8sf, "vf*UcV8iV8fIi", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_scattersiv8si, "vi*UcV8iV8iIi", "nV:256:", "avx512vl") + +TARGET_BUILTIN(__builtin_ia32_vpermi2vard128, "V4iV4iV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2vard256, "V8iV8iV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2vard512, "V16iV16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varpd128, "V2dV2dV2LLiV2d", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varpd256, "V4dV4dV4LLiV4d", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varpd512, "V8dV8dV8LLiV8d", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varps128, "V4fV4fV4iV4f", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varps256, "V8fV8fV8iV8f", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varps512, "V16fV16fV16iV16f", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermi2varqi128, "V16cV16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varqi256, "V32cV32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpermi2varqi512, "V64cV64cV64cV64c", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_vpermi2varhi128, "V8sV8sV8sV8s", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_vpermi2varhi256, "V16sV16sV16sV16s", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_vpermi2varhi512, "V32sV32sV32sV32s", "ncV:512:", "avx512bw") + +TARGET_BUILTIN(__builtin_ia32_vpshldd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldd512, "V16iV16iV16iIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshldvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshldvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_mask, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_mask, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_mask, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_mask, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_mask, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_mask, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_mask, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_mask, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_mask, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd128_maskz, "V4iV4iV4iV4iUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd256_maskz, "V8iV8iV8iV8iUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvd512_maskz, "V16iV16iV16iV16iUs", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq128_maskz, "V2LLiV2LLiV2LLiV2LLiUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq256_maskz, "V4LLiV4LLiV4LLiV4LLiUc", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvq512_maskz, "V8LLiV8LLiV8LLiV8LLiUc", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw128_maskz, "V8sV8sV8sV8sUc", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw256_maskz, "V16sV16sV16sV16sUs", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdvw512_maskz, "V32sV32sV32sV32sUi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_vpshrdd128, "V4iV4iV4iIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd256, "V8iV8iV8iIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdd512, "V16iV16iV16iIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq128, "V2LLiV2LLiV2LLiIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdq512, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw128, "V8sV8sV8sIi", "ncV:128:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw256, "V16sV16sV16sIi", "ncV:256:", "avx512vl,avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_vpshrdw512, "V32sV32sV32sIi", "ncV:512:", "avx512vbmi2") + +TARGET_BUILTIN(__builtin_ia32_pmovswb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovuswb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovwb512_mask, "V32cV32sV32cUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtpd2qq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2qq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2qq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2qq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2uqq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2uqq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2ps128_mask, "V4fV2LLiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2ps256_mask, "V4fV4LLiV4fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2qq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2qq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq128_mask, "V2LLiV2dV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq256_mask, "V4LLiV4dV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2qq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2qq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2uqq128_mask, "V2LLiV4fV2LLiUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2uqq256_mask, "V4LLiV4fV4LLiUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps128_mask, "V4fV2LLiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps256_mask, "V4fV4LLiV4fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangepd128_mask, "V2dV2dV2dIiV2dUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangepd256_mask, "V4dV4dV4dIiV4dUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangeps128_mask, "V4fV4fV4fIiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangeps256_mask, "V8fV8fV8fIiV8fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangesd128_round_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangess128_round_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducepd128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducepd256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reduceps128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reduceps256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl,avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducesd_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducess_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_pmovswb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovswb256_mask, "V16cV16sV16cUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovuswb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovuswb256_mask, "V16cV16sV16cUs", "ncV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovwb128_mask, "V16cV8sV16cUc", "ncV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2qq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2pd512_mask, "V8dV8LLiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtqq2ps512_mask, "V8fV8LLiV8fUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2qq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttpd2uqq512_mask, "V8LLiV8dV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2qq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvttps2uqq512_mask, "V8LLiV8fV8LLiUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2pd512_mask, "V8dV8LLiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtuqq2ps512_mask, "V8fV8LLiV8fUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangepd512_mask, "V8dV8dV8dIiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_rangeps512_mask, "V16fV16fV16fIiV16fUsIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reducepd512_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_reduceps512_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_prold512, "V16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolq512, "V8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prold128, "V4iV4iIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prold256, "V8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolq128, "V2LLiV2LLiIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolq256, "V4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolvq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prord512, "V16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorq512, "V8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prolvd128, "V4iV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvd256, "V8iV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prolvq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prord128, "V4iV4iIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prord256, "V8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorq128, "V2LLiV2LLiIi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorq256, "V4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvd512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorvq512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_prorvd128, "V4iV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvd256, "V8iV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_prorvq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pshufhw512, "V32sV32sIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pshuflw512, "V32sV32sIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllv32hi, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllw512, "V32sV32sV8s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllwi512, "V32sV32si", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psllv16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psllv8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_pslldi512, "V16iV16ii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllqi512, "V8LLiV8LLii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlv32hi, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrlv16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psrlv8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psrldi512, "V16iV16ii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlqi512, "V8LLiV8LLii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrav32hi, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrav16hi, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psrav8hi, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_psravq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psravq256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraw512, "V32sV32sV8s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrawi512, "V32sV32si", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrlw512, "V32sV32sV8s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrlwi512, "V32sV32si", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pslldqi512_byteshift, "V8LLiV8LLiIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psrldqi512_byteshift, "V8LLiV8LLiIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_movdqa32load128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa32load256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa32load512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa32store512_mask, "vV16i*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa64load512_mask, "V8LLiV8LLiC*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa64store512_mask, "vV8LLi*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_movdqa32store128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa32store256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64load128_mask, "V2LLiV2LLiC*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64load256_mask, "V4LLiV4LLiC*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64store128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_movdqa64store256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52huq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512ifma") +TARGET_BUILTIN(__builtin_ia32_vpmadd52luq512, "V8LLiV8LLiV8LLiV8LLi", "ncV:512:", "avx512ifma") +TARGET_BUILTIN(__builtin_ia32_vpmadd52huq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52huq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52luq128, "V2LLiV2LLiV2LLiV2LLi", "ncV:128:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmadd52luq256, "V4LLiV4LLiV4LLiV4LLi", "ncV:256:", "avx512ifma,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcomisd, "iV2dV2dIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcomiss, "iV4fV4fIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kunpckdi, "ULLiULLiULLi", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_kunpcksi, "UiUiUi", "nc", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_loaddquhi512_mask, "V32sV32s*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_loaddquqi512_mask, "V64cV64c*V64cULLi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_mask, "V8dV8dV8dV8LLiIiUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd512_maskz, "V8dV8dV8dV8LLiIiUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmps512_mask, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmps512_maskz, "V16fV16fV16fV16iIiUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmsd_mask, "V2dV2dV2dV2LLiIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmsd_maskz, "V2dV2dV2dV2LLiIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmss_mask, "V4fV4fV4fV4iIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_fixupimmss_maskz, "V4fV4fV4fV4iIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexpsd128_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexpss128_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantsd_round_mask, "V2dV2dV2dIiV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantss_round_mask, "V4fV4fV4fIiV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loaddquhi128_mask, "V8sV8s*V8sUc", "nV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddquhi256_mask, "V16sV16s*V16sUs", "nV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddquqi128_mask, "V16cV16c*V16cUs", "nV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddquqi256_mask, "V32cV32c*V32cUi", "nV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_mask, "V2dV2dV2dV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd128_maskz, "V2dV2dV2dV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_mask, "V4dV4dV4dV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmpd256_maskz, "V4dV4dV4dV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps128_mask, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps128_maskz, "V4fV4fV4fV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps256_mask, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fixupimmps256_maskz, "V8fV8fV8fV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadapd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadsd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadapd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadaps128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadss128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_loadaps256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqudi128_mask, "V2LLiV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqudi256_mask, "V4LLiV4LLi*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqusi128_mask, "V4iV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loaddqusi256_mask, "V8iV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadupd128_mask, "V2dV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadupd256_mask, "V4dV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadups128_mask, "V4fV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_loadups256_mask, "V8fV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedquhi512_mask, "vV32s*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquqi512_mask, "vV64c*V64cULLi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquhi128_mask, "vV8s*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquhi256_mask, "vV16s*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquqi128_mask, "vV16c*V16cUs", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storedquqi256_mask, "vV32c*V32cUi", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_storeapd128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storesd128_mask, "vV2d*V2dUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeapd256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeaps128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storess128_mask, "vV4f*V4fUc", "nV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_storeaps256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqudi128_mask, "vV2LLi*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqudi256_mask, "vV4LLi*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqusi128_mask, "vV4i*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storedqusi256_mask, "vV8i*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeupd128_mask, "vV2d*V2dUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeupd256_mask, "vV4d*V4dUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeups128_mask, "vV4f*V4fUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_storeups256_mask, "vV8f*V8fUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14pd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14pd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14ps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rcp14ps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntd_128, "V4iV4i", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntd_256, "V8iV8i", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntq_128, "V2LLiV2LLi", "ncV:128:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vplzcntq_256, "V4LLiV4LLi", "ncV:256:", "avx512cd,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2si32, "iV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi32, "UiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2si32, "iV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2usi32, "UiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2si32, "iV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi32, "UiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2si32, "iV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2usi32, "UiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilpd512, "V8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilps512, "V16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilvarpd512, "V8dV8dV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpermilvarps512, "V16fV16fV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rndscalesd_round_mask, "V2dV2dV2dV2dUcIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rndscaless_round_mask, "V4fV4fV4fV4fUcIiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefpd512_mask, "V8dV8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefps512_mask, "V16fV16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_scalefss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psradi512, "V16iV16ii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psraqi512, "V8LLiV8LLii", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psraq128, "V2LLiV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraq256, "V4LLiV4LLiV2LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraqi128, "V2LLiV2LLii", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_psraqi256, "V4LLiV4LLii", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pslld512, "V16iV16iV4i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllv16si, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psllv8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrad512, "V16iV16iV4i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psraq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrav16si, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrav8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrld512, "V16iV16iV4i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlq512, "V8LLiV8LLiV2LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlv16si, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_psrlv8di, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogd512_mask, "V16iV16iV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogd512_maskz, "V16iV16iV16iV16iIiUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogq512_mask, "V8LLiV8LLiV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogq512_maskz, "V8LLiV8LLiV8LLiV8LLiIiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pternlogd128_mask, "V4iV4iV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogd128_maskz, "V4iV4iV4iV4iIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogd256_mask, "V8iV8iV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogd256_maskz, "V8iV8iV8iV8iIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq128_mask, "V2LLiV2LLiV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq128_maskz, "V2LLiV2LLiV2LLiV2LLiIiUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq256_mask, "V4LLiV4LLiV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pternlogq256_maskz, "V4LLiV4LLiV4LLiV4LLiIiUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_f32x4, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_f64x2, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_i32x4, "V16iV16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_i64x2, "V8LLiV8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shufpd512, "V8dV8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shufps512, "V16fV16fV16fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_shuf_f32x4_256, "V8fV8fV8fIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_f64x2_256, "V4dV4dV4dIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_i32x4_256, "V8iV8iV8iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_shuf_i64x2_256, "V4LLiV4LLiV4LLiIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_sqrtsd_round_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_sqrtss_round_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_rsqrt14pd128_mask, "V2dV2dV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rsqrt14pd256_mask, "V4dV4dV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ps128_mask, "V4fV4fV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_rsqrt14ps256_mask, "V8fV8fV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtb2mask512, "ULLiV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtmask2b512, "V64cULLi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtmask2w512, "V32sUi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtd2mask512, "UsV16i", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtmask2d512, "V16iUs", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtmask2q512, "V8LLiUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtq2mask512, "UcV8LLi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_cvtb2mask128, "UsV16c", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtb2mask256, "UiV32c", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2b128, "V16cUs", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2b256, "V32cUi", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2w128, "V8sUc", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2w256, "V16sUs", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtd2mask128, "UcV4i", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtd2mask256, "UcV8i", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2d128, "V4iUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2d256, "V8iUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2q128, "V2LLiUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtmask2q256, "V4LLiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtq2mask128, "UcV2LLi", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtq2mask256, "UcV4LLi", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovswb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovsdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovsdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovswb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovsdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovswb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovsdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd256_mask, "V4iV4LLiV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovsqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovuswb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovusdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovusdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovuswb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovusdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovuswb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovusdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd256_mask, "V4iV4LLiV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovusqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdb512_mask, "V16cV16iV16cUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovdb512mem_mask, "vV16c*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovwb512mem_mask, "vV32c*V32sUi", "nV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovdw512_mask, "V16sV16iV16sUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovdw512mem_mask, "vV16s*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqb512_mask, "V16cV8LLiV16cUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqb512mem_mask, "vV16c*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqd512_mask, "V8iV8LLiV8iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqd512mem_mask, "vV8i*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqw512_mask, "V8sV8LLiV8sUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovqw512mem_mask, "vV8s*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pmovdb128_mask, "V16cV4iV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovwb128mem_mask, "vV16c*V8sUc", "nV:128:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovdb128mem_mask, "vV16c*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdb256_mask, "V16cV8iV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdb256mem_mask, "vV16c*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovwb256mem_mask, "vV16c*V16sUs", "nV:256:", "avx512vl,avx512bw") +TARGET_BUILTIN(__builtin_ia32_pmovdw128_mask, "V8sV4iV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdw128mem_mask, "vV8s*V4iUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdw256_mask, "V8sV8iV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovdw256mem_mask, "vV8s*V8iUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb128_mask, "V16cV2LLiV16cUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb128mem_mask, "vV16c*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb256_mask, "V16cV4LLiV16cUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqb256mem_mask, "vV16c*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqd128_mask, "V4iV2LLiV4iUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqd128mem_mask, "vV4i*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqd256mem_mask, "vV4i*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw128_mask, "V8sV2LLiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw128mem_mask, "vV8s*V2LLiUc", "nV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw256_mask, "V8sV4LLiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_pmovqw256mem_mask, "vV8s*V4LLiUc", "nV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x8_mask, "V8fV16fIiV8fUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_512_mask, "V2dV8dIiV2dUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x8_mask, "V8iV16iIiV8iUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_512_mask, "V2LLiV8LLiIiV2LLiUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_mask, "V4iV16iIiV4iUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extracti64x4_mask, "V4LLiV8LLiIiV4LLiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_extractf64x2_256_mask, "V2dV4dIiV2dUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti64x2_256_mask, "V2LLiV4LLiIiV2LLiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_extractf32x4_256_mask, "V4fV8fIiV4fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_extracti32x4_256_mask, "V4iV8iIiV4iUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x8, "V16fV16fV8fIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_insertf64x2_512, "V8dV8dV2dIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_inserti32x8, "V16iV16iV8iIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_inserti64x2_512, "V8LLiV8LLiV2LLiIi", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_insertf64x4, "V8dV8dV4dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_inserti64x4, "V8LLiV8LLiV4LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_insertf64x2_256, "V4dV4dV2dIi", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_inserti64x2_256, "V4LLiV4LLiV2LLiIi", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x4_256, "V8fV8fV4fIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_inserti32x4_256, "V8iV8iV4iIi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_insertf32x4, "V16fV16fV4fIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_inserti32x4, "V16iV16iV4iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantpd128_mask, "V2dV2dIiV2dUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantpd256_mask, "V4dV4dIiV4dUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantps128_mask, "V4fV4fIiV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantps256_mask, "V8fV8fIiV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_getmantpd512_mask, "V8dV8dIiV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getmantps512_mask, "V16fV16fIiV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexppd512_mask, "V8dV8dV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_getexpps512_mask, "V16fV16fV16fUsIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3_maskz, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddss3_mask3, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_maskz, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmaddsd3_mask3, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubsd3_mask3, "V2dV2dV2dV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vfmsubss3_mask3, "V4fV4fV4fV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permdf512, "V8dV8dIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permdi512, "V8LLiV8LLiIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarhi512, "V32sV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_permvardf512, "V8dV8dV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvardi512, "V8LLiV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarsf512, "V16fV16fV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarsi512, "V16iV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_permvarqi512, "V64cV64cV64c", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_permvarqi128, "V16cV16cV16c", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvarqi256, "V32cV32cV32c", "ncV:256:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvarhi128, "V8sV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvarhi256, "V16sV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvardf256, "V4dV4dV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_permvardi256, "V4LLiV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclasspd128_mask, "UcV2dIiUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclasspd256_mask, "UcV4dIiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclassps128_mask, "UcV4fIiUc", "ncV:128:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclassps256_mask, "UcV8fIiUc", "ncV:256:", "avx512dq,avx512vl") +TARGET_BUILTIN(__builtin_ia32_fpclassps512_mask, "UsV16fIiUs", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_fpclasspd512_mask, "UcV8dIiUc", "ncV:512:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_fpclasssd_mask, "UcV2dIiUc", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_fpclassss_mask, "UcV4fIiUc", "ncV:128:", "avx512dq") +TARGET_BUILTIN(__builtin_ia32_kandhi, "UsUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kandnhi, "UsUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_korhi, "UsUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kortestchi, "iUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kortestzhi, "iUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kunpckhi, "UsUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kxnorhi, "UsUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_kxorhi, "UsUsUs", "nc", "avx512f") +TARGET_BUILTIN(__builtin_ia32_palignr512, "V64cV64cV64cIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw128, "V8sV16cV16cIi", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw256, "V16sV32cV32cIi", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_dbpsadbw512, "V32sV64cV64cIi", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_psadbw512, "V8LLiV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_compressdf512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressdi512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compresshi512_mask, "V32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressqi512_mask, "V64cV64cV64cULLi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compresssf512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compresssi512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpsd_mask, "UcV2dV2dIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cmpss_mask, "UcV4fV4fIiUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_pshufd512, "V16iV16iIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expanddf512_mask, "V8dV8dV8dUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expanddi512_mask, "V8LLiV8LLiV8LLiUc", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandhi512_mask, "V32sV32sV32sUi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandqi512_mask, "V64cV64cV64cULLi", "ncV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloaddf512_mask, "V8dV8dC*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandloaddi512_mask, "V8LLiV8LLiC*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandloadhi512_mask, "V32sV32sC*V32sUi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadqi512_mask, "V64cV64cC*V64cULLi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_expandloadsf512_mask, "V16fV16fC*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandloadsi512_mask, "V16iV16iC*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandsf512_mask, "V16fV16fV16fUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_expandsi512_mask, "V16iV16iV16iUs", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtps2pd512_mask, "V8dV8fV8dUcIi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstoredf512_mask, "vV8d*V8dUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstoredi512_mask, "vV8LLi*V8LLiUc", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstorehi512_mask, "vV32s*V32sUi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoreqi512_mask, "vV64c*V64cULLi", "nV:512:", "avx512vbmi2") +TARGET_BUILTIN(__builtin_ia32_compressstoresf512_mask, "vV16f*V16fUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_compressstoresi512_mask, "vV16i*V16iUs", "nV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps_mask, "V4fV8sV4fUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtph2ps256_mask, "V8fV8sV8fUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph_mask, "V8sV4fIiV8sUc", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_vcvtps2ph256_mask, "V8sV8fIiV8sUc", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtw2mask512, "UiV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_cvtw2mask128, "UcV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtw2mask256, "UsV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_cvtsd2ss_round_mask, "V4fV4fV2dV4fUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtsi2ss32, "V4fV4fiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtss2sd_round_mask, "V2dV2dV4fV2dUcIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtusi2ss32, "V4fV4fUiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb512_mask, "V64cV64cV64cV64cULLi", "ncV:512:", "avx512vbmi") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb128_mask, "V16cV16cV16cV16cUs", "ncV:128:", "avx512vbmi,avx512vl") +TARGET_BUILTIN(__builtin_ia32_vpmultishiftqb256_mask, "V32cV32cV32cV32cUi", "ncV:256:", "avx512vbmi,avx512vl") // generic select intrinsics -TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "", "") -TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "", "") -TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "", "") -TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "", "") -TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "", "") -TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "", "") -TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "", "") -TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "", "") -TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "", "") -TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "", "") -TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "", "") -TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "", "") -TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "", "") -TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "", "") -TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "", "") -TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "", "") -TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "", "") -TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "", "") +TARGET_BUILTIN(__builtin_ia32_selectb_128, "V16cUsV16cV16c", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectb_256, "V32cUiV32cV32c", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectb_512, "V64cULLiV64cV64c", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_selectw_128, "V8sUcV8sV8s", "ncV:128:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectw_256, "V16sUsV16sV16s", "ncV:256:", "avx512bw,avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectw_512, "V32sUiV32sV32s", "ncV:512:", "avx512bw") +TARGET_BUILTIN(__builtin_ia32_selectd_128, "V4iUcV4iV4i", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectd_256, "V8iUcV8iV8i", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectd_512, "V16iUsV16iV16i", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectq_128, "V2LLiUcV2LLiV2LLi", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectq_256, "V4LLiUcV4LLiV4LLi", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectq_512, "V8LLiUcV8LLiV8LLi", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectps_128, "V4fUcV4fV4f", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectps_256, "V8fUcV8fV8f", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectps_512, "V16fUsV16fV16f", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectpd_128, "V2dUcV2dV2d", "ncV:128:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectpd_256, "V4dUcV4dV4d", "ncV:256:", "avx512vl") +TARGET_BUILTIN(__builtin_ia32_selectpd_512, "V8dUcV8dV8d", "ncV:512:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectss_128, "V4fUcV4fV4f", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_selectsd_128, "V2dUcV2dV2d", "ncV:128:", "avx512f") // MONITORX/MWAITX -TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "", "mwaitx") -TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "", "mwaitx") +TARGET_BUILTIN(__builtin_ia32_monitorx, "vv*UiUi", "n", "mwaitx") +TARGET_BUILTIN(__builtin_ia32_mwaitx, "vUiUiUi", "n", "mwaitx") + +// WAITPKG +TARGET_BUILTIN(__builtin_ia32_umonitor, "vv*", "n", "waitpkg") +TARGET_BUILTIN(__builtin_ia32_umwait, "UcUiUiUi", "n", "waitpkg") +TARGET_BUILTIN(__builtin_ia32_tpause, "UcUiUiUi", "n", "waitpkg") // CLZERO -TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "", "clzero") +TARGET_BUILTIN(__builtin_ia32_clzero, "vv*", "n", "clzero") + +// CLDEMOTE +TARGET_BUILTIN(__builtin_ia32_cldemote, "vvC*", "n", "cldemote") + +// Direct Move +TARGET_BUILTIN(__builtin_ia32_directstore_u32, "vUi*Ui", "n", "movdiri") +TARGET_BUILTIN(__builtin_ia32_movdir64b, "vv*vC*", "n", "movdir64b") + +// PTWRITE +TARGET_BUILTIN(__builtin_ia32_ptwrite32, "vUi", "n", "ptwrite") + +// INVPCID +TARGET_BUILTIN(__builtin_ia32_invpcid, "vUiv*", "nc", "invpcid") // MSVC TARGET_HEADER_BUILTIN(_BitScanForward, "UcUNi*UNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") @@ -1897,14 +1845,14 @@ TARGET_HEADER_BUILTIN(_ReadWriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES TARGET_HEADER_BUILTIN(_ReadBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_WriteBarrier, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__emul, "LLiii", "nh", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__emul, "LLiii", "nch", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__emulu, "ULLiUiUi", "nch", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(_AddressOfReturnAddress, "v*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__stosb, "vUc*Ucz", "nh", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__int2c, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(__ud2, "v", "nr", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__int2c, "v", "nhr", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(__ud2, "v", "nhr", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__readfsbyte, "UcUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__readfsword, "UsUNi", "nh", "intrin.h", ALL_MS_LANGUAGES, "") diff --git a/include/clang/Basic/BuiltinsX86_64.def b/include/clang/Basic/BuiltinsX86_64.def index fe2c887c7e0f5..cc400c0697f91 100644 --- a/include/clang/Basic/BuiltinsX86_64.def +++ b/include/clang/Basic/BuiltinsX86_64.def @@ -27,8 +27,8 @@ TARGET_HEADER_BUILTIN(_BitScanReverse64, "UcUNi*ULLi", "nh", "intrin.h", ALL_MS_ TARGET_HEADER_BUILTIN(__mulh, "LLiLLiLLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__umulh, "ULLiULLiULLi", "nch", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(_mul128, "LLiLLiLLiLLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") -TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nh", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_mul128, "LLiLLiLLiLLi*", "nch", "intrin.h", ALL_MS_LANGUAGES, "") +TARGET_HEADER_BUILTIN(_umul128, "ULLiULLiULLiULLi*", "nch", "intrin.h", ALL_MS_LANGUAGES, "") TARGET_HEADER_BUILTIN(__faststorefence, "v", "nh", "intrin.h", ALL_MS_LANGUAGES, "") @@ -44,50 +44,62 @@ TARGET_HEADER_BUILTIN(_InterlockedCompareExchange128, "UcLLiD*LLiLLiLLi*", "nh", TARGET_BUILTIN(__builtin_ia32_readeflags_u64, "ULLi", "n", "") TARGET_BUILTIN(__builtin_ia32_writeeflags_u64, "vULLi", "n", "") -TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "", "sse") -TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "", "sse2") -TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "", "sse4.2") -TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "", "fsgsbase") -TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "", "fxsr") -TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "", "fxsr") -TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "", "xsave") -TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "", "xsave") -TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "", "xsaveopt") -TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "", "xsaves") -TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "", "xsavec") -TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "", "xsaves") -TARGET_BUILTIN(__builtin_ia32_incsspq, "vULLi", "u", "shstk") -TARGET_BUILTIN(__builtin_ia32_rdsspq, "ULLiULLi", "Un", "shstk") -TARGET_BUILTIN(__builtin_ia32_wrssq, "vULLiv*", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_wrussq, "vULLiv*", "", "shstk") -TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "", "adx") -TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "", "") -TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "", "") -TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "", "rdseed") -TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "", "bmi") -TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "", "bmi2") -TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "", "bmi2") -TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "", "bmi2") -TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "", "tbm") -TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcULLiUiUi", "", "lwp") -TARGET_BUILTIN(__builtin_ia32_lwpval64, "vULLiUiUi", "", "lwp") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtsi2sd64, "V2dV2dLLiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi","","avx512f") -TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi","","avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtss2si64, "LLiV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cvttss2si64, "LLiV4f", "ncV:128:", "sse") +TARGET_BUILTIN(__builtin_ia32_cvtsd2si64, "LLiV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_cvttsd2si64, "LLiV2d", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_movnti64, "vLLi*LLi", "n", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v2di, "LLiV2LLiIi", "ncV:128:", "sse2") +TARGET_BUILTIN(__builtin_ia32_vec_set_v2di, "V2LLiV2LLiLLiIi", "ncV:128:", "sse4.1") +TARGET_BUILTIN(__builtin_ia32_crc32di, "ULLiULLiULLi", "nc", "sse4.2") +TARGET_BUILTIN(__builtin_ia32_vec_ext_v4di, "LLiV4LLiIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_vec_set_v4di, "V4LLiV4LLiLLiIi", "ncV:256:", "avx") +TARGET_BUILTIN(__builtin_ia32_rdfsbase32, "Ui", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_rdfsbase64, "ULLi", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_rdgsbase32, "Ui", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_rdgsbase64, "ULLi", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_wrfsbase32, "vUi", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_wrfsbase64, "vULLi", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_wrgsbase32, "vUi", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_wrgsbase64, "vULLi", "n", "fsgsbase") +TARGET_BUILTIN(__builtin_ia32_fxrstor64, "vv*", "n", "fxsr") +TARGET_BUILTIN(__builtin_ia32_fxsave64, "vv*", "n", "fxsr") +TARGET_BUILTIN(__builtin_ia32_xsave64, "vv*ULLi", "n", "xsave") +TARGET_BUILTIN(__builtin_ia32_xrstor64, "vv*ULLi", "n", "xsave") +TARGET_BUILTIN(__builtin_ia32_xsaveopt64, "vv*ULLi", "n", "xsaveopt") +TARGET_BUILTIN(__builtin_ia32_xrstors64, "vv*ULLi", "n", "xsaves") +TARGET_BUILTIN(__builtin_ia32_xsavec64, "vv*ULLi", "n", "xsavec") +TARGET_BUILTIN(__builtin_ia32_xsaves64, "vv*ULLi", "n", "xsaves") +TARGET_BUILTIN(__builtin_ia32_incsspq, "vULLi", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_rdsspq, "ULLiULLi", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_wrssq, "vULLiv*", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_wrussq, "vULLiv*", "n", "shstk") +TARGET_BUILTIN(__builtin_ia32_addcarryx_u64, "UcUcULLiULLiULLi*", "n", "adx") +TARGET_BUILTIN(__builtin_ia32_addcarry_u64, "UcUcULLiULLiULLi*", "n", "") +TARGET_BUILTIN(__builtin_ia32_subborrow_u64, "UcUcULLiULLiULLi*", "n", "") +TARGET_BUILTIN(__builtin_ia32_rdrand64_step, "UiULLi*", "n", "rdrnd") +TARGET_BUILTIN(__builtin_ia32_rdseed64_step, "UiULLi*", "n", "rdseed") +TARGET_BUILTIN(__builtin_ia32_bextr_u64, "ULLiULLiULLi", "nc", "bmi") +TARGET_BUILTIN(__builtin_ia32_bzhi_di, "ULLiULLiULLi", "nc", "bmi2") +TARGET_BUILTIN(__builtin_ia32_pdep_di, "ULLiULLiULLi", "nc", "bmi2") +TARGET_BUILTIN(__builtin_ia32_pext_di, "ULLiULLiULLi", "nc", "bmi2") +TARGET_BUILTIN(__builtin_ia32_bextri_u64, "ULLiULLiIULLi", "nc", "tbm") +TARGET_BUILTIN(__builtin_ia32_lwpins64, "UcULLiUiUi", "n", "lwp") +TARGET_BUILTIN(__builtin_ia32_lwpval64, "vULLiUiUi", "n", "lwp") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2si64, "LLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtsd2usi64, "ULLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2si64, "LLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvtss2usi64, "ULLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2si64, "LLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttsd2usi64, "ULLiV2dIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2si64, "LLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_vcvttss2usi64, "ULLiV4fIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtsi2sd64, "V2dV2dLLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtsi2ss64, "V4fV4fLLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtusi2sd64, "V2dV2dULLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_cvtusi2ss64, "V4fV4fULLiIi", "ncV:128:", "avx512f") +TARGET_BUILTIN(__builtin_ia32_directstore_u64, "vULi*ULi", "n", "movdiri") +TARGET_BUILTIN(__builtin_ia32_ptwrite64, "vULLi", "n", "ptwrite") #undef BUILTIN #undef TARGET_BUILTIN diff --git a/include/clang/Basic/CMakeLists.txt b/include/clang/Basic/CMakeLists.txt index 821c405913c8b..15bed5adec9e1 100644 --- a/include/clang/Basic/CMakeLists.txt +++ b/include/clang/Basic/CMakeLists.txt @@ -43,6 +43,8 @@ clang_tablegen(AttrHasAttributeImpl.inc -gen-clang-attr-has-attribute-impl # ARM NEON clang_tablegen(arm_neon.inc -gen-arm-neon-sema - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../ SOURCE arm_neon.td TARGET ClangARMNeon) +clang_tablegen(arm_fp16.inc -gen-arm-neon-sema + SOURCE arm_fp16.td + TARGET ClangARMFP16) diff --git a/include/clang/Basic/CapturedStmt.h b/include/clang/Basic/CapturedStmt.h index c4a289b696dd9..324e1b1d3d093 100644 --- a/include/clang/Basic/CapturedStmt.h +++ b/include/clang/Basic/CapturedStmt.h @@ -13,9 +13,10 @@ namespace clang { -/// \brief The different kinds of captured statement. +/// The different kinds of captured statement. enum CapturedRegionKind { CR_Default, + CR_ObjCAtFinally, CR_OpenMP }; diff --git a/include/clang/Basic/CharInfo.h b/include/clang/Basic/CharInfo.h index cc27bbb48e0d1..e6c5e90d346c6 100644 --- a/include/clang/Basic/CharInfo.h +++ b/include/clang/Basic/CharInfo.h @@ -1,4 +1,4 @@ -//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters ------------===// +//===--- clang/Basic/CharInfo.h - Classifying ASCII Characters --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -180,14 +180,15 @@ LLVM_READONLY inline char toUppercase(char c) { /// Return true if this is a valid ASCII identifier. /// -/// Note that this is a very simple check; it does not accept '$' or UCNs as -/// valid identifier characters. -LLVM_READONLY inline bool isValidIdentifier(StringRef S) { - if (S.empty() || !isIdentifierHead(S[0])) +/// Note that this is a very simple check; it does not accept UCNs as valid +/// identifier characters. +LLVM_READONLY inline bool isValidIdentifier(StringRef S, + bool AllowDollar = false) { + if (S.empty() || !isIdentifierHead(S[0], AllowDollar)) return false; for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) - if (!isIdentifierBody(*I)) + if (!isIdentifierBody(*I, AllowDollar)) return false; return true; diff --git a/include/clang/Basic/CommentOptions.h b/include/clang/Basic/CommentOptions.h index 92419f91b741b..6cc9cf6b199c5 100644 --- a/include/clang/Basic/CommentOptions.h +++ b/include/clang/Basic/CommentOptions.h @@ -1,4 +1,4 @@ -//===--- CommentOptions.h - Options for parsing comments -----*- C++ -*-===// +//===- CommentOptions.h - Options for parsing comments ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the clang::CommentOptions interface. -/// +/// Defines the clang::CommentOptions interface. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_COMMENTOPTIONS_H @@ -20,20 +20,20 @@ namespace clang { -/// \brief Options for controlling comment parsing. +/// Options for controlling comment parsing. struct CommentOptions { - typedef std::vector<std::string> BlockCommandNamesTy; + using BlockCommandNamesTy = std::vector<std::string>; - /// \brief Command names to treat as block commands in comments. + /// Command names to treat as block commands in comments. /// Should not include the leading backslash. BlockCommandNamesTy BlockCommandNames; - /// \brief Treat ordinary comments as documentation comments. - bool ParseAllComments; + /// Treat ordinary comments as documentation comments. + bool ParseAllComments = false; - CommentOptions() : ParseAllComments(false) { } + CommentOptions() = default; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_COMMENTOPTIONS_H diff --git a/include/clang/Basic/Cuda.h b/include/clang/Basic/Cuda.h index 1a0731c37a35f..24159e160f3fc 100644 --- a/include/clang/Basic/Cuda.h +++ b/include/clang/Basic/Cuda.h @@ -22,7 +22,9 @@ enum class CudaVersion { CUDA_75, CUDA_80, CUDA_90, - LATEST = CUDA_90, + CUDA_91, + CUDA_92, + LATEST = CUDA_92, }; const char *CudaVersionToString(CudaVersion V); @@ -44,6 +46,21 @@ enum class CudaArch { SM_61, SM_62, SM_70, + SM_72, + GFX600, + GFX601, + GFX700, + GFX701, + GFX702, + GFX703, + GFX704, + GFX801, + GFX802, + GFX803, + GFX810, + GFX900, + GFX902, + LAST, }; const char *CudaArchToString(CudaArch A); @@ -64,6 +81,8 @@ enum class CudaVirtualArch { COMPUTE_61, COMPUTE_62, COMPUTE_70, + COMPUTE_72, + COMPUTE_AMDGCN, }; const char *CudaVirtualArchToString(CudaVirtualArch A); diff --git a/include/clang/Basic/DebugInfoOptions.h b/include/clang/Basic/DebugInfoOptions.h index e7ff4a662b630..037c813c6114f 100644 --- a/include/clang/Basic/DebugInfoOptions.h +++ b/include/clang/Basic/DebugInfoOptions.h @@ -28,7 +28,7 @@ enum DebugInfoKind { /// forward decls for types that could be /// replaced with forward decls in the source /// code. For dynamic C++ classes type info - /// is only emitted int the module that + /// is only emitted into the module that /// contains the classe's vtable. FullDebugInfo /// Generate complete debug info. }; diff --git a/include/clang/Basic/Diagnostic.h b/include/clang/Basic/Diagnostic.h index a7458d45618ee..5205b4c210a6f 100644 --- a/include/clang/Basic/Diagnostic.h +++ b/include/clang/Basic/Diagnostic.h @@ -1,4 +1,4 @@ -//===--- Diagnostic.h - C Language Family Diagnostic Handling ---*- C++ -*-===// +//===- Diagnostic.h - C Language Family Diagnostic Handling -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the Diagnostic-related interfaces. -/// +/// Defines the Diagnostic-related interfaces. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_DIAGNOSTIC_H @@ -22,12 +22,13 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" -#include "llvm/ADT/iterator_range.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include <algorithm> +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Compiler.h" #include <cassert> #include <cstdint> +#include <limits> #include <list> #include <map> #include <memory> @@ -44,15 +45,16 @@ class DiagnosticConsumer; class IdentifierInfo; class LangOptions; class Preprocessor; +class SourceManager; class StoredDiagnostic; namespace tok { - enum TokenKind : unsigned short; +enum TokenKind : unsigned short; -} // end namespace tok +} // namespace tok -/// \brief Annotates a diagnostic with some code that should be +/// Annotates a diagnostic with some code that should be /// inserted, removed, or replaced to fix the problem. /// /// This kind of hint should be used when we are certain that the @@ -63,29 +65,29 @@ namespace tok { /// compilation. class FixItHint { public: - /// \brief Code that should be replaced to correct the error. Empty for an + /// Code that should be replaced to correct the error. Empty for an /// insertion hint. CharSourceRange RemoveRange; - /// \brief Code in the specific range that should be inserted in the insertion + /// Code in the specific range that should be inserted in the insertion /// location. CharSourceRange InsertFromRange; - /// \brief The actual code to insert at the insertion location, as a + /// The actual code to insert at the insertion location, as a /// string. std::string CodeToInsert; - bool BeforePreviousInsertions; + bool BeforePreviousInsertions = false; - /// \brief Empty code modification hint, indicating that no code + /// Empty code modification hint, indicating that no code /// modification is known. - FixItHint() : BeforePreviousInsertions(false) { } + FixItHint() = default; bool isNull() const { return !RemoveRange.isValid(); } - /// \brief Create a code modification hint that inserts the given + /// Create a code modification hint that inserts the given /// code string at a specific location. static FixItHint CreateInsertion(SourceLocation InsertionLoc, StringRef Code, @@ -98,7 +100,7 @@ public: return Hint; } - /// \brief Create a code modification hint that inserts the given + /// Create a code modification hint that inserts the given /// code from \p FromRange at a specific location. static FixItHint CreateInsertionFromRange(SourceLocation InsertionLoc, CharSourceRange FromRange, @@ -111,7 +113,7 @@ public: return Hint; } - /// \brief Create a code modification hint that removes the given + /// Create a code modification hint that removes the given /// source range. static FixItHint CreateRemoval(CharSourceRange RemoveRange) { FixItHint Hint; @@ -122,7 +124,7 @@ public: return CreateRemoval(CharSourceRange::getTokenRange(RemoveRange)); } - /// \brief Create a code modification hint that replaces the given + /// Create a code modification hint that replaces the given /// source range with the given code string. static FixItHint CreateReplacement(CharSourceRange RemoveRange, StringRef Code) { @@ -138,7 +140,7 @@ public: } }; -/// \brief Concrete class used by the front-end to report problems and issues. +/// Concrete class used by the front-end to report problems and issues. /// /// This massages the diagnostics (e.g. handling things like "report warnings /// as errors" and passes them off to the DiagnosticConsumer for reporting to @@ -146,7 +148,7 @@ public: /// SourceManager. class DiagnosticsEngine : public RefCountedBase<DiagnosticsEngine> { public: - /// \brief The level of the diagnostic, after it has been through mapping. + /// The level of the diagnostic, after it has been through mapping. enum Level { Ignored = DiagnosticIDs::Ignored, Note = DiagnosticIDs::Note, @@ -157,45 +159,88 @@ public: }; enum ArgumentKind { - ak_std_string, ///< std::string - ak_c_string, ///< const char * - ak_sint, ///< int - ak_uint, ///< unsigned - ak_tokenkind, ///< enum TokenKind : unsigned - ak_identifierinfo, ///< IdentifierInfo - ak_qualtype, ///< QualType - ak_declarationname, ///< DeclarationName - ak_nameddecl, ///< NamedDecl * - ak_nestednamespec, ///< NestedNameSpecifier * - ak_declcontext, ///< DeclContext * - ak_qualtype_pair, ///< pair<QualType, QualType> - ak_attr ///< Attr * + /// std::string + ak_std_string, + + /// const char * + ak_c_string, + + /// int + ak_sint, + + /// unsigned + ak_uint, + + /// enum TokenKind : unsigned + ak_tokenkind, + + /// IdentifierInfo + ak_identifierinfo, + + /// QualType + ak_qualtype, + + /// DeclarationName + ak_declarationname, + + /// NamedDecl * + ak_nameddecl, + + /// NestedNameSpecifier * + ak_nestednamespec, + + /// DeclContext * + ak_declcontext, + + /// pair<QualType, QualType> + ak_qualtype_pair, + + /// Attr * + ak_attr }; - /// \brief Represents on argument value, which is a union discriminated + /// Represents on argument value, which is a union discriminated /// by ArgumentKind, with a value. - typedef std::pair<ArgumentKind, intptr_t> ArgumentValue; + using ArgumentValue = std::pair<ArgumentKind, intptr_t>; private: - unsigned char AllExtensionsSilenced; // Used by __extension__ - bool SuppressAfterFatalError; // Suppress diagnostics after a fatal error? - bool SuppressAllDiagnostics; // Suppress all diagnostics. - bool ElideType; // Elide common types of templates. - bool PrintTemplateTree; // Print a tree when comparing templates. - bool ShowColors; // Color printing is enabled. - OverloadsShown ShowOverloads; // Which overload candidates to show. - unsigned ErrorLimit; // Cap of # errors emitted, 0 -> no limit. - unsigned TemplateBacktraceLimit; // Cap on depth of template backtrace stack, - // 0 -> no limit. - unsigned ConstexprBacktraceLimit; // Cap on depth of constexpr evaluation - // backtrace stack, 0 -> no limit. + // Used by __extension__ + unsigned char AllExtensionsSilenced = 0; + + // Suppress diagnostics after a fatal error? + bool SuppressAfterFatalError = true; + + // Suppress all diagnostics. + bool SuppressAllDiagnostics = false; + + // Elide common types of templates. + bool ElideType = true; + + // Print a tree when comparing templates. + bool PrintTemplateTree = false; + + // Color printing is enabled. + bool ShowColors = false; + + // Which overload candidates to show. + OverloadsShown ShowOverloads = Ovl_All; + + // Cap of # errors emitted, 0 -> no limit. + unsigned ErrorLimit = 0; + + // Cap on depth of template backtrace stack, 0 -> no limit. + unsigned TemplateBacktraceLimit = 0; + + // Cap on depth of constexpr evaluation backtrace stack, 0 -> no limit. + unsigned ConstexprBacktraceLimit = 0; + IntrusiveRefCntPtr<DiagnosticIDs> Diags; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; - DiagnosticConsumer *Client; + DiagnosticConsumer *Client = nullptr; std::unique_ptr<DiagnosticConsumer> Owner; - SourceManager *SourceMgr; + SourceManager *SourceMgr = nullptr; - /// \brief Mapping information for diagnostics. + /// Mapping information for diagnostics. /// /// Mapping info is packed into four bits per diagnostic. The low three /// bits are the mapping (an instance of diag::Severity), or zero if unset. @@ -211,25 +256,38 @@ private: public: // "Global" configuration state that can actually vary between modules. - unsigned IgnoreAllWarnings : 1; // Ignore all warnings: -w - unsigned EnableAllWarnings : 1; // Enable all warnings. - unsigned WarningsAsErrors : 1; // Treat warnings like errors. - unsigned ErrorsAsFatal : 1; // Treat errors like fatal errors. - unsigned SuppressSystemWarnings : 1; // Suppress warnings in system headers. - diag::Severity ExtBehavior; // Map extensions to warnings or errors? + + // Ignore all warnings: -w + unsigned IgnoreAllWarnings : 1; + + // Enable all warnings. + unsigned EnableAllWarnings : 1; + + // Treat warnings like errors. + unsigned WarningsAsErrors : 1; + + // Treat errors like fatal errors. + unsigned ErrorsAsFatal : 1; + + // Suppress warnings in system headers. + unsigned SuppressSystemWarnings : 1; + + // Map extensions to warnings or errors? + diag::Severity ExtBehavior = diag::Severity::Ignored; DiagState() : IgnoreAllWarnings(false), EnableAllWarnings(false), WarningsAsErrors(false), ErrorsAsFatal(false), - SuppressSystemWarnings(false), ExtBehavior(diag::Severity::Ignored) {} + SuppressSystemWarnings(false) {} - typedef llvm::DenseMap<unsigned, DiagnosticMapping>::iterator iterator; - typedef llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator - const_iterator; + using iterator = llvm::DenseMap<unsigned, DiagnosticMapping>::iterator; + using const_iterator = + llvm::DenseMap<unsigned, DiagnosticMapping>::const_iterator; void setMapping(diag::kind Diag, DiagnosticMapping Info) { DiagMap[Diag] = Info; } + DiagnosticMapping lookupMapping(diag::kind Diag) const { return DiagMap.lookup(Diag); } @@ -240,7 +298,7 @@ private: const_iterator end() const { return DiagMap.end(); } }; - /// \brief Keeps and automatically disposes all DiagStates that we create. + /// Keeps and automatically disposes all DiagStates that we create. std::list<DiagState> DiagStates; /// A mapping from files to the diagnostic states for those files. Lazily @@ -249,12 +307,16 @@ private: public: /// Add an initial diagnostic state. void appendFirst(DiagState *State); + /// Add a new latest state point. void append(SourceManager &SrcMgr, SourceLocation Loc, DiagState *State); + /// Look up the diagnostic state at a given source location. DiagState *lookup(SourceManager &SrcMgr, SourceLocation Loc) const; + /// Determine whether this map is empty. bool empty() const { return Files.empty(); } + /// Clear out this map. void clear() { Files.clear(); @@ -262,13 +324,21 @@ private: CurDiagStateLoc = SourceLocation(); } + /// Produce a debugging dump of the diagnostic state. + LLVM_DUMP_METHOD void dump(SourceManager &SrcMgr, + StringRef DiagName = StringRef()) const; + /// Grab the most-recently-added state point. DiagState *getCurDiagState() const { return CurDiagState; } + /// Get the location at which a diagnostic state was last added. SourceLocation getCurDiagStateLoc() const { return CurDiagStateLoc; } private: - /// \brief Represents a point in source where the diagnostic state was + friend class ASTReader; + friend class ASTWriter; + + /// Represents a point in source where the diagnostic state was /// modified because of a pragma. /// /// 'Loc' can be null if the point represents the diagnostic state @@ -276,8 +346,9 @@ private: struct DiagStatePoint { DiagState *State; unsigned Offset; + DiagStatePoint(DiagState *State, unsigned Offset) - : State(State), Offset(Offset) { } + : State(State), Offset(Offset) {} }; /// Description of the diagnostic states and state transitions for a @@ -287,11 +358,14 @@ private: /// as looking up the DecomposedIncludedLoc for the FileID in the Files /// map would give us this, but we cache it here for performance. File *Parent = nullptr; + /// The offset of this file within its parent. unsigned ParentOffset = 0; + /// Whether this file has any local (not imported from an AST file) /// diagnostic state transitions. bool HasLocalTransitions = false; + /// The points within the file where the state changes. There will always /// be at least one of these (the state on entry to the file). llvm::SmallVector<DiagStatePoint, 4> StateTransitions; @@ -304,21 +378,20 @@ private: /// The initial diagnostic state. DiagState *FirstDiagState; + /// The current diagnostic state. DiagState *CurDiagState; + /// The location at which the current diagnostic state was established. SourceLocation CurDiagStateLoc; /// Get the diagnostic state information for a file. File *getFile(SourceManager &SrcMgr, FileID ID) const; - - friend class ASTReader; - friend class ASTWriter; }; DiagStateMap DiagStatesByLoc; - /// \brief Keeps the DiagState that was active during each diagnostic 'push' + /// Keeps the DiagState that was active during each diagnostic 'push' /// so we can get back at it when we 'pop'. std::vector<DiagState *> DiagStateOnPushStack; @@ -328,41 +401,44 @@ private: void PushDiagStatePoint(DiagState *State, SourceLocation L); - /// \brief Finds the DiagStatePoint that contains the diagnostic state of + /// Finds the DiagStatePoint that contains the diagnostic state of /// the given source location. DiagState *GetDiagStateForLoc(SourceLocation Loc) const { return SourceMgr ? DiagStatesByLoc.lookup(*SourceMgr, Loc) : DiagStatesByLoc.getCurDiagState(); } - /// \brief Sticky flag set to \c true when an error is emitted. + /// Sticky flag set to \c true when an error is emitted. bool ErrorOccurred; - /// \brief Sticky flag set to \c true when an "uncompilable error" occurs. + /// Sticky flag set to \c true when an "uncompilable error" occurs. /// I.e. an error that was not upgraded from a warning by -Werror. bool UncompilableErrorOccurred; - /// \brief Sticky flag set to \c true when a fatal error is emitted. + /// Sticky flag set to \c true when a fatal error is emitted. bool FatalErrorOccurred; - /// \brief Indicates that an unrecoverable error has occurred. + /// Indicates that an unrecoverable error has occurred. bool UnrecoverableErrorOccurred; - /// \brief Counts for DiagnosticErrorTrap to check whether an error occurred + /// Counts for DiagnosticErrorTrap to check whether an error occurred /// during a parsing section, e.g. during parsing a function. unsigned TrapNumErrorsOccurred; unsigned TrapNumUnrecoverableErrorsOccurred; - /// \brief The level of the last diagnostic emitted. + /// The level of the last diagnostic emitted. /// /// This is used to emit continuation diagnostics with the same level as the /// diagnostic that they follow. DiagnosticIDs::Level LastDiagLevel; - unsigned NumWarnings; ///< Number of warnings reported - unsigned NumErrors; ///< Number of errors reported + /// Number of warnings reported + unsigned NumWarnings; - /// \brief A function pointer that converts an opaque diagnostic + /// Number of errors reported + unsigned NumErrors; + + /// A function pointer that converts an opaque diagnostic /// argument to a strings. /// /// This takes the modifiers and argument that was present in the diagnostic. @@ -372,28 +448,29 @@ private: /// avoid redundancy across arguments. /// /// This is a hack to avoid a layering violation between libbasic and libsema. - typedef void (*ArgToStringFnTy)( + using ArgToStringFnTy = void (*)( ArgumentKind Kind, intptr_t Val, StringRef Modifier, StringRef Argument, ArrayRef<ArgumentValue> PrevArgs, SmallVectorImpl<char> &Output, void *Cookie, ArrayRef<intptr_t> QualTypeVals); - void *ArgToStringCookie; + + void *ArgToStringCookie = nullptr; ArgToStringFnTy ArgToStringFn; - /// \brief ID of the "delayed" diagnostic, which is a (typically + /// ID of the "delayed" diagnostic, which is a (typically /// fatal) diagnostic that had to be delayed because it was found /// while emitting another diagnostic. unsigned DelayedDiagID; - /// \brief First string argument for the delayed diagnostic. + /// First string argument for the delayed diagnostic. std::string DelayedDiagArg1; - /// \brief Second string argument for the delayed diagnostic. + /// Second string argument for the delayed diagnostic. std::string DelayedDiagArg2; - /// \brief Optional flag value. + /// Optional flag value. /// /// Some flags accept values, for instance: -Wframe-larger-than=<value> and /// -Rpass=<value>. The content of this string is emitted after the flag name @@ -402,23 +479,28 @@ private: public: explicit DiagnosticsEngine(IntrusiveRefCntPtr<DiagnosticIDs> Diags, - DiagnosticOptions *DiagOpts, + IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts, DiagnosticConsumer *client = nullptr, bool ShouldOwnClient = true); DiagnosticsEngine(const DiagnosticsEngine &) = delete; DiagnosticsEngine &operator=(const DiagnosticsEngine &) = delete; ~DiagnosticsEngine(); + LLVM_DUMP_METHOD void dump() const { DiagStatesByLoc.dump(*SourceMgr); } + LLVM_DUMP_METHOD void dump(StringRef DiagName) const { + DiagStatesByLoc.dump(*SourceMgr, DiagName); + } + const IntrusiveRefCntPtr<DiagnosticIDs> &getDiagnosticIDs() const { return Diags; } - /// \brief Retrieve the diagnostic options. + /// Retrieve the diagnostic options. DiagnosticOptions &getDiagnosticOptions() const { return *DiagOpts; } - typedef llvm::iterator_range<DiagState::const_iterator> diag_mapping_range; + using diag_mapping_range = llvm::iterator_range<DiagState::const_iterator>; - /// \brief Get the current set of diagnostic mappings. + /// Get the current set of diagnostic mappings. diag_mapping_range getDiagnosticMappings() const { const DiagState &DS = *GetCurDiagState(); return diag_mapping_range(DS.begin(), DS.end()); @@ -427,18 +509,20 @@ public: DiagnosticConsumer *getClient() { return Client; } const DiagnosticConsumer *getClient() const { return Client; } - /// \brief Determine whether this \c DiagnosticsEngine object own its client. + /// Determine whether this \c DiagnosticsEngine object own its client. bool ownsClient() const { return Owner != nullptr; } - /// \brief Return the current diagnostic client along with ownership of that + /// Return the current diagnostic client along with ownership of that /// client. std::unique_ptr<DiagnosticConsumer> takeClient() { return std::move(Owner); } bool hasSourceManager() const { return SourceMgr != nullptr; } + SourceManager &getSourceManager() const { assert(SourceMgr && "SourceManager not set!"); return *SourceMgr; } + void setSourceManager(SourceManager *SrcMgr) { assert(DiagStatesByLoc.empty() && "Leftover diag state from a different SourceManager."); @@ -450,54 +534,54 @@ public: // how diagnostics are emitted. // - /// \brief Copies the current DiagMappings and pushes the new copy + /// Copies the current DiagMappings and pushes the new copy /// onto the top of the stack. void pushMappings(SourceLocation Loc); - /// \brief Pops the current DiagMappings off the top of the stack, + /// Pops the current DiagMappings off the top of the stack, /// causing the new top of the stack to be the active mappings. /// /// \returns \c true if the pop happens, \c false if there is only one /// DiagMapping on the stack. bool popMappings(SourceLocation Loc); - /// \brief Set the diagnostic client associated with this diagnostic object. + /// Set the diagnostic client associated with this diagnostic object. /// /// \param ShouldOwnClient true if the diagnostic object should take /// ownership of \c client. void setClient(DiagnosticConsumer *client, bool ShouldOwnClient = true); - /// \brief Specify a limit for the number of errors we should + /// Specify a limit for the number of errors we should /// emit before giving up. /// /// Zero disables the limit. void setErrorLimit(unsigned Limit) { ErrorLimit = Limit; } - /// \brief Specify the maximum number of template instantiation + /// Specify the maximum number of template instantiation /// notes to emit along with a given diagnostic. void setTemplateBacktraceLimit(unsigned Limit) { TemplateBacktraceLimit = Limit; } - /// \brief Retrieve the maximum number of template instantiation + /// Retrieve the maximum number of template instantiation /// notes to emit along with a given diagnostic. unsigned getTemplateBacktraceLimit() const { return TemplateBacktraceLimit; } - /// \brief Specify the maximum number of constexpr evaluation + /// Specify the maximum number of constexpr evaluation /// notes to emit along with a given diagnostic. void setConstexprBacktraceLimit(unsigned Limit) { ConstexprBacktraceLimit = Limit; } - /// \brief Retrieve the maximum number of constexpr evaluation + /// Retrieve the maximum number of constexpr evaluation /// notes to emit along with a given diagnostic. unsigned getConstexprBacktraceLimit() const { return ConstexprBacktraceLimit; } - /// \brief When set to true, any unmapped warnings are ignored. + /// When set to true, any unmapped warnings are ignored. /// /// If this and WarningsAsErrors are both set, then this one wins. void setIgnoreAllWarnings(bool Val) { @@ -507,7 +591,7 @@ public: return GetCurDiagState()->IgnoreAllWarnings; } - /// \brief When set to true, any unmapped ignored warnings are no longer + /// When set to true, any unmapped ignored warnings are no longer /// ignored. /// /// If this and IgnoreAllWarnings are both set, then that one wins. @@ -518,7 +602,7 @@ public: return GetCurDiagState()->EnableAllWarnings; } - /// \brief When set to true, any warnings reported are issued as errors. + /// When set to true, any warnings reported are issued as errors. void setWarningsAsErrors(bool Val) { GetCurDiagState()->WarningsAsErrors = Val; } @@ -526,15 +610,15 @@ public: return GetCurDiagState()->WarningsAsErrors; } - /// \brief When set to true, any error reported is made a fatal error. + /// When set to true, any error reported is made a fatal error. void setErrorsAsFatal(bool Val) { GetCurDiagState()->ErrorsAsFatal = Val; } bool getErrorsAsFatal() const { return GetCurDiagState()->ErrorsAsFatal; } - /// \brief When set to true (the default), suppress further diagnostics after + /// When set to true (the default), suppress further diagnostics after /// a fatal error. void setSuppressAfterFatalError(bool Val) { SuppressAfterFatalError = Val; } - /// \brief When set to true mask warnings that come from system headers. + /// When set to true mask warnings that come from system headers. void setSuppressSystemWarnings(bool Val) { GetCurDiagState()->SuppressSystemWarnings = Val; } @@ -542,7 +626,7 @@ public: return GetCurDiagState()->SuppressSystemWarnings; } - /// \brief Suppress all diagnostics, to silence the front end when we + /// Suppress all diagnostics, to silence the front end when we /// know that we don't want any more diagnostics to be passed along to the /// client void setSuppressAllDiagnostics(bool Val = true) { @@ -550,22 +634,22 @@ public: } bool getSuppressAllDiagnostics() const { return SuppressAllDiagnostics; } - /// \brief Set type eliding, to skip outputting same types occurring in + /// Set type eliding, to skip outputting same types occurring in /// template types. void setElideType(bool Val = true) { ElideType = Val; } bool getElideType() { return ElideType; } - /// \brief Set tree printing, to outputting the template difference in a + /// Set tree printing, to outputting the template difference in a /// tree format. void setPrintTemplateTree(bool Val = false) { PrintTemplateTree = Val; } bool getPrintTemplateTree() { return PrintTemplateTree; } - /// \brief Set color printing, so the type diffing will inject color markers + /// Set color printing, so the type diffing will inject color markers /// into the output. void setShowColors(bool Val = false) { ShowColors = Val; } bool getShowColors() { return ShowColors; } - /// \brief Specify which overload candidates to show when overload resolution + /// Specify which overload candidates to show when overload resolution /// fails. /// /// By default, we show all candidates. @@ -574,7 +658,7 @@ public: } OverloadsShown getShowOverloads() const { return ShowOverloads; } - /// \brief Pretend that the last diagnostic issued was ignored, so any + /// Pretend that the last diagnostic issued was ignored, so any /// subsequent notes will be suppressed, or restore a prior ignoring /// state after ignoring some diagnostics and their notes, possibly in /// the middle of another diagnostic. @@ -586,14 +670,14 @@ public: LastDiagLevel = Ignored ? DiagnosticIDs::Ignored : DiagnosticIDs::Warning; } - /// \brief Determine whether the previous diagnostic was ignored. This can + /// Determine whether the previous diagnostic was ignored. This can /// be used by clients that want to determine whether notes attached to a /// diagnostic will be suppressed. bool isLastDiagnosticIgnored() const { return LastDiagLevel == DiagnosticIDs::Ignored; } - /// \brief Controls whether otherwise-unmapped extension diagnostics are + /// Controls whether otherwise-unmapped extension diagnostics are /// mapped onto ignore/warning/error. /// /// This corresponds to the GCC -pedantic and -pedantic-errors option. @@ -604,7 +688,7 @@ public: return GetCurDiagState()->ExtBehavior; } - /// \brief Counter bumped when an __extension__ block is/ encountered. + /// Counter bumped when an __extension__ block is/ encountered. /// /// When non-zero, all extension diagnostics are entirely silenced, no /// matter how they are mapped. @@ -612,7 +696,7 @@ public: void DecrementAllExtensionsSilenced() { --AllExtensionsSilenced; } bool hasAllExtensionsSilenced() { return AllExtensionsSilenced != 0; } - /// \brief This allows the client to specify that certain warnings are + /// This allows the client to specify that certain warnings are /// ignored. /// /// Notes can never be mapped, errors can only be mapped to fatal, and @@ -622,7 +706,7 @@ public: /// take affect. It can be null if we are setting the latest state. void setSeverity(diag::kind Diag, diag::Severity Map, SourceLocation Loc); - /// \brief Change an entire diagnostic group (e.g. "unknown-pragmas") to + /// Change an entire diagnostic group (e.g. "unknown-pragmas") to /// have the specified mapping. /// /// \returns true (and ignores the request) if "Group" was unknown, false @@ -637,21 +721,21 @@ public: diag::Severity Map, SourceLocation Loc = SourceLocation()); - /// \brief Set the warning-as-error flag for the given diagnostic group. + /// Set the warning-as-error flag for the given diagnostic group. /// /// This function always only operates on the current diagnostic state. /// /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupWarningAsError(StringRef Group, bool Enabled); - /// \brief Set the error-as-fatal flag for the given diagnostic group. + /// Set the error-as-fatal flag for the given diagnostic group. /// /// This function always only operates on the current diagnostic state. /// /// \returns True if the given group is unknown, false otherwise. bool setDiagnosticGroupErrorAsFatal(StringRef Group, bool Enabled); - /// \brief Add the specified mapping to all diagnostics of the specified + /// Add the specified mapping to all diagnostics of the specified /// flavor. /// /// Mainly to be used by -Wno-everything to disable all warnings but allow @@ -661,14 +745,14 @@ public: bool hasErrorOccurred() const { return ErrorOccurred; } - /// \brief Errors that actually prevent compilation, not those that are + /// Errors that actually prevent compilation, not those that are /// upgraded from a warning by -Werror. bool hasUncompilableErrorOccurred() const { return UncompilableErrorOccurred; } bool hasFatalErrorOccurred() const { return FatalErrorOccurred; } - /// \brief Determine whether any kind of unrecoverable error has occurred. + /// Determine whether any kind of unrecoverable error has occurred. bool hasUnrecoverableErrorOccurred() const { return FatalErrorOccurred || UnrecoverableErrorOccurred; } @@ -679,7 +763,7 @@ public: this->NumWarnings = NumWarnings; } - /// \brief Return an ID for a diagnostic with the specified format string and + /// Return an ID for a diagnostic with the specified format string and /// level. /// /// If this is the first request for this diagnostic, it is registered and @@ -693,7 +777,7 @@ public: StringRef(FormatString, N - 1)); } - /// \brief Converts a diagnostic argument (as an intptr_t) into the string + /// Converts a diagnostic argument (as an intptr_t) into the string /// that represents it. void ConvertArgToString(ArgumentKind Kind, intptr_t Val, StringRef Modifier, StringRef Argument, @@ -709,13 +793,13 @@ public: ArgToStringCookie = Cookie; } - /// \brief Note that the prior diagnostic was emitted by some other + /// Note that the prior diagnostic was emitted by some other /// \c DiagnosticsEngine, and we may be attaching a note to that diagnostic. void notePriorDiagnosticFrom(const DiagnosticsEngine &Other) { LastDiagLevel = Other.LastDiagLevel; } - /// \brief Reset the state of the diagnostic object to its initial + /// Reset the state of the diagnostic object to its initial /// configuration. void Reset(); @@ -723,7 +807,7 @@ public: // DiagnosticsEngine classification and reporting interfaces. // - /// \brief Determine whether the diagnostic is known to be ignored. + /// Determine whether the diagnostic is known to be ignored. /// /// This can be used to opportunistically avoid expensive checks when it's /// known for certain that the diagnostic has been suppressed at the @@ -736,7 +820,7 @@ public: diag::Severity::Ignored; } - /// \brief Based on the way the client configured the DiagnosticsEngine + /// Based on the way the client configured the DiagnosticsEngine /// object, classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticConsumer. /// @@ -750,7 +834,7 @@ public: return (Level)Diags->getDiagnosticLevel(DiagID, Loc, *this); } - /// \brief Issue the message to the client. + /// Issue the message to the client. /// /// This actually returns an instance of DiagnosticBuilder which emits the /// diagnostics (through @c ProcessDiag) when it is destroyed. @@ -763,10 +847,12 @@ public: void Report(const StoredDiagnostic &storedDiag); - /// \brief Determine whethere there is already a diagnostic in flight. - bool isDiagnosticInFlight() const { return CurDiagID != ~0U; } + /// Determine whethere there is already a diagnostic in flight. + bool isDiagnosticInFlight() const { + return CurDiagID != std::numeric_limits<unsigned>::max(); + } - /// \brief Set the "delayed" diagnostic that will be emitted once + /// Set the "delayed" diagnostic that will be emitted once /// the current diagnostic completes. /// /// If a diagnostic is already in-flight but the front end must @@ -790,38 +876,39 @@ public: void SetDelayedDiagnostic(unsigned DiagID, StringRef Arg1 = "", StringRef Arg2 = ""); - /// \brief Clear out the current diagnostic. - void Clear() { CurDiagID = ~0U; } + /// Clear out the current diagnostic. + void Clear() { CurDiagID = std::numeric_limits<unsigned>::max(); } - /// \brief Return the value associated with this diagnostic flag. + /// Return the value associated with this diagnostic flag. StringRef getFlagValue() const { return FlagValue; } private: - /// \brief Report the delayed diagnostic. - void ReportDelayed(); - // This is private state used by DiagnosticBuilder. We put it here instead of // in DiagnosticBuilder in order to keep DiagnosticBuilder a small lightweight // object. This implementation choice means that we can only have one // diagnostic "in flight" at a time, but this seems to be a reasonable // tradeoff to keep these objects small. Assertions verify that only one // diagnostic is in flight at a time. - friend class DiagnosticIDs; - friend class DiagnosticBuilder; friend class Diagnostic; - friend class PartialDiagnostic; + friend class DiagnosticBuilder; friend class DiagnosticErrorTrap; + friend class DiagnosticIDs; + friend class PartialDiagnostic; - /// \brief The location of the current diagnostic that is in flight. + /// Report the delayed diagnostic. + void ReportDelayed(); + + /// The location of the current diagnostic that is in flight. SourceLocation CurDiagLoc; - /// \brief The ID of the current diagnostic that is in flight. + /// The ID of the current diagnostic that is in flight. /// - /// This is set to ~0U when there is no diagnostic in flight. + /// This is set to std::numeric_limits<unsigned>::max() when there is no + /// diagnostic in flight. unsigned CurDiagID; enum { - /// \brief The maximum number of arguments we can hold. + /// The maximum number of arguments we can hold. /// /// We currently only support up to 10 arguments (%0-%9). A single /// diagnostic with more than that almost certainly has to be simplified @@ -829,33 +916,33 @@ private: MaxArguments = 10, }; - /// \brief The number of entries in Arguments. + /// The number of entries in Arguments. signed char NumDiagArgs; - /// \brief Specifies whether an argument is in DiagArgumentsStr or + /// Specifies whether an argument is in DiagArgumentsStr or /// in DiagArguments. /// /// This is an array of ArgumentKind::ArgumentKind enum values, one for each /// argument. unsigned char DiagArgumentsKind[MaxArguments]; - /// \brief Holds the values of each string argument for the current + /// Holds the values of each string argument for the current /// diagnostic. /// /// This is only used when the corresponding ArgumentKind is ak_std_string. std::string DiagArgumentsStr[MaxArguments]; - /// \brief The values for the various substitution positions. + /// The values for the various substitution positions. /// /// This is used when the argument is not an std::string. The specific /// value is mangled into an intptr_t and the interpretation depends on /// exactly what sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; - /// \brief The list of ranges added to this diagnostic. + /// The list of ranges added to this diagnostic. SmallVector<CharSourceRange, 8> DiagRanges; - /// \brief If valid, provides a hint with some code to insert, remove, + /// If valid, provides a hint with some code to insert, remove, /// or modify at a particular position. SmallVector<FixItHint, 8> DiagFixItHints; @@ -874,7 +961,7 @@ private: return Mapping; } - /// \brief Used to report a diagnostic that is finally fully formed. + /// Used to report a diagnostic that is finally fully formed. /// /// \returns true if the diagnostic was emitted, false if it was suppressed. bool ProcessDiag() { @@ -884,13 +971,16 @@ private: /// @name Diagnostic Emission /// @{ protected: + friend class ASTReader; + friend class ASTWriter; + // Sema requires access to the following functions because the current design // of SFINAE requires it to use its own SemaDiagnosticBuilder, which needs to // access us directly to ensure we minimize the emitted code for the common // Sema::Diag() patterns. friend class Sema; - /// \brief Emit the current diagnostic and clear the diagnostic state. + /// Emit the current diagnostic and clear the diagnostic state. /// /// \param Force Emit the diagnostic regardless of suppression settings. bool EmitCurrentDiagnostic(bool Force = false); @@ -900,12 +990,9 @@ protected: SourceLocation getCurrentDiagLoc() const { return CurDiagLoc; } /// @} - - friend class ASTReader; - friend class ASTWriter; }; -/// \brief RAII class that determines when any errors have occurred +/// RAII class that determines when any errors have occurred /// between the time the instance was created and the time it was /// queried. class DiagnosticErrorTrap { @@ -915,21 +1002,21 @@ class DiagnosticErrorTrap { public: explicit DiagnosticErrorTrap(DiagnosticsEngine &Diag) - : Diag(Diag) { reset(); } + : Diag(Diag) { reset(); } - /// \brief Determine whether any errors have occurred since this + /// Determine whether any errors have occurred since this /// object instance was created. bool hasErrorOccurred() const { return Diag.TrapNumErrorsOccurred > NumErrors; } - /// \brief Determine whether any unrecoverable errors have occurred since this + /// Determine whether any unrecoverable errors have occurred since this /// object instance was created. bool hasUnrecoverableErrorOccurred() const { return Diag.TrapNumUnrecoverableErrorsOccurred > NumUnrecoverableErrors; } - /// \brief Set to initial state of "no errors occurred". + /// Set to initial state of "no errors occurred". void reset() { NumErrors = Diag.TrapNumErrorsOccurred; NumUnrecoverableErrors = Diag.TrapNumUnrecoverableErrorsOccurred; @@ -940,7 +1027,7 @@ public: // DiagnosticBuilder //===----------------------------------------------------------------------===// -/// \brief A little helper class used to produce diagnostics. +/// A little helper class used to produce diagnostics. /// /// This is constructed by the DiagnosticsEngine::Report method, and /// allows insertion of extra information (arguments and source ranges) into @@ -953,22 +1040,23 @@ public: /// the common fields to registers, eliminating increments of the NumArgs field, /// for example. class DiagnosticBuilder { + friend class DiagnosticsEngine; + friend class PartialDiagnostic; + mutable DiagnosticsEngine *DiagObj = nullptr; mutable unsigned NumArgs = 0; - /// \brief Status variable indicating if this diagnostic is still active. + /// Status variable indicating if this diagnostic is still active. /// // NOTE: This field is redundant with DiagObj (IsActive iff (DiagObj == 0)), // but LLVM is not currently smart enough to eliminate the null check that // Emit() would end up with if we used that as our status variable. mutable bool IsActive = false; - /// \brief Flag indicating that this diagnostic is being emitted via a + /// Flag indicating that this diagnostic is being emitted via a /// call to ForceEmit. mutable bool IsForceEmit = false; - friend class DiagnosticsEngine; - DiagnosticBuilder() = default; explicit DiagnosticBuilder(DiagnosticsEngine *diagObj) @@ -978,24 +1066,22 @@ class DiagnosticBuilder { diagObj->DiagFixItHints.clear(); } - friend class PartialDiagnostic; - protected: void FlushCounts() { DiagObj->NumDiagArgs = NumArgs; } - /// \brief Clear out the current diagnostic. + /// Clear out the current diagnostic. void Clear() const { DiagObj = nullptr; IsActive = false; IsForceEmit = false; } - /// \brief Determine whether this diagnostic is still active. + /// Determine whether this diagnostic is still active. bool isActive() const { return IsActive; } - /// \brief Force the diagnostic builder to emit the diagnostic now. + /// Force the diagnostic builder to emit the diagnostic now. /// /// Once this function has been called, the DiagnosticBuilder object /// should not be used again before it is destroyed. @@ -1033,23 +1119,23 @@ public: DiagnosticBuilder &operator=(const DiagnosticBuilder &) = delete; - /// \brief Emits the diagnostic. + /// Emits the diagnostic. ~DiagnosticBuilder() { Emit(); } - /// \brief Retrieve an empty diagnostic builder. + /// Retrieve an empty diagnostic builder. static DiagnosticBuilder getEmpty() { - return DiagnosticBuilder(); + return {}; } - /// \brief Forces the diagnostic to be emitted. + /// Forces the diagnostic to be emitted. const DiagnosticBuilder &setForceEmit() const { IsForceEmit = true; return *this; } - /// \brief Conversion of DiagnosticBuilder to bool always returns \c true. + /// Conversion of DiagnosticBuilder to bool always returns \c true. /// /// This allows is to be used in boolean error contexts (where \c true is /// used to indicate that an error has occurred), like: @@ -1089,11 +1175,12 @@ public: }; struct AddFlagValue { - explicit AddFlagValue(StringRef V) : Val(V) {} StringRef Val; + + explicit AddFlagValue(StringRef V) : Val(V) {} }; -/// \brief Register a value for the flag in the current diagnostic. This +/// Register a value for the flag in the current diagnostic. This /// value will be shown as the suffix "=value" after the flag name. It is /// useful in cases where the diagnostic flag accepts values (e.g., /// -Rpass or -Wframe-larger-than). @@ -1199,14 +1286,15 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, /// A nullability kind paired with a bit indicating whether it used a /// context-sensitive keyword. -typedef std::pair<NullabilityKind, bool> DiagNullabilityKind; +using DiagNullabilityKind = std::pair<NullabilityKind, bool>; const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, DiagNullabilityKind nullability); inline DiagnosticBuilder DiagnosticsEngine::Report(SourceLocation Loc, unsigned DiagID) { - assert(CurDiagID == ~0U && "Multiple diagnostics in flight at once!"); + assert(CurDiagID == std::numeric_limits<unsigned>::max() && + "Multiple diagnostics in flight at once!"); CurDiagLoc = Loc; CurDiagID = DiagID; FlagValue.clear(); @@ -1231,7 +1319,7 @@ class Diagnostic { public: explicit Diagnostic(const DiagnosticsEngine *DO) : DiagObj(DO) {} Diagnostic(const DiagnosticsEngine *DO, StringRef storedDiagMessage) - : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} + : DiagObj(DO), StoredDiagMessage(storedDiagMessage) {} const DiagnosticsEngine *getDiags() const { return DiagObj; } unsigned getID() const { return DiagObj->CurDiagID; } @@ -1241,7 +1329,7 @@ public: unsigned getNumArgs() const { return DiagObj->NumDiagArgs; } - /// \brief Return the kind of the specified index. + /// Return the kind of the specified index. /// /// Based on the kind of argument, the accessors below can be used to get /// the value. @@ -1252,7 +1340,7 @@ public: return (DiagnosticsEngine::ArgumentKind)DiagObj->DiagArgumentsKind[Idx]; } - /// \brief Return the provided argument string specified by \p Idx. + /// Return the provided argument string specified by \p Idx. /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_std_string const std::string &getArgStdStr(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_std_string && @@ -1260,7 +1348,7 @@ public: return DiagObj->DiagArgumentsStr[Idx]; } - /// \brief Return the specified C string argument. + /// Return the specified C string argument. /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_c_string const char *getArgCStr(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_c_string && @@ -1268,7 +1356,7 @@ public: return reinterpret_cast<const char*>(DiagObj->DiagArgumentsVal[Idx]); } - /// \brief Return the specified signed integer argument. + /// Return the specified signed integer argument. /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_sint int getArgSInt(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_sint && @@ -1276,7 +1364,7 @@ public: return (int)DiagObj->DiagArgumentsVal[Idx]; } - /// \brief Return the specified unsigned integer argument. + /// Return the specified unsigned integer argument. /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_uint unsigned getArgUInt(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_uint && @@ -1284,7 +1372,7 @@ public: return (unsigned)DiagObj->DiagArgumentsVal[Idx]; } - /// \brief Return the specified IdentifierInfo argument. + /// Return the specified IdentifierInfo argument. /// \pre getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo const IdentifierInfo *getArgIdentifier(unsigned Idx) const { assert(getArgKind(Idx) == DiagnosticsEngine::ak_identifierinfo && @@ -1292,7 +1380,7 @@ public: return reinterpret_cast<IdentifierInfo*>(DiagObj->DiagArgumentsVal[Idx]); } - /// \brief Return the specified non-string argument in an opaque form. + /// Return the specified non-string argument in an opaque form. /// \pre getArgKind(Idx) != DiagnosticsEngine::ak_std_string intptr_t getRawArg(unsigned Idx) const { assert(getArgKind(Idx) != DiagnosticsEngine::ak_std_string && @@ -1300,7 +1388,7 @@ public: return DiagObj->DiagArgumentsVal[Idx]; } - /// \brief Return the number of source ranges associated with this diagnostic. + /// Return the number of source ranges associated with this diagnostic. unsigned getNumRanges() const { return DiagObj->DiagRanges.size(); } @@ -1311,7 +1399,7 @@ public: return DiagObj->DiagRanges[Idx]; } - /// \brief Return an array reference for this diagnostic's ranges. + /// Return an array reference for this diagnostic's ranges. ArrayRef<CharSourceRange> getRanges() const { return DiagObj->DiagRanges; } @@ -1329,20 +1417,20 @@ public: return DiagObj->DiagFixItHints; } - /// \brief Format this diagnostic into a string, substituting the + /// Format this diagnostic into a string, substituting the /// formal arguments into the %0 slots. /// /// The result is appended onto the \p OutStr array. void FormatDiagnostic(SmallVectorImpl<char> &OutStr) const; - /// \brief Format the given format-string into the output buffer using the + /// Format the given format-string into the output buffer using the /// arguments stored in this diagnostic. void FormatDiagnostic(const char *DiagStr, const char *DiagEnd, SmallVectorImpl<char> &OutStr) const; }; /** - * \brief Represents a diagnostic in a form that can be retained until its + * Represents a diagnostic in a form that can be retained until its * corresponding source manager is destroyed. */ class StoredDiagnostic { @@ -1363,7 +1451,7 @@ public: ArrayRef<CharSourceRange> Ranges, ArrayRef<FixItHint> Fixits); - /// \brief Evaluates true when this object stores a diagnostic. + /// Evaluates true when this object stores a diagnostic. explicit operator bool() const { return !Message.empty(); } unsigned getID() const { return ID; } @@ -1373,7 +1461,8 @@ public: void setLocation(FullSourceLoc Loc) { this->Loc = Loc; } - typedef std::vector<CharSourceRange>::const_iterator range_iterator; + using range_iterator = std::vector<CharSourceRange>::const_iterator; + range_iterator range_begin() const { return Ranges.begin(); } range_iterator range_end() const { return Ranges.end(); } unsigned range_size() const { return Ranges.size(); } @@ -1382,7 +1471,8 @@ public: return llvm::makeArrayRef(Ranges); } - typedef std::vector<FixItHint>::const_iterator fixit_iterator; + using fixit_iterator = std::vector<FixItHint>::const_iterator; + fixit_iterator fixit_begin() const { return FixIts.begin(); } fixit_iterator fixit_end() const { return FixIts.end(); } unsigned fixit_size() const { return FixIts.size(); } @@ -1392,7 +1482,7 @@ public: } }; -/// \brief Abstract interface, implemented by clients of the front-end, which +/// Abstract interface, implemented by clients of the front-end, which /// formats and prints fully processed diagnostics. class DiagnosticConsumer { protected: @@ -1401,14 +1491,13 @@ protected: public: DiagnosticConsumer() = default; - virtual ~DiagnosticConsumer(); unsigned getNumErrors() const { return NumErrors; } unsigned getNumWarnings() const { return NumWarnings; } virtual void clear() { NumWarnings = NumErrors = 0; } - /// \brief Callback to inform the diagnostic client that processing + /// Callback to inform the diagnostic client that processing /// of a source file is beginning. /// /// Note that diagnostics may be emitted outside the processing of a source @@ -1422,25 +1511,25 @@ public: virtual void BeginSourceFile(const LangOptions &LangOpts, const Preprocessor *PP = nullptr) {} - /// \brief Callback to inform the diagnostic client that processing + /// Callback to inform the diagnostic client that processing /// of a source file has ended. /// /// The diagnostic client should assume that any objects made available via /// BeginSourceFile() are inaccessible. virtual void EndSourceFile() {} - /// \brief Callback to inform the diagnostic client that processing of all + /// Callback to inform the diagnostic client that processing of all /// source files has ended. virtual void finish() {} - /// \brief Indicates whether the diagnostics handled by this + /// Indicates whether the diagnostics handled by this /// DiagnosticConsumer should be included in the number of diagnostics /// reported by DiagnosticsEngine. /// /// The default implementation returns true. virtual bool IncludeInDiagnosticCounts() const; - /// \brief Handle this diagnostic, reporting it to the user or + /// Handle this diagnostic, reporting it to the user or /// capturing it to a log as needed. /// /// The default implementation just keeps track of the total number of @@ -1449,7 +1538,7 @@ public: const Diagnostic &Info); }; -/// \brief A diagnostic client that ignores all diagnostics. +/// A diagnostic client that ignores all diagnostics. class IgnoringDiagConsumer : public DiagnosticConsumer { virtual void anchor(); @@ -1459,7 +1548,7 @@ class IgnoringDiagConsumer : public DiagnosticConsumer { } }; -/// \brief Diagnostic consumer that forwards diagnostics along to an +/// Diagnostic consumer that forwards diagnostics along to an /// existing, already-initialized diagnostic consumer. /// class ForwardingDiagnosticConsumer : public DiagnosticConsumer { @@ -1467,7 +1556,6 @@ class ForwardingDiagnosticConsumer : public DiagnosticConsumer { public: ForwardingDiagnosticConsumer(DiagnosticConsumer &Target) : Target(Target) {} - ~ForwardingDiagnosticConsumer() override; void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, @@ -1485,6 +1573,7 @@ struct TemplateDiffTypes { unsigned PrintFromType : 1; unsigned ElideType : 1; unsigned ShowColors : 1; + // The printer sets this variable to true if the template diff was used. unsigned TemplateDiffUsed : 1; }; @@ -1493,13 +1582,12 @@ struct TemplateDiffTypes { /// attribute. The character itself will be not be printed. const char ToggleHighlight = 127; - /// ProcessWarningOptions - Initialize the diagnostic client and process the /// warning options specified on the command line. void ProcessWarningOptions(DiagnosticsEngine &Diags, const DiagnosticOptions &Opts, bool ReportDiags = true); -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_BASIC_DIAGNOSTIC_H diff --git a/include/clang/Basic/Diagnostic.td b/include/clang/Basic/Diagnostic.td index 52ccf350e651e..2a0f1e6385d37 100644 --- a/include/clang/Basic/Diagnostic.td +++ b/include/clang/Basic/Diagnostic.td @@ -39,6 +39,15 @@ def SFINAE_Suppress : SFINAEResponse; def SFINAE_Report : SFINAEResponse; def SFINAE_AccessControl : SFINAEResponse; +// Textual substitutions which may be performed on the text of diagnostics +class TextSubstitution<string Text> { + string Substitution = Text; + // TODO: These are only here to allow substitutions to be declared inline with + // diagnostics + string Component = ""; + string CategoryName = ""; +} + // Diagnostic Categories. These can be applied to groups or individual // diagnostics to specify a category. class DiagCategory<string Name> { diff --git a/include/clang/Basic/DiagnosticASTKinds.td b/include/clang/Basic/DiagnosticASTKinds.td index 215580b2e9b66..4fa1db96cb897 100644 --- a/include/clang/Basic/DiagnosticASTKinds.td +++ b/include/clang/Basic/DiagnosticASTKinds.td @@ -273,6 +273,8 @@ def note_odr_objc_synthesize_ivar_here : Note< "property is synthesized to ivar %0 here">; // Importing C++ ASTs +def note_odr_friend : Note<"friend declared here">; +def note_odr_missing_friend : Note<"no corresponding friend here">; def err_odr_different_num_template_parameters : Error< "template parameter lists have a different number of parameters (%0 vs %1)">; def note_odr_template_parameter_list : Note< diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 82ca27b7345e3..61a73541d0b37 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -94,6 +94,9 @@ def remark_module_lock_failure : Remark< "could not acquire lock file for module '%0': %1">, InGroup<ModuleBuild>; def remark_module_lock_timeout : Remark< "timed out waiting to acquire lock file for module '%0'">, InGroup<ModuleBuild>; +def err_module_shadowed : Error<"import of shadowed module '%0'">, DefaultFatal; +def err_module_build_shadowed_submodule : Error< + "build a shadowed submodule '%0'">, DefaultFatal; def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, DefaultFatal; def err_module_prebuilt : Error< @@ -165,6 +168,10 @@ def ext_clang_enable_if : Extension<"'enable_if' is a clang extension">, InGroup<GccCompat>; def ext_clang_diagnose_if : Extension<"'diagnose_if' is a clang extension">, InGroup<GccCompat>; +def err_too_large_for_fixed_point : Error< + "this value is too large for this fixed point type">; +def err_fixed_point_not_enabled : Error<"compile with " + "'-ffixed-point' to enable fixed point types">; // SEH def err_seh_expected_handler : Error< @@ -185,6 +192,7 @@ def note_invalid_subexpr_in_const_expr : Note< def err_target_unknown_triple : Error< "unknown target triple '%0', please use -triple or -arch">; def err_target_unknown_cpu : Error<"unknown target CPU '%0'">; +def note_valid_options : Note<"valid target CPU values are: %0">; def err_target_unsupported_cpu_for_micromips : Error< "micromips is not supported for target CPU '%0'">; def err_target_unknown_abi : Error<"unknown target ABI '%0'">; @@ -200,6 +208,10 @@ def err_target_unsupported_execute_only : Error< "execute only is not supported for the %0 sub-architecture">; def err_opt_not_valid_with_opt : Error< "option '%0' cannot be specified with '%1'">; +def err_opt_not_valid_without_opt : Error< + "option '%0' cannot be specified without '%1'">; +def err_opt_not_valid_on_target : Error< + "option '%0' cannot be specified on this target">; // Source manager def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; @@ -226,6 +238,10 @@ def note_mt_message : Note<"[rewriter] %0">; def warn_arcmt_nsalloc_realloc : Warning<"[rewriter] call returns pointer to GC managed memory; it will become unmanaged in ARC">; def err_arcmt_nsinvocation_ownership : Error<"NSInvocation's %0 is not safe to be used with an object with ownership other than __unsafe_unretained">; +// OpenCL C++. +def err_openclcxx_not_supported : Error< + "'%0' is not supported in OpenCL C++">; + // OpenMP def err_omp_more_one_clause : Error< "directive '#pragma omp %0' cannot contain more than one '%1' clause%select{| with '%3' name modifier| with 'source' dependence}2">; diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 41b5e42b44322..a6be0595e1ae9 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -11,6 +11,8 @@ let Component = "Driver" in { def err_drv_no_such_file : Error<"no such file or directory: '%0'">; def err_drv_unsupported_opt : Error<"unsupported option '%0'">; +def err_drv_unsupported_opt_with_suggestion + : Error<"unsupported option '%0', did you mean '%1'?">; def err_drv_unsupported_opt_for_target : Error< "unsupported option '%0' for target '%1'">; def err_drv_unsupported_option_argument : Error< @@ -22,6 +24,10 @@ 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_riscv_arch_name : Error< + "invalid arch name '%0', %1">; +def err_drv_invalid_riscv_ext_arch_name : Error< + "invalid arch name '%0', %1 '%2'">; def err_drv_cuda_bad_gpu_arch : Error<"Unsupported CUDA gpu architecture: %0">; def err_drv_no_cuda_installation : Error< "cannot find CUDA installation. Provide its path via --cuda-path, or pass " @@ -34,7 +40,8 @@ def err_drv_cuda_version_unsupported : Error< "but installation at %3 is %4. Use --cuda-path to specify a different CUDA " "install, pass a different GPU arch with --cuda-gpu-arch, or pass " "--no-cuda-version-check.">; -def err_drv_cuda_nvptx_host : Error<"unsupported use of NVPTX for host compilation.">; +def err_drv_cuda_host_arch : Error<"unsupported architecture '%0' for host compilation.">; +def err_drv_mix_cuda_hip : Error<"Mixed Cuda and HIP compilation is not supported.">; 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< @@ -112,6 +119,18 @@ def err_drv_invalid_argument_to_fdebug_prefix_map : Error< "invalid argument '%0' to -fdebug-prefix-map">; def err_drv_malformed_sanitizer_blacklist : Error< "malformed sanitizer blacklist: '%0'">; +def err_drv_duplicate_config : Error< + "no more than one option '--config' is allowed">; +def err_drv_config_file_not_exist : Error< + "configuration file '%0' does not exist">; +def err_drv_config_file_not_found : Error< + "configuration file '%0' cannot be found">; +def note_drv_config_file_searched_in : Note< + "was searched for in the directory: %0">; +def err_drv_cannot_read_config_file : Error< + "cannot read configuration file '%0'">; +def err_drv_nested_config_file: Error< + "option '--config' is not allowed inside configuration file">; def err_target_unsupported_arch : Error<"the target architecture '%0' is not supported by the target '%1'">; @@ -123,9 +142,14 @@ def err_arch_unsupported_isa def err_drv_I_dash_not_supported : Error< "'%0' not supported, please use -iquote instead">; def err_drv_unknown_argument : Error<"unknown argument: '%0'">; +def err_drv_unknown_argument_with_suggestion + : Error<"unknown argument '%0', did you mean '%1'?">; def warn_drv_unknown_argument_clang_cl : Warning< "unknown argument ignored in clang-cl: '%0'">, InGroup<UnknownArgument>; +def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning< + "unknown argument ignored in clang-cl '%0' (did you mean '%1'?)">, + InGroup<UnknownArgument>; def warn_drv_ycyu_no_arg_clang_cl : Warning< "support for '%0' without a filename not implemented yet; flag ignored">, @@ -169,6 +193,8 @@ def err_drv_mg_requires_m_or_mm : Error< "option '-MG' requires '-M' or '-MM'">; def err_drv_unknown_objc_runtime : Error< "unknown or ill-formed Objective-C runtime '%0'">; +def err_drv_gnustep_objc_runtime_incompatible_binary : Error< + "GNUstep Objective-C runtime version %0 incompatible with target binary format">; def err_drv_emit_llvm_link : Error< "-emit-llvm cannot be used when linking">; def err_drv_optimization_remark_pattern : Error< @@ -184,6 +210,9 @@ def err_drv_expecting_fopenmp_with_fopenmp_targets : Error< def warn_drv_omp_offload_target_duplicate : Warning< "The OpenMP offloading target '%0' is similar to target '%1' already specified - will be ignored.">, InGroup<OpenMPTarget>; +def warn_drv_omp_offload_target_missingbcruntime : Warning< + "No library '%0' found in the default clang lib directory or in LIBRARY_PATH. Expect degraded performance due to no inlining of runtime functions on target devices.">, + InGroup<OpenMPTarget>; def err_drv_bitcode_unsupported_on_toolchain : Error< "-fembed-bitcode is not supported on versions of iOS prior to 6.0">; @@ -239,15 +268,12 @@ def warn_incompatible_sysroot : Warning<"using sysroot for '%0' but targeting '% InGroup<DiagGroup<"incompatible-sysroot">>; def warn_debug_compression_unavailable : Warning<"cannot compress debug sections (zlib not installed)">, InGroup<DiagGroup<"debug-compression-unavailable">>; -def warn_drv_enabling_rtti_with_exceptions : Warning< - "implicitly enabling rtti for exception handling">, - InGroup<DiagGroup<"rtti-for-exceptions">>; def warn_drv_disabling_vptr_no_rtti_default : Warning< "implicitly disabling vptr sanitizer because rtti wasn't enabled">, InGroup<AutoDisableVptrSanitizer>; def warn_drv_object_size_disabled_O0 : Warning< "the object size sanitizer has no effect at -O0, but is explicitly enabled: %0">, - InGroup<InvalidCommandLineArgument>; + InGroup<InvalidCommandLineArgument>, DefaultWarnNoWerror; def note_drv_command_failed_diag_msg : Note< "diagnostic msg: %0">; @@ -266,6 +292,9 @@ def err_analyzer_config_multiple_values : Error< def err_drv_invalid_hvx_length : Error< "-mhvx-length is not supported without a -mhvx/-mhvx= flag">; +def warn_drv_vectorize_needs_hvx : Warning< + "auto-vectorization requires HVX, use -mhvx to enable it">, + InGroup<OptionIgnored>; def err_drv_modules_validate_once_requires_timestamp : Error< "option '-fmodules-validate-once-per-build-session' requires " @@ -310,10 +339,16 @@ def warn_drv_unsupported_longcalls : Warning< "ignoring '-mlong-calls' option as it is not currently supported with " "%select{|the implicit usage of }0-mabicalls">, InGroup<OptionIgnored>; -def warn_drv_unsupported_abicalls : Warning< - "ignoring '-mabicalls' option as it cannot be used with " - "non position-independent code and the N64 ABI">, +def warn_drv_unsupported_pic_with_mabicalls : Warning< + "ignoring '%0' option as it cannot be used with " + "%select{implicit usage of|}1 -mabicalls and the N64 ABI">, InGroup<OptionIgnored>; +def err_drv_unsupported_noabicalls_pic : Error< + "position-independent code requires ‘-mabicalls’">; +def err_drv_unsupported_indirect_jump_opt : Error< + "'-mindirect-jump=%0' is unsupported with the '%1' architecture">; +def err_drv_unknown_indirect_jump_opt : Error< + "unknown '-mindirect-jump=' option '%0'">; def warn_drv_unable_to_find_directory_expected : Warning< "unable to find %0 directory, expected to be in '%1'">, @@ -342,4 +377,16 @@ def warn_drv_fine_grained_bitfield_accesses_ignored : Warning< def note_drv_verify_prefix_spelling : Note< "-verify prefixes must start with a letter and contain only alphanumeric" " characters, hyphens, and underscores">; + +def warn_drv_experimental_isel_incomplete : Warning< + "-fexperimental-isel support for the '%0' architecture is incomplete">, + InGroup<ExperimentalISel>; + +def warn_drv_experimental_isel_incomplete_opt : Warning< + "-fexperimental-isel support is incomplete for this architecture at the current optimization level">, + InGroup<ExperimentalISel>; + +def warn_drv_moutline_unsupported_opt : Warning< + "The '%0' architecture does not support -moutline; flag ignored">, + InGroup<OptionIgnored>; } diff --git a/include/clang/Basic/DiagnosticError.h b/include/clang/Basic/DiagnosticError.h index 6b4b073736a8d..3f7be46c9505e 100644 --- a/include/clang/Basic/DiagnosticError.h +++ b/include/clang/Basic/DiagnosticError.h @@ -15,7 +15,7 @@ namespace clang { -/// \brief Carries a Clang diagnostic in an llvm::Error. +/// Carries a Clang diagnostic in an llvm::Error. /// /// Users should emit the stored diagnostic using the DiagnosticsEngine. class DiagnosticError : public llvm::ErrorInfo<DiagnosticError> { diff --git a/include/clang/Basic/DiagnosticFrontendKinds.td b/include/clang/Basic/DiagnosticFrontendKinds.td index b25181f256586..6add448871fe5 100644 --- a/include/clang/Basic/DiagnosticFrontendKinds.td +++ b/include/clang/Basic/DiagnosticFrontendKinds.td @@ -118,6 +118,8 @@ def err_fe_invalid_alignment : Error< "invalid value '%1' in '%0'; alignment must be a power of 2">; def err_fe_invalid_wchar_type : Error<"invalid wchar_t type '%0'; must be one of 'char', 'short', 'int'">; +def err_fe_invalid_exception_model + : Error<"invalid exception model '%0' for target '%1'">; def warn_fe_serialized_diag_merge_failure : Warning< "unable to merge a subprocess's serialized diagnostics">, @@ -234,4 +236,9 @@ def err_invalid_vfs_overlay : Error< def warn_option_invalid_ocl_version : Warning< "OpenCL version %0 does not support the option '%1'">, InGroup<Deprecated>; + +def warn_stdlibcxx_not_found : Warning< + "include path for stdlibc++ headers not found; pass '-std=libc++' on the " + "command line to use the libc++ standard library instead">, + InGroup<DiagGroup<"stdlibcxx-not-found">>; } diff --git a/include/clang/Basic/DiagnosticGroups.td b/include/clang/Basic/DiagnosticGroups.td index c23183c81ac8b..7087db7f0fb89 100644 --- a/include/clang/Basic/DiagnosticGroups.td +++ b/include/clang/Basic/DiagnosticGroups.td @@ -31,6 +31,10 @@ def AutoDisableVptrSanitizer : DiagGroup<"auto-disable-vptr-sanitizer">; def Availability : DiagGroup<"availability">; def Section : DiagGroup<"section">; def AutoImport : DiagGroup<"auto-import">; +def FrameworkHdrQuotedInclude : DiagGroup<"quoted-include-in-framework-header">; +def FrameworkIncludePrivateFromPublic : + DiagGroup<"framework-include-private-from-public">; +def FrameworkHdrAtImport : DiagGroup<"atimport-in-framework-header">; def CXX14BinaryLiteral : DiagGroup<"c++14-binary-literal">; def CXXPre14CompatBinaryLiteral : DiagGroup<"c++98-c++11-compat-binary-literal">; def GNUBinaryLiteral : DiagGroup<"gnu-binary-literal">; @@ -116,6 +120,7 @@ def DeprecatedDynamicExceptionSpec def DeprecatedImplementations :DiagGroup<"deprecated-implementations">; def DeprecatedIncrementBool : DiagGroup<"deprecated-increment-bool">; def DeprecatedRegister : DiagGroup<"deprecated-register">; +def DeprecatedThisCapture : DiagGroup<"deprecated-this-capture">; def DeprecatedWritableStr : DiagGroup<"deprecated-writable-strings", [CXX11CompatDeprecatedWritableStr]>; // FIXME: Why is DeprecatedImplementations not in this group? @@ -124,6 +129,7 @@ def Deprecated : DiagGroup<"deprecated", [DeprecatedAttributes, DeprecatedDynamicExceptionSpec, DeprecatedIncrementBool, DeprecatedRegister, + DeprecatedThisCapture, DeprecatedWritableStr]>, DiagCategory<"Deprecations">; @@ -151,8 +157,10 @@ def Exceptions : DiagGroup<"exceptions">; def GNUEmptyInitializer : DiagGroup<"gnu-empty-initializer">; def GNUEmptyStruct : DiagGroup<"gnu-empty-struct">; def ExtraTokens : DiagGroup<"extra-tokens">; +def CXX98CompatExtraSemi : DiagGroup<"c++98-compat-extra-semi">; def CXX11ExtraSemi : DiagGroup<"c++11-extra-semi">; -def ExtraSemi : DiagGroup<"extra-semi", [CXX11ExtraSemi]>; +def ExtraSemi : DiagGroup<"extra-semi", [CXX98CompatExtraSemi, + CXX11ExtraSemi]>; def GNUFlexibleArrayInitializer : DiagGroup<"gnu-flexible-array-initializer">; def GNUFlexibleArrayUnionMember : DiagGroup<"gnu-flexible-array-union-member">; @@ -196,6 +204,7 @@ def CXX98Compat : DiagGroup<"c++98-compat", def CXX98CompatPedantic : DiagGroup<"c++98-compat-pedantic", [CXX98Compat, CXX98CompatBindToTemporaryCopy, + CXX98CompatExtraSemi, CXXPre14CompatPedantic, CXXPre17CompatPedantic, CXXPre2aCompatPedantic]>; @@ -263,6 +272,11 @@ def ShiftOpParentheses: DiagGroup<"shift-op-parentheses">; def OverloadedShiftOpParentheses: DiagGroup<"overloaded-shift-op-parentheses">; def DanglingElse: DiagGroup<"dangling-else">; def DanglingField : DiagGroup<"dangling-field">; +def DanglingInitializerList : DiagGroup<"dangling-initializer-list">; +def ReturnStackAddress : DiagGroup<"return-stack-address">; +def Dangling : DiagGroup<"dangling", [DanglingField, + DanglingInitializerList, + ReturnStackAddress]>; def DistributedObjectModifiers : DiagGroup<"distributed-object-modifiers">; def ExpansionToDefined : DiagGroup<"expansion-to-defined">; def FlagEnum : DiagGroup<"flag-enum">; @@ -282,6 +296,8 @@ def IncompatiblePointerTypes [IncompatiblePointerTypesDiscardsQualifiers, IncompatibleFunctionPointerTypes]>; def IncompleteUmbrella : DiagGroup<"incomplete-umbrella">; +def IncompleteFrameworkModuleDeclaration + : DiagGroup<"incomplete-framework-module-declaration">; def NonModularIncludeInFrameworkModule : DiagGroup<"non-modular-include-in-framework-module">; def NonModularIncludeInModule : DiagGroup<"non-modular-include-in-module", @@ -380,7 +396,11 @@ def DeprecatedObjCIsaUsage : DiagGroup<"deprecated-objc-isa-usage">; def ExplicitInitializeCall : DiagGroup<"explicit-initialize-call">; def Packed : DiagGroup<"packed">; def Padded : DiagGroup<"padded">; + def PessimizingMove : DiagGroup<"pessimizing-move">; +def ReturnStdMoveInCXX11 : DiagGroup<"return-std-move-in-c++11">; +def ReturnStdMove : DiagGroup<"return-std-move">; + def PointerArith : DiagGroup<"pointer-arith">; def PoundWarning : DiagGroup<"#warnings">; def PoundPragmaMessage : DiagGroup<"#pragma-messages">, @@ -391,13 +411,13 @@ def RedeclaredClassMember : DiagGroup<"redeclared-class-member">; def GNURedeclaredEnum : DiagGroup<"gnu-redeclared-enum">; def RedundantMove : DiagGroup<"redundant-move">; def Register : DiagGroup<"register", [DeprecatedRegister]>; -def ReturnStackAddress : DiagGroup<"return-stack-address">; def ReturnTypeCLinkage : DiagGroup<"return-type-c-linkage">; def ReturnType : DiagGroup<"return-type", [ReturnTypeCLinkage]>; def BindToTemporaryCopy : DiagGroup<"bind-to-temporary-copy", [CXX98CompatBindToTemporaryCopy]>; def SelfAssignmentField : DiagGroup<"self-assign-field">; -def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentField]>; +def SelfAssignmentOverloaded : DiagGroup<"self-assign-overloaded">; +def SelfAssignment : DiagGroup<"self-assign", [SelfAssignmentOverloaded, SelfAssignmentField]>; def SelfMove : DiagGroup<"self-move">; def SemiBeforeMethodBody : DiagGroup<"semicolon-before-method-body">; def Sentinel : DiagGroup<"sentinel">; @@ -426,6 +446,13 @@ def : DiagGroup<"synth">; def SizeofArrayArgument : DiagGroup<"sizeof-array-argument">; def SizeofArrayDecay : DiagGroup<"sizeof-array-decay">; def SizeofPointerMemaccess : DiagGroup<"sizeof-pointer-memaccess">; +def MemsetTransposedArgs : DiagGroup<"memset-transposed-args">; +def DynamicClassMemaccess : DiagGroup<"dynamic-class-memaccess">; +def NonTrivialMemaccess : DiagGroup<"nontrivial-memaccess">; +def SuspiciousBzero : DiagGroup<"suspicious-bzero">; +def SuspiciousMemaccess : DiagGroup<"suspicious-memaccess", + [SizeofPointerMemaccess, DynamicClassMemaccess, + NonTrivialMemaccess, MemsetTransposedArgs, SuspiciousBzero]>; def StaticInInline : DiagGroup<"static-in-inline">; def StaticLocalInInline : DiagGroup<"static-local-in-inline">; def GNUStaticFloatInit : DiagGroup<"gnu-static-float-init">; @@ -435,13 +462,16 @@ def StringCompare : DiagGroup<"string-compare">; def StringPlusInt : DiagGroup<"string-plus-int">; def StringPlusChar : DiagGroup<"string-plus-char">; def StrncatSize : DiagGroup<"strncat-size">; +def TautologicalTypeLimitCompare : DiagGroup<"tautological-type-limit-compare">; def TautologicalUnsignedZeroCompare : DiagGroup<"tautological-unsigned-zero-compare">; def TautologicalUnsignedEnumZeroCompare : DiagGroup<"tautological-unsigned-enum-zero-compare">; +def TautologicalInRangeCompare : DiagGroup<"tautological-constant-in-range-compare", + [TautologicalTypeLimitCompare, + TautologicalUnsignedZeroCompare, + TautologicalUnsignedEnumZeroCompare]>; def TautologicalOutOfRangeCompare : DiagGroup<"tautological-constant-out-of-range-compare">; def TautologicalConstantCompare : DiagGroup<"tautological-constant-compare", - [TautologicalUnsignedZeroCompare, - TautologicalUnsignedEnumZeroCompare, - TautologicalOutOfRangeCompare]>; + [TautologicalOutOfRangeCompare]>; def TautologicalPointerCompare : DiagGroup<"tautological-pointer-compare">; def TautologicalOverlapCompare : DiagGroup<"tautological-overlap-compare">; def TautologicalUndefinedCompare : DiagGroup<"tautological-undefined-compare">; @@ -509,8 +539,13 @@ def UninitializedStaticSelfInit : DiagGroup<"static-self-init">; def Uninitialized : DiagGroup<"uninitialized", [UninitializedSometimes, UninitializedStaticSelfInit]>; def IgnoredPragmaIntrinsic : DiagGroup<"ignored-pragma-intrinsic">; +// #pragma optimize is often used to avoid to work around MSVC codegen bugs or +// to disable inlining. It's not completely clear what alternative to suggest +// (#pragma clang optimize, noinline) so suggest nothing for now. +def IgnoredPragmaOptimize : DiagGroup<"ignored-pragma-optimize">; def UnknownPragmas : DiagGroup<"unknown-pragmas">; -def IgnoredPragmas : DiagGroup<"ignored-pragmas", [IgnoredPragmaIntrinsic]>; +def IgnoredPragmas : DiagGroup<"ignored-pragmas", + [IgnoredPragmaIntrinsic, IgnoredPragmaOptimize]>; def PragmaClangAttribute : DiagGroup<"pragma-clang-attribute">; def PragmaPackSuspiciousInclude : DiagGroup<"pragma-pack-suspicious-include">; def PragmaPack : DiagGroup<"pragma-pack", [PragmaPackSuspiciousInclude]>; @@ -712,7 +747,12 @@ def IntToVoidPointerCast : DiagGroup<"int-to-void-pointer-cast">; def IntToPointerCast : DiagGroup<"int-to-pointer-cast", [IntToVoidPointerCast]>; -def Move : DiagGroup<"move", [PessimizingMove, RedundantMove, SelfMove]>; +def Move : DiagGroup<"move", [ + PessimizingMove, + RedundantMove, + ReturnStdMove, + SelfMove + ]>; def Extra : DiagGroup<"extra", [ MissingFieldInitializers, @@ -982,3 +1022,10 @@ def UnknownArgument : DiagGroup<"unknown-argument">; // A warning group for warnings about code that clang accepts when // compiling OpenCL C/C++ but which is not compatible with the SPIR spec. def SpirCompat : DiagGroup<"spir-compat">; + +// Warning for the experimental-isel options. +def ExperimentalISel : DiagGroup<"experimental-isel">; + +// A warning group specifically for warnings related to function +// multiversioning. +def FunctionMultiVersioning : DiagGroup<"function-multiversion">; diff --git a/include/clang/Basic/DiagnosticIDs.h b/include/clang/Basic/DiagnosticIDs.h index b4ea85ba853cc..b610af953fba1 100644 --- a/include/clang/Basic/DiagnosticIDs.h +++ b/include/clang/Basic/DiagnosticIDs.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the Diagnostic IDs-related interfaces. +/// Defines the Diagnostic IDs-related interfaces. /// //===----------------------------------------------------------------------===// @@ -60,7 +60,7 @@ namespace clang { class CustomDiagInfo; - /// \brief All of the diagnostics that can be emitted by the frontend. + /// All of the diagnostics that can be emitted by the frontend. typedef unsigned kind; // Get typedefs for common diagnostics. @@ -158,25 +158,25 @@ public: } }; -/// \brief Used for handling and querying diagnostic IDs. +/// Used for handling and querying diagnostic IDs. /// /// Can be used and shared by multiple Diagnostics for multiple translation units. class DiagnosticIDs : public RefCountedBase<DiagnosticIDs> { public: - /// \brief The level of the diagnostic, after it has been through mapping. + /// The level of the diagnostic, after it has been through mapping. enum Level { Ignored, Note, Remark, Warning, Error, Fatal }; private: - /// \brief Information for uniquing and looking up custom diags. + /// Information for uniquing and looking up custom diags. diag::CustomDiagInfo *CustomDiagInfo; public: DiagnosticIDs(); ~DiagnosticIDs(); - /// \brief Return an ID for a diagnostic with the specified format string and + /// Return an ID for a diagnostic with the specified format string and /// level. /// /// If this is the first request for this diagnostic, it is registered and @@ -191,31 +191,31 @@ public: // Diagnostic classification and reporting interfaces. // - /// \brief Given a diagnostic ID, return a description of the issue. + /// Given a diagnostic ID, return a description of the issue. StringRef getDescription(unsigned DiagID) const; - /// \brief Return true if the unmapped diagnostic levelof the specified + /// Return true if the unmapped diagnostic levelof the specified /// diagnostic ID is a Warning or Extension. /// /// This only works on builtin diagnostics, not custom ones, and is not /// legal to call on NOTEs. static bool isBuiltinWarningOrExtension(unsigned DiagID); - /// \brief Return true if the specified diagnostic is mapped to errors by + /// Return true if the specified diagnostic is mapped to errors by /// default. static bool isDefaultMappingAsError(unsigned DiagID); - /// \brief Determine whether the given built-in diagnostic ID is a Note. + /// Determine whether the given built-in diagnostic ID is a Note. static bool isBuiltinNote(unsigned DiagID); - /// \brief Determine whether the given built-in diagnostic ID is for an + /// Determine whether the given built-in diagnostic ID is for an /// extension of some sort. static bool isBuiltinExtensionDiag(unsigned DiagID) { bool ignored; return isBuiltinExtensionDiag(DiagID, ignored); } - /// \brief Determine whether the given built-in diagnostic ID is for an + /// Determine whether the given built-in diagnostic ID is for an /// extension of some sort, and whether it is enabled by default. /// /// This also returns EnabledByDefault, which is set to indicate whether the @@ -225,53 +225,53 @@ public: static bool isBuiltinExtensionDiag(unsigned DiagID, bool &EnabledByDefault); - /// \brief Return the lowest-level warning option that enables the specified + /// Return the lowest-level warning option that enables the specified /// diagnostic. /// /// If there is no -Wfoo flag that controls the diagnostic, this returns null. static StringRef getWarningOptionForDiag(unsigned DiagID); - /// \brief Return the category number that a specified \p DiagID belongs to, + /// Return the category number that a specified \p DiagID belongs to, /// or 0 if no category. static unsigned getCategoryNumberForDiag(unsigned DiagID); - /// \brief Return the number of diagnostic categories. + /// Return the number of diagnostic categories. static unsigned getNumberOfCategories(); - /// \brief Given a category ID, return the name of the category. + /// Given a category ID, return the name of the category. static StringRef getCategoryNameFromID(unsigned CategoryID); - /// \brief Return true if a given diagnostic falls into an ARC diagnostic + /// Return true if a given diagnostic falls into an ARC diagnostic /// category. static bool isARCDiagnostic(unsigned DiagID); - /// \brief Enumeration describing how the emission of a diagnostic should + /// Enumeration describing how the emission of a diagnostic should /// be treated when it occurs during C++ template argument deduction. enum SFINAEResponse { - /// \brief The diagnostic should not be reported, but it should cause + /// The diagnostic should not be reported, but it should cause /// template argument deduction to fail. /// /// The vast majority of errors that occur during template argument /// deduction fall into this category. SFINAE_SubstitutionFailure, - /// \brief The diagnostic should be suppressed entirely. + /// The diagnostic should be suppressed entirely. /// /// Warnings generally fall into this category. SFINAE_Suppress, - /// \brief The diagnostic should be reported. + /// The diagnostic should be reported. /// /// The diagnostic should be reported. Various fatal errors (e.g., /// template instantiation depth exceeded) fall into this category. SFINAE_Report, - /// \brief The diagnostic is an access-control diagnostic, which will be + /// The diagnostic is an access-control diagnostic, which will be /// substitution failures in some contexts and reported in others. SFINAE_AccessControl }; - /// \brief Determines whether the given built-in diagnostic ID is + /// Determines whether the given built-in diagnostic ID is /// for an error that is suppressed if it occurs during C++ template /// argument deduction. /// @@ -281,30 +281,30 @@ public: /// are not SFINAE errors. static SFINAEResponse getDiagnosticSFINAEResponse(unsigned DiagID); - /// \brief Get the string of all diagnostic flags. + /// Get the string of all diagnostic flags. /// /// \returns A list of all diagnostics flags as they would be written in a /// command line invocation including their `no-` variants. For example: /// `{"-Wempty-body", "-Wno-empty-body", ...}` static std::vector<std::string> getDiagnosticFlags(); - /// \brief Get the set of all diagnostic IDs in the group with the given name. + /// Get the set of all diagnostic IDs in the group with the given name. /// /// \param[out] Diags - On return, the diagnostics in the group. /// \returns \c true if the given group is unknown, \c false otherwise. bool getDiagnosticsInGroup(diag::Flavor Flavor, StringRef Group, SmallVectorImpl<diag::kind> &Diags) const; - /// \brief Get the set of all diagnostic IDs. + /// Get the set of all diagnostic IDs. static void getAllDiagnostics(diag::Flavor Flavor, std::vector<diag::kind> &Diags); - /// \brief Get the diagnostic option with the closest edit distance to the + /// Get the diagnostic option with the closest edit distance to the /// given group name. static StringRef getNearestOption(diag::Flavor Flavor, StringRef Group); private: - /// \brief Classify the specified diagnostic ID into a Level, consumable by + /// Classify the specified diagnostic ID into a Level, consumable by /// the DiagnosticClient. /// /// The classification is based on the way the client configured the @@ -320,17 +320,17 @@ private: getDiagnosticSeverity(unsigned DiagID, SourceLocation Loc, const DiagnosticsEngine &Diag) const LLVM_READONLY; - /// \brief Used to report a diagnostic that is finally fully formed. + /// Used to report a diagnostic that is finally fully formed. /// /// \returns \c true if the diagnostic was emitted, \c false if it was /// suppressed. bool ProcessDiag(DiagnosticsEngine &Diag) const; - /// \brief Used to emit a diagnostic that is finally fully formed, + /// Used to emit a diagnostic that is finally fully formed, /// ignoring suppression. void EmitDiag(DiagnosticsEngine &Diag, Level DiagLevel) const; - /// \brief Whether the diagnostic may leave the AST in a state where some + /// Whether the diagnostic may leave the AST in a state where some /// invariants can break. bool isUnrecoverable(unsigned DiagID) const; diff --git a/include/clang/Basic/DiagnosticLexKinds.td b/include/clang/Basic/DiagnosticLexKinds.td index c391470cb1c89..b5b5e8f654bca 100644 --- a/include/clang/Basic/DiagnosticLexKinds.td +++ b/include/clang/Basic/DiagnosticLexKinds.td @@ -404,6 +404,14 @@ def err_pp_invalid_directive : Error<"invalid preprocessing directive">; def err_pp_directive_required : Error< "%0 must be used within a preprocessing directive">; def err_pp_file_not_found : Error<"'%0' file not found">, DefaultFatal; +def err_pp_through_header_not_found : Error< + "'%0' required for precompiled header not found">, DefaultFatal; +def err_pp_through_header_not_seen : Error< + "#include of '%0' not seen while attempting to " + "%select{create|use}1 precompiled header">, DefaultFatal; +def warn_pp_macro_def_mismatch_with_pch : Warning< + "definition of macro %0 does not match definition in precompiled header">, + InGroup<ClangClPch>; def err_pp_file_not_found_not_fatal : Error< "'%0' file not found with <angled> include; use \"quotes\" instead">; def err_pp_error_opening_file : Error< @@ -505,17 +513,12 @@ def warn_pragma_message : Warning<"%0">, def err_pragma_message : Error<"%0">; def warn_pragma_ignored : Warning<"unknown pragma ignored">, InGroup<UnknownPragmas>, DefaultIgnore; -def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, - InGroup<UnknownPragmas>; def ext_on_off_switch_syntax : ExtWarn<"expected 'ON' or 'OFF' or 'DEFAULT' in pragma">, InGroup<UnknownPragmas>; def ext_pragma_syntax_eod : ExtWarn<"expected end of directive in pragma">, InGroup<UnknownPragmas>; -def warn_stdc_fenv_access_not_supported : - Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, - InGroup<UnknownPragmas>; def warn_pragma_diagnostic_invalid : ExtWarn<"pragma diagnostic expected 'error', 'warning', 'ignored', 'fatal'," " 'push', or 'pop'">, @@ -699,6 +702,11 @@ def warn_mmap_mismatched_private_module_name : Warning< InGroup<PrivateModule>; def note_mmap_rename_top_level_private_module : Note< "rename '%0' to ensure it can be found by name">; +def warn_mmap_incomplete_framework_module_declaration : Warning< + "skipping '%0' because module declaration of '%1' lacks the 'framework' qualifier">, + InGroup<IncompleteFrameworkModuleDeclaration>; +def note_mmap_add_framework_keyword : Note< + "use 'framework module' to declare module '%0'">; def err_mmap_duplicate_header_attribute : Error< "header attribute '%0' specified multiple times">; @@ -714,6 +722,14 @@ def warn_mmap_redundant_export_as : Warning< def err_mmap_submodule_export_as : Error< "only top-level modules can be re-exported as public">; +def warn_quoted_include_in_framework_header : Warning< + "double-quoted include \"%0\" in framework header, " + "expected angle-bracketed instead" + >, InGroup<FrameworkHdrQuotedInclude>, DefaultIgnore; +def warn_framework_include_private_from_public : Warning< + "public framework header includes private framework header '%0'" + >, InGroup<FrameworkIncludePrivateFromPublic>; + def warn_auto_module_import : Warning< "treating #%select{include|import|include_next|__include_macros}0 as an " "import of module '%1'">, InGroup<AutoImport>, DefaultIgnore; diff --git a/include/clang/Basic/DiagnosticOptions.h b/include/clang/Basic/DiagnosticOptions.h index 3844eb63f0eaf..391e252eaddda 100644 --- a/include/clang/Basic/DiagnosticOptions.h +++ b/include/clang/Basic/DiagnosticOptions.h @@ -1,4 +1,4 @@ -//===--- DiagnosticOptions.h ------------------------------------*- C++ -*-===// +//===- DiagnosticOptions.h --------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,14 +18,17 @@ namespace clang { -/// \brief Specifies which overload candidates to display when overload +/// Specifies which overload candidates to display when overload /// resolution fails. enum OverloadsShown : unsigned { - Ovl_All, ///< Show all overloads. - Ovl_Best ///< Show just the "best" overload candidates. + /// Show all overloads. + Ovl_All, + + /// Show just the "best" overload candidates. + Ovl_Best }; -/// \brief A bitmask representing the diagnostic levels used by +/// A bitmask representing the diagnostic levels used by /// VerifyDiagnosticConsumer. enum class DiagnosticLevelMask : unsigned { None = 0, @@ -57,7 +60,7 @@ inline DiagnosticLevelMask operator&(DiagnosticLevelMask LHS, raw_ostream& operator<<(raw_ostream& Out, DiagnosticLevelMask M); -/// \brief Options for controlling the compiler diagnostics engine. +/// Options for controlling the compiler diagnostics engine. class DiagnosticOptions : public RefCountedBase<DiagnosticOptions>{ public: enum TextDiagnosticFormat { Clang, MSVC, Vi }; @@ -86,10 +89,10 @@ protected: #include "clang/Basic/DiagnosticOptions.def" public: - /// \brief The file to log diagnostic output to. + /// The file to log diagnostic output to. std::string DiagnosticLogFile; - /// \brief The file to serialize diagnostics to (non-appending). + /// The file to serialize diagnostics to (non-appending). std::string DiagnosticSerializationFile; /// The list of -W... options used to alter the diagnostic mappings, with the @@ -119,8 +122,8 @@ public: } }; -typedef DiagnosticOptions::TextDiagnosticFormat TextDiagnosticFormat; +using TextDiagnosticFormat = DiagnosticOptions::TextDiagnosticFormat; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_DIAGNOSTICOPTIONS_H diff --git a/include/clang/Basic/DiagnosticParseKinds.td b/include/clang/Basic/DiagnosticParseKinds.td index 7936cdd96f80b..dd4c81922592f 100644 --- a/include/clang/Basic/DiagnosticParseKinds.td +++ b/include/clang/Basic/DiagnosticParseKinds.td @@ -39,7 +39,7 @@ def ext_empty_translation_unit : Extension< InGroup<DiagGroup<"empty-translation-unit">>; def warn_cxx98_compat_top_level_semi : Warning< "extra ';' outside of a function is incompatible with C++98">, - InGroup<CXX98CompatPedantic>, DefaultIgnore; + InGroup<CXX98CompatExtraSemi>, DefaultIgnore; def ext_extra_semi : Extension< "extra ';' %select{" "outside of a function|" @@ -173,6 +173,9 @@ def warn_attribute_on_function_definition : Warning< def warn_gcc_attribute_location : Warning< "GCC does not allow an attribute in this position on a function declaration">, InGroup<GccCompat>; +def warn_gcc_variable_decl_in_for_loop : Warning< + "GCC does not allow variable declarations in for loop initializers before " + "C99">, InGroup<GccCompat>; def warn_attribute_no_decl : Warning< "attribute %0 ignored, because it is not attached to a declaration">, InGroup<IgnoredAttributes>; @@ -248,6 +251,11 @@ def err_unexpected_at : Error<"unexpected '@' in program">; def err_atimport : Error< "use of '@import' when modules are disabled">; +def warn_atimport_in_framework_header : Warning< + "use of '@import' in framework header is discouraged, " + "including this header requires -fmodules">, + InGroup<FrameworkHdrAtImport>; + def err_invalid_reference_qualifier_application : Error< "'%0' qualifier may not be applied to a reference">; def err_illegal_decl_reference_to_reference : Error< @@ -575,7 +583,7 @@ def err_cxx11_attribute_forbids_arguments : Error< def err_attribute_requires_arguments : Error< "parentheses must be omitted if %0 attribute's argument list is empty">; def err_cxx11_attribute_forbids_ellipsis : Error< - "attribute '%0' cannot be used as an attribute pack">; + "attribute %0 cannot be used as an attribute pack">; def err_cxx11_attribute_repeated : Error< "attribute %0 cannot appear multiple times in an attribute specifier">; def warn_cxx14_compat_using_attribute_ns : Warning< @@ -633,6 +641,8 @@ def err_template_spec_syntax_non_template : Error< "<unused>|refers to a variable template|<unused>}1">; def err_id_after_template_in_nested_name_spec : Error< "expected template name after 'template' keyword in nested name specifier">; +def err_unexpected_template_in_unqualified_id : Error< + "'template' keyword not permitted here">; def err_two_right_angle_brackets_need_space : Error< "a space is required between consecutive right angle brackets (use '> >')">; def err_right_angle_bracket_equal_needs_space : Error< @@ -895,6 +905,12 @@ def warn_pragma_expected_rparen : Warning< "missing ')' after '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>; def warn_pragma_expected_identifier : Warning< "expected identifier in '#pragma %0' - ignored">, InGroup<IgnoredPragmas>; +def warn_pragma_expected_string : Warning< + "expected string literal in '#pragma %0' - ignoring">, InGroup<IgnoredPragmas>; +def warn_pragma_missing_argument : Warning< + "missing argument to '#pragma %0'%select{|; expected %2}1">, InGroup<IgnoredPragmas>; +def warn_pragma_invalid_argument : Warning< + "unexpected argument '%0' to '#pragma %1'%select{|; expected %3}2">, InGroup<IgnoredPragmas>; // '#pragma clang section' related errors def err_pragma_expected_clang_section_name : Error< @@ -923,6 +939,8 @@ def warn_pragma_ms_struct : Warning< def warn_pragma_extra_tokens_at_eol : Warning< "extra tokens at end of '#pragma %0' - ignored">, InGroup<IgnoredPragmas>; +def warn_pragma_expected_comma : Warning< + "expected ',' in '#pragma %0'">, InGroup<IgnoredPragmas>; def warn_pragma_expected_punc : Warning< "expected ')' or ',' in '#pragma %0'">, InGroup<IgnoredPragmas>; def warn_pragma_expected_non_wide_string : Warning< @@ -960,6 +978,10 @@ def warn_pragma_pack_malformed : Warning< def warn_pragma_intrinsic_builtin : Warning< "%0 is not a recognized builtin%select{|; consider including <intrin.h> to access non-builtin intrinsics}1">, InGroup<IgnoredPragmaIntrinsic>; +// - #pragma optimize +def warn_pragma_optimize : Warning< + "'#pragma optimize' is not supported">, + InGroup<IgnoredPragmaOptimize>; // - #pragma unused def warn_pragma_unused_expected_var : Warning< "expected '#pragma unused' argument to be a variable name">, @@ -973,6 +995,12 @@ def warn_pragma_init_seg_unsupported_target : Warning< def err_pragma_fp_contract_scope : Error< "'#pragma fp_contract' can only appear at file scope or at the start of a " "compound statement">; +// - #pragma stdc unknown +def ext_stdc_pragma_ignored : ExtWarn<"unknown pragma in STDC namespace">, + InGroup<UnknownPragmas>; +def warn_stdc_fenv_access_not_supported : + Warning<"pragma STDC FENV_ACCESS ON is not supported, ignoring pragma">, + InGroup<UnknownPragmas>; // - #pragma comment def err_pragma_comment_malformed : Error< "pragma comment requires parenthesized identifier and optional string">; @@ -1055,6 +1083,12 @@ def err_opencl_taking_function_address_parser : Error< def err_opencl_logical_exclusive_or : Error< "^^ is a reserved operator in OpenCL">; +// OpenCL C++. +def err_openclcxx_virtual_function : Error< + "virtual functions are not supported in OpenCL C++">; +def err_openclcxx_reserved : Error< + "'%0' is a reserved keyword in OpenCL C++">; + // OpenMP support. def warn_pragma_omp_ignored : Warning< "unexpected '#pragma omp ...' in program">, InGroup<SourceUsesOpenMP>, DefaultIgnore; @@ -1066,7 +1100,7 @@ def warn_pragma_expected_colon_r_paren : Warning< def err_omp_unknown_directive : Error< "expected an OpenMP directive">; def err_omp_unexpected_directive : Error< - "unexpected OpenMP directive '#pragma omp %0'">; + "unexpected OpenMP directive %select{|'#pragma omp %1'}0">; def err_omp_expected_punc : Error< "expected ',' or ')' in '%0' %select{clause|directive}1">; def err_omp_unexpected_clause : Error< @@ -1156,6 +1190,9 @@ def err_objc_parameterized_implementation : Error< def err_objc_type_args_after_protocols : Error< "protocol qualifiers must precede type arguments">; + +def note_meant_to_use_typename : Note< + "did you mean to use 'typename'?">; } let CategoryName = "Coroutines Issue" in { diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 01e819942f686..d0a2bec780527 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -203,6 +203,8 @@ def ext_imaginary_constant : Extension< def ext_integer_complex : Extension< "complex integer types are a GNU extension">, InGroup<GNUComplexInteger>; +def err_invalid_saturation_spec : Error<"'_Sat' specifier is only valid on " + "'_Fract' or '_Accum', not '%0'">; def err_invalid_sign_spec : Error<"'%0' cannot be signed or unsigned">; def err_invalid_width_spec : Error< "'%select{|short|long|long long}0 %1' is invalid">; @@ -272,6 +274,14 @@ def warn_mips_interrupt_attribute : Warning< "MIPS 'interrupt' attribute only applies to functions that have " "%select{no parameters|a 'void' return type}0">, InGroup<IgnoredAttributes>; +def warn_riscv_repeated_interrupt_attribute : Warning< + "repeated RISC-V 'interrupt' attribute">, InGroup<IgnoredAttributes>; +def note_riscv_repeated_interrupt_attribute : Note< + "repeated RISC-V 'interrupt' attribute is here">; +def warn_riscv_interrupt_attribute : Warning< + "RISC-V 'interrupt' attribute only applies to functions that have " + "%select{no parameters|a 'void' return type}0">, + InGroup<IgnoredAttributes>; def warn_unused_parameter : Warning<"unused parameter %0">, InGroup<UnusedParameter>, DefaultIgnore; def warn_unused_variable : Warning<"unused variable %0">, @@ -279,7 +289,7 @@ def warn_unused_variable : Warning<"unused variable %0">, def warn_unused_local_typedef : Warning< "unused %select{typedef|type alias}0 %1">, InGroup<UnusedLocalTypedef>, DefaultIgnore; -def warn_unused_property_backing_ivar : +def warn_unused_property_backing_ivar : Warning<"ivar %0 which backs the property is not " "referenced in this property's accessor">, InGroup<UnusedPropertyIvar>, DefaultIgnore; @@ -602,9 +612,12 @@ def warn_redecl_library_builtin : Warning< "incompatible redeclaration of library function %0">, InGroup<DiagGroup<"incompatible-library-redeclaration">>; def err_builtin_definition : Error<"definition of builtin function %0">; +def err_builtin_redeclare : Error<"cannot redeclare builtin function %0">; def err_arm_invalid_specialreg : Error<"invalid special register for builtin">; def err_invalid_cpu_supports : Error<"invalid cpu feature string for builtin">; def err_invalid_cpu_is : Error<"invalid cpu name for builtin">; +def err_invalid_cpu_specific_dispatch_value : Error< +"invalid option '%0' for %select{cpu_specific|cpu_dispatch}1">; def err_builtin_needs_feature : Error<"%0 needs target feature %1">; def err_function_needs_feature : Error<"always_inline function %1 requires target feature '%2', but would " @@ -612,11 +625,18 @@ def err_function_needs_feature "'%2'">; def warn_builtin_unknown : Warning<"use of unknown builtin %0">, InGroup<ImplicitFunctionDeclare>, DefaultError; +def warn_cstruct_memaccess : Warning< + "%select{destination for|source of|first operand of|second operand of}0 this " + "%1 call is a pointer to record %2 that is not trivial to " + "%select{primitive-default-initialize|primitive-copy}3">, + InGroup<NonTrivialMemaccess>; +def note_nontrivial_field : Note< + "field is non-trivial to %select{copy|default-initialize}0">; def warn_dyn_class_memaccess : Warning< "%select{destination for|source of|first operand of|second operand of}0 this " "%1 call is a pointer to %select{|class containing a }2dynamic class %3; " "vtable pointer will be %select{overwritten|copied|moved|compared}4">, - InGroup<DiagGroup<"dynamic-class-memaccess">>; + InGroup<DynamicClassMemaccess>; def note_bad_memaccess_silence : Note< "explicitly cast the pointer to silence this warning">; def warn_sizeof_pointer_expr_memaccess : Warning< @@ -645,7 +665,19 @@ def note_memsize_comparison_paren : Note< "did you mean to compare the result of %0 instead?">; def note_memsize_comparison_cast_silence : Note< "explicitly cast the argument to size_t to silence this warning">; - +def warn_suspicious_sizeof_memset : Warning< + "%select{'size' argument to memset is '0'|" + "setting buffer to a 'sizeof' expression}0" + "; did you mean to transpose the last two arguments?">, + InGroup<MemsetTransposedArgs>; +def note_suspicious_sizeof_memset_silence : Note< + "%select{parenthesize the third argument|" + "cast the second argument to 'int'}0 to silence">; +def warn_suspicious_bzero_size : Warning<"'size' argument to bzero is '0'">, + InGroup<SuspiciousBzero>; +def note_suspicious_bzero_size_silence : Note< + "parenthesize the second argument to silence">; + def warn_strncat_large_size : Warning< "the value of the size argument in 'strncat' is too large, might lead to a " "buffer overflow">, InGroup<StrncatSize>; @@ -751,7 +783,7 @@ def note_pragma_pack_pop_instead_reset : Note< "did you intend to use '#pragma pack (pop)' instead of '#pragma pack()'?">; // Follow the Microsoft implementation. def warn_pragma_pack_show : Warning<"value of #pragma pack(show) == %0">; -def warn_pragma_pack_pop_identifer_and_alignment : Warning< +def warn_pragma_pack_pop_identifier_and_alignment : Warning< "specifying both a name and alignment to 'pop' is undefined">; def warn_pragma_pop_failed : Warning<"#pragma %0(pop, ...) failed: %1">, InGroup<IgnoredPragmas>; @@ -759,6 +791,10 @@ def warn_cxx_ms_struct : Warning<"ms_struct may not produce Microsoft-compatible layouts for classes " "with base classes or virtual functions">, DefaultError, InGroup<IncompatibleMSStruct>; +def warn_npot_ms_struct : + Warning<"ms_struct may not produce Microsoft-compatible layouts with fundamental " + "data types with sizes that aren't a power of two">, + 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', " @@ -1027,7 +1063,7 @@ def warn_objc_pointer_masking : Warning< def warn_objc_pointer_masking_performSelector : Warning<warn_objc_pointer_masking.Text>, InGroup<ObjCPointerIntrospectPerformSelector>; def warn_objc_property_default_assign_on_object : Warning< - "default property attribute 'assign' not appropriate for non-GC object">, + "default property attribute 'assign' not appropriate for object">, InGroup<ObjCPropertyNoAttribute>; def warn_property_attr_mismatch : Warning< "property attribute in class extension does not match the primary class">, @@ -1325,7 +1361,7 @@ def err_invalid_member_in_interface : Error< "nested class }0%1 is not permitted within an interface type">; def err_invalid_base_in_interface : Error< "interface type cannot inherit from " - "%select{'struct|non-public 'interface|'class}0 %1'">; + "%select{struct|non-public interface|class}0 %1">; def err_abstract_type_in_decl : Error< "%select{return|parameter|variable|field|instance variable|" @@ -1582,6 +1618,8 @@ def err_not_integral_type_bitfield : Error< "bit-field %0 has non-integral type %1">; def err_not_integral_type_anon_bitfield : Error< "anonymous bit-field has non-integral type %0">; +def err_anon_bitfield_qualifiers : Error< + "anonymous bit-field cannot have qualifiers">; def err_member_function_initialization : Error< "initializer on function does not look like a pure-specifier">; def err_non_virtual_pure : Error< @@ -1589,24 +1627,35 @@ def err_non_virtual_pure : Error< def ext_pure_function_definition : ExtWarn< "function definition with pure-specifier is a Microsoft extension">, InGroup<MicrosoftPureDefinition>; -def err_implicit_object_parameter_init : Error< - "cannot initialize object parameter of type %0 with an expression " - "of type %1">; def err_qualified_member_of_unrelated : Error< "%q0 is not a member of class %1">; +def err_member_function_call_bad_cvr : Error< + "'this' argument to member function %0 has type %1, but function is not marked " + "%select{const|restrict|const or restrict|volatile|const or volatile|" + "volatile or restrict|const, volatile, or restrict}2">; +def err_member_function_call_bad_ref : Error< + "'this' argument to member function %0 is an %select{lvalue|rvalue}1, " + "but function has %select{non-const lvalue|rvalue}2 ref-qualifier">; +def err_member_function_call_bad_type : Error< + "cannot initialize object parameter of type %0 with an expression " + "of type %1">; + def warn_call_to_pure_virtual_member_function_from_ctor_dtor : Warning< "call to pure virtual member function %0 has undefined behavior; " "overrides of %0 in subclasses are not available in the " "%select{constructor|destructor}1 of %2">; +def select_special_member_kind : TextSubstitution< + "%select{default constructor|copy constructor|move constructor|" + "copy assignment operator|move assignment operator|destructor}0">; + def note_member_declared_at : Note<"member is declared here">; def note_ivar_decl : Note<"instance variable is declared here">; def note_bitfield_decl : Note<"bit-field is declared here">; def note_implicit_param_decl : Note<"%0 is an implicit parameter">; def note_member_synthesized_at : Note< - "in implicit %select{default constructor|copy constructor|move constructor|" - "copy assignment operator|move assignment operator|destructor}0 for %1 " + "in implicit %sub{select_special_member_kind}0 for %1 " "first required here">; def err_missing_default_ctor : Error< "%select{constructor for %1 must explicitly initialize the|" @@ -1615,16 +1664,14 @@ def err_missing_default_ctor : Error< "%select{base class|member}2 %3 %select{which|which|of %1}0 " "does not have a default constructor">; def note_due_to_dllexported_class : Note< - "due to '%0' being dllexported%select{|; try compiling in C++11 mode}1">; + "due to %0 being dllexported%select{|; try compiling in C++11 mode}1">; def err_illegal_union_or_anon_struct_member : Error< "%select{anonymous struct|union}0 member %1 has a non-trivial " - "%select{constructor|copy constructor|move constructor|copy assignment " - "operator|move assignment operator|destructor}2">; + "%sub{select_special_member_kind}2">; def warn_cxx98_compat_nontrivial_union_or_anon_struct_member : Warning< "%select{anonymous struct|union}0 member %1 with a non-trivial " - "%select{constructor|copy constructor|move constructor|copy assignment " - "operator|move assignment operator|destructor}2 is incompatible with C++98">, + "%sub{select_special_member_kind}2 is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; def note_nontrivial_virtual_dtor : Note< @@ -1643,8 +1690,7 @@ def note_nontrivial_no_copy : Note< "%select{base class|field|an object}0 of type %3">; def note_nontrivial_user_provided : Note< "because %select{base class of |field of |}0type %1 has a user-provided " - "%select{default constructor|copy constructor|move constructor|" - "copy assignment operator|move assignment operator|destructor}2">; + "%sub{select_special_member_kind}2">; def note_nontrivial_in_class_init : Note< "because field %0 has an initializer">; def note_nontrivial_param_type : Note< @@ -1711,9 +1757,7 @@ def err_covariant_return_type_class_type_more_qualified : Error< // C++ implicit special member functions def note_in_declaration_of_implicit_special_member : Note< - "while declaring the implicit " - "%select{default constructor|copy constructor|move constructor|" - "copy assignment operator|move assignment operator|destructor}1" + "while declaring the implicit %sub{select_special_member_kind}1" " for %0">; // C++ constructors @@ -1768,7 +1812,8 @@ def err_destructor_template : Error< // C++ initialization def err_init_conversion_failed : Error< - "cannot initialize %select{a variable|a parameter|return object|an " + "cannot initialize %select{a variable|a parameter|return object|" + "statement expression result|an " "exception object|a member subobject|an array element|a new value|a value|a " "base class|a constructor delegation|a vector element|a block element|a " "block element|a complex element|a lambda capture|a compound literal " @@ -1808,17 +1853,9 @@ def err_reference_bind_failed : Error< "type $|could not bind to %select{rvalue|lvalue}1 of incompatible type}0,2">; def err_reference_bind_init_list : Error< "reference to type %0 cannot bind to an initializer list">; -def warn_temporary_array_to_pointer_decay : Warning< - "pointer is initialized by a temporary array, which will be destroyed at the " - "end of the full-expression">, - InGroup<DiagGroup<"address-of-array-temporary">>; def err_init_list_bad_dest_type : Error< "%select{|non-aggregate }0type %1 cannot be initialized with an initializer " "list">; -def err_member_function_call_bad_cvr : Error<"member function %0 not viable: " - "'this' argument has type %1, but function is not marked " - "%select{const|restrict|const or restrict|volatile|const or volatile|" - "volatile or restrict|const, volatile, or restrict}2">; def err_reference_bind_to_bitfield : Error< "%select{non-const|volatile}0 reference cannot bind to " @@ -1907,34 +1944,29 @@ def warn_unsequenced_mod_mod : Warning< def warn_unsequenced_mod_use : Warning< "unsequenced modification and access to %0">, InGroup<Unsequenced>; +def select_initialized_entity_kind : TextSubstitution< + "%select{copying variable|copying parameter|" + "returning object|initializing statement expression result|" + "throwing object|copying member subobject|copying array element|" + "allocating object|copying temporary|initializing base subobject|" + "initializing vector element|capturing value}0">; + def err_temp_copy_no_viable : Error< - "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|" - "initializing vector element|capturing value}0 of type %1">; + "no viable constructor %sub{select_initialized_entity_kind}0 of type %1">; 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|" - "initializing vector element|capturing value}0 of type %1; C++98 requires a copy " - "constructor when binding a reference to a temporary">, + "no viable constructor %sub{select_initialized_entity_kind}0 of type %1; " + "C++98 requires a copy constructor when binding a reference to a temporary">, InGroup<BindToTemporaryCopy>; def err_temp_copy_ambiguous : Error< - "ambiguous constructor call when %select{copying variable|copying " - "parameter|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">; + "ambiguous constructor call when %sub{select_initialized_entity_kind}0 " + "of type %1">; def err_temp_copy_deleted : Error< - "%select{copying variable|copying parameter|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 invokes deleted constructor">; + "%sub{select_initialized_entity_kind}0 of type %1 " + "invokes deleted constructor">; def err_temp_copy_incomplete : Error< "copying a temporary object of incomplete type %0">; def warn_cxx98_compat_temp_copy : Warning< - "%select{copying variable|copying parameter|returning object|throwing " - "object|copying member subobject|copying array element|allocating object|" - "copying temporary|initializing base subobject|initializing vector element}1 " + "%sub{select_initialized_entity_kind}1 " "of type %2 when binding a reference to a temporary would %select{invoke " "an inaccessible constructor|find no viable constructor|find ambiguous " "constructors|invoke a deleted constructor}0 in C++98">, @@ -2031,10 +2063,6 @@ def err_implied_std_initializer_list_not_found : Error< "not found; include <initializer_list>">; def err_malformed_std_initializer_list : Error< "std::initializer_list must be a class template with a single type parameter">; -def warn_dangling_std_initializer_list : Warning< - "array backing the initializer list will be destroyed at the end of " - "%select{the full-expression|the constructor}0">, - InGroup<DiagGroup<"dangling-initializer-list">>; def err_auto_init_list_from_c : Error< "cannot use __auto_type with initializer list in C">; def err_auto_bitfield : Error< @@ -2099,9 +2127,16 @@ def err_deduction_guide_explicit_mismatch : Error< def err_deduction_guide_specialized : Error<"deduction guide cannot be " "%select{explicitly instantiated|explicitly specialized}0">; def err_deduction_guide_template_not_deducible : Error< - "deduction guide template contains " - "%select{a template parameter|template parameters}0 that cannot be " - "deduced">; + "deduction guide template contains " + "%select{a template parameter|template parameters}0 that cannot be " + "deduced">; +def err_deduction_guide_wrong_access : Error< + "deduction guide has different access from the corresponding " + "member template">; +def note_deduction_guide_template_access : Note< + "member template declared %0 here">; +def note_deduction_guide_access : Note< + "deduction guide declared %0 by intervening access specifier">; // C++1y deduced return types def err_auto_fn_deduction_failure : Error< @@ -2363,6 +2398,8 @@ def note_non_literal_user_provided_dtor : Note< "%0 is not literal because it has a user-provided destructor">; def note_non_literal_nontrivial_dtor : Note< "%0 is not literal because it has a non-trivial destructor">; +def note_non_literal_lambda : Note< + "lambda closure types are non-literal types before C++17">; def warn_private_extern : Warning< "use of __private_extern__ on a declaration may not produce external symbol " "private to the linkage unit and is deprecated">, InGroup<PrivateExtern>; @@ -2403,6 +2440,9 @@ def err_template_different_associated_constraints : Error< def warn_cxx98_compat_unicode_type : Warning< "'%0' type specifier is incompatible with C++98">, InGroup<CXX98Compat>, DefaultIgnore; +def warn_cxx17_compat_unicode_type : Warning< + "'char8_t' type specifier is incompatible with C++ standards before C++20">, + InGroup<CXXPre2aCompat>, DefaultIgnore; // __make_integer_seq def err_integer_sequence_negative_length : Error< @@ -2441,8 +2481,8 @@ def err_attribute_requires_positive_integer : Error< def err_attribute_requires_opencl_version : Error< "%0 attribute requires OpenCL version %1%select{| or above}2">; def warn_unsupported_target_attribute - : Warning<"ignoring %select{unsupported|duplicate}0" - "%select{| architecture}1 '%2' in the target attribute string">, + : Warning<"%select{unsupported|duplicate}0%select{| architecture}1 '%2' in" + " the 'target' attribute string; 'target' attribute ignored">, InGroup<IgnoredAttributes>; def err_attribute_unsupported : Error<"%0 attribute is not supported for this target">; @@ -2546,6 +2586,9 @@ def err_attribute_address_space_too_high : Error< "address space is larger than the maximum supported (%0)">; def err_attribute_address_multiple_qualifiers : Error< "multiple address spaces specified for type">; +def warn_attribute_address_multiple_identical_qualifiers : Warning< + "multiple identical address spaces specified for type">, + InGroup<DuplicateDeclSpecifier>; def err_attribute_address_function_type : Error< "function type may not be qualified with an address space">; def err_as_qualified_auto_decl : Error< @@ -2639,11 +2682,19 @@ def err_only_annotate_after_access_spec : Error< "access specifier can only have annotation attributes">; def err_attribute_section_invalid_for_target : Error< - "argument to 'section' attribute is not valid for this target: %0">; + "argument to %select{'code_seg'|'section'}1 attribute is not valid for this target: %0">; def warn_mismatched_section : Warning< - "section does not match previous declaration">, InGroup<Section>; + "%select{codeseg|section}0 does not match previous declaration">, InGroup<Section>; def warn_attribute_section_on_redeclaration : Warning< "section attribute is specified on redeclared variable">, InGroup<Section>; +def err_mismatched_code_seg_base : Error< + "derived class must specify the same code segment as its base classes">; +def err_mismatched_code_seg_override : Error< + "overriding virtual function must specify the same code segment as its overridden function">; +def err_conflicting_codeseg_attribute : Error< + "conflicting code segment specifiers">; +def warn_duplicate_codeseg_attribute : Warning< + "duplicate code segment specifiers">, InGroup<Section>; def err_anonymous_property: Error< "anonymous property is not supported">; @@ -2683,6 +2734,9 @@ def warn_attribute_ignored : Warning<"%0 attribute ignored">, def warn_attribute_ignored_on_inline : Warning<"%0 attribute ignored on inline function">, InGroup<IgnoredAttributes>; +def warn_nocf_check_attribute_ignored : + Warning<"'nocf_check' attribute ignored; use -fcf-protection to enable the attribute">, + InGroup<IgnoredAttributes>; def warn_attribute_after_definition_ignored : Warning< "attribute %0 after definition is ignored">, InGroup<IgnoredAttributes>; @@ -2796,7 +2850,7 @@ def warn_alias_with_section : Warning< "%select{alias|ifunc}1 will not be in section '%0' but in the same section as the %select{aliasee|resolver}2">, InGroup<IgnoredAttributes>; def err_duplicate_mangled_name : Error< - "definition with same mangled name as another definition">; + "definition with same mangled name '%0' as another definition">; def err_cyclic_alias : Error< "%select{alias|ifunc}0 definition is part of a cycle">; def err_ifunc_resolver_return : Error< @@ -2821,8 +2875,7 @@ def warn_attribute_wrong_decl_type : Warning< "|types and namespaces" "|variables, functions and classes" "|kernel functions" - "|non-K&R-style functions" - "|variables, functions, methods, types, enumerations, enumerators, labels, and non-static data members}1">, + "|non-K&R-style functions}1">, InGroup<IgnoredAttributes>; def err_attribute_wrong_decl_type : Error<warn_attribute_wrong_decl_type.Text>; def warn_type_attribute_wrong_type : Warning< @@ -2877,6 +2930,9 @@ def err_base_specifier_attribute : Error< def err_invalid_attribute_on_virtual_function : Error< "%0 attribute cannot be applied to virtual functions">; +def ext_cannot_use_trivial_abi : ExtWarn< + "'trivial_abi' cannot be applied to %0">, InGroup<IgnoredAttributes>; + // Availability attribute def warn_availability_unknown_platform : Warning< "unknown platform %0 in availability macro">, InGroup<Availability>; @@ -2896,6 +2952,10 @@ def warn_mismatched_availability_override_unavail : Warning< "%select{the protocol method it implements|its overridden method}1 is " "available">, InGroup<Availability>; +def warn_availability_on_static_initializer : Warning< + "ignoring availability attribute %select{on '+load' method|" + "with constructor attribute|with destructor attribute}0">, + InGroup<Availability>; def note_overridden_method : Note< "overridden method is here">; def note_protocol_method : Note< @@ -2970,11 +3030,11 @@ def warn_lock_exclusive_and_shared : Warning< def note_lock_exclusive_and_shared : Note< "the other acquisition of %0 '%1' is here">; def warn_variable_requires_any_lock : Warning< - "%select{reading|writing}1 variable '%0' requires holding " + "%select{reading|writing}1 variable %0 requires holding " "%select{any mutex|any mutex exclusively}1">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_var_deref_requires_any_lock : Warning< - "%select{reading|writing}1 the value pointed to by '%0' requires holding " + "%select{reading|writing}1 the value pointed to by %0 requires holding " "%select{any mutex|any mutex exclusively}1">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_fun_excludes_mutex : Warning< @@ -2998,25 +3058,25 @@ def warn_acquire_requires_negative_cap : Warning< // Thread safety warnings on pass by reference def warn_guarded_pass_by_reference : Warning< - "passing variable '%1' by reference requires holding %0 " + "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 " + "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 " + "%select{reading|writing}3 variable %1 requires holding %0 " "%select{'%2'|'%2' exclusively}3">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_var_deref_requires_lock : Warning< - "%select{reading|writing}3 the value pointed to by '%1' requires " + "%select{reading|writing}3 the value pointed to by %1 requires " "holding %0 %select{'%2'|'%2' exclusively}3">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; def warn_fun_requires_lock : Warning< - "calling function '%1' requires holding %0 %select{'%2'|'%2' exclusively}3">, + "calling function %1 requires holding %0 %select{'%2'|'%2' exclusively}3">, InGroup<ThreadSafetyAnalysis>, DefaultIgnore; // Precise thread safety warnings @@ -3034,7 +3094,7 @@ 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_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. @@ -3082,6 +3142,9 @@ def err_impcast_complex_scalar : Error< def warn_impcast_float_precision : Warning< "implicit conversion loses floating-point precision: %0 to %1">, InGroup<Conversion>, DefaultIgnore; +def warn_impcast_float_result_precision : Warning< + "implicit conversion when assigning computation result loses floating-point precision: %0 to %1">, + InGroup<Conversion>, DefaultIgnore; def warn_impcast_double_promotion : Warning< "implicit conversion increases floating-point precision: %0 to %1">, InGroup<DoublePromotion>, DefaultIgnore; @@ -3107,13 +3170,18 @@ def warn_impcast_bitfield_precision_constant : Warning< def warn_impcast_literal_float_to_integer : Warning< "implicit conversion from %0 to %1 changes value from %2 to %3">, InGroup<LiteralConversion>; +def warn_impcast_literal_float_to_integer_out_of_range : Warning< + "implicit conversion of out of range value from %0 to %1 is undefined">, + InGroup<LiteralConversion>; def warn_impcast_float_integer : Warning< "implicit conversion turns floating-point number into integer: %0 to %1">, InGroup<FloatConversion>, DefaultIgnore; def warn_impcast_float_to_integer : Warning< - "implicit conversion of out of range value from %0 to %1 changes value " - "from %2 to %3">, + "implicit conversion from %0 to %1 changes value from %2 to %3">, + InGroup<FloatOverflowConversion>, DefaultIgnore; +def warn_impcast_float_to_integer_out_of_range : Warning< + "implicit conversion of out of range value from %0 to %1 is undefined">, InGroup<FloatOverflowConversion>, DefaultIgnore; def warn_impcast_float_to_integer_zero : Warning< "implicit conversion from %0 to %1 changes non-zero value from %2 to %3">, @@ -3303,6 +3371,9 @@ def err_attribute_not_supported_in_lang : Error< "%0 attribute is not supported in %select{C|C++|Objective-C}1">; def err_attribute_not_supported_on_arch : Error<"%0 attribute is not supported on '%1'">; +def warn_gcc_ignores_type_attr : Warning< + "GCC does not allow the %0 attribute to be written on a type">, + InGroup<GccCompat>; // Clang-Specific Attributes def warn_attribute_iboutlet : Warning< @@ -3484,27 +3555,29 @@ def err_ovl_deleted_member_call : Error< def note_ovl_too_many_candidates : Note< "remaining %0 candidate%s0 omitted; " "pass -fshow-overloads=all to show them">; -def note_ovl_candidate : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "is the implicit default constructor|" - "is the implicit copy constructor|" - "is the implicit move constructor|" - "is the implicit copy assignment operator|" - "is the implicit move assignment operator|" - "inherited constructor|" - "inherited constructor }0%2" - "%select{| has different class%diff{ (expected $ but has $)|}4,5" - "| has different number of parameters (expected %4 but has %5)" - "| has type mismatch at %ordinal4 parameter" - "%diff{ (expected $ but has $)|}5,6" - "| has different return type%diff{ ($ expected but has $)|}4,5" + +def select_ovl_candidate_kind : TextSubstitution< + "%select{function|function|constructor|" + "constructor (the implicit default constructor)|" + "constructor (the implicit copy constructor)|" + "constructor (the implicit move constructor)|" + "function (the implicit copy assignment operator)|" + "function (the implicit move assignment operator)|" + "inherited constructor}0%select{| template| %2}1">; + +def note_ovl_candidate : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,3" + "%select{| has different class%diff{ (expected $ but has $)|}5,6" + "| has different number of parameters (expected %5 but has %6)" + "| has type mismatch at %ordinal5 parameter" + "%diff{ (expected $ but has $)|}6,7" + "| has different return type%diff{ ($ expected but has $)|}5,6" "| has different qualifiers (expected " "%select{none|const|restrict|const and restrict|volatile|const and volatile" - "|volatile and restrict|const, volatile, and restrict}4 but found " + "|volatile and restrict|const, volatile, and restrict}5 but found " "%select{none|const|restrict|const and restrict|volatile|const and volatile" - "|volatile and restrict|const, volatile, and restrict}5)" - "| has different exception specification}3">; + "|volatile and restrict|const, volatile, and restrict}6)" + "| has different exception specification}4">; def note_ovl_candidate_inherited_constructor : Note< "constructor from base class %0 inherited here">; @@ -3518,6 +3591,9 @@ def note_ovl_candidate_bad_deduction : Note< "candidate template ignored: failed template argument deduction">; def note_ovl_candidate_incomplete_deduction : Note<"candidate template ignored: " "couldn't infer template argument %0">; +def note_ovl_candidate_incomplete_deduction_pack : Note<"candidate template ignored: " + "deduced too few arguments for expanded pack %0; no argument for %ordinal1 " + "expanded parameter in deduced argument pack %2">; def note_ovl_candidate_inconsistent_deduction : Note< "candidate template ignored: deduced conflicting %select{types|values|" "templates}0 for parameter %1%diff{ ($ vs. $)|}2,3">; @@ -3574,233 +3650,99 @@ def note_ovl_candidate_non_deduced_mismatch_qualified : Note< // Note that we don't treat templates differently for this diagnostic. def note_ovl_candidate_arity : Note<"candidate " - "%select{function|function|constructor|function|function|constructor|" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor}0 %select{|template }1" - "not viable: requires%select{ at least| at most|}2 %3 argument%s3, but %4 " - "%plural{1:was|:were}4 provided">; + "%sub{select_ovl_candidate_kind}0,1,2 not viable: " + "requires%select{ at least| at most|}3 %4 argument%s4, but %5 " + "%plural{1:was|:were}5 provided">; def note_ovl_candidate_arity_one : Note<"candidate " - "%select{function|function|constructor|function|function|constructor|" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor}0 %select{|template }1not viable: " - "%select{requires at least|allows at most single|requires single}2 " - "argument %3, but %plural{0:no|:%4}4 arguments were provided">; + "%sub{select_ovl_candidate_kind}0,1,2 not viable: " + "%select{requires at least|allows at most single|requires single}3 " + "argument %4, but %plural{0:no|:%5}5 arguments were provided">; def note_ovl_candidate_deleted : Note< - "candidate %select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 has been " + "candidate %sub{select_ovl_candidate_kind}0,1,2 has been " "%select{explicitly made unavailable|explicitly deleted|" - "implicitly deleted}2">; + "implicitly deleted}3">; // Giving the index of the bad argument really clutters this message, and // it's relatively unimportant because 1) it's generally obvious which // argument(s) are of the given object type and 2) the fix is usually // to complete the type, which doesn't involve changes to the call line // anyway. If people complain, we can change it. -def note_ovl_candidate_bad_conv_incomplete : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 " - "not viable: cannot convert argument of incomplete type " - "%diff{$ to $|to parameter type}2,3 for " - "%select{%ordinal5 argument|object argument}4" +def note_ovl_candidate_bad_conv_incomplete : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "cannot convert argument of incomplete type " + "%diff{$ to $|to parameter type}3,4 for " + "%select{%ordinal6 argument|object argument}5" "%select{|; dereference the argument with *|" "; take the address of the argument with &|" "; remove *|" - "; remove &}6">; -def note_ovl_candidate_bad_list_argument : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 " - "not viable: cannot convert initializer list argument to %3">; -def note_ovl_candidate_bad_overload : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1" - " not viable: no overload of %3 matching %2 for %ordinal4 argument">; -def note_ovl_candidate_bad_conv : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1" - " not viable: no known conversion " - "%diff{from $ to $|from argument type to parameter type}2,3 for " - "%select{%ordinal5 argument|object argument}4" + "; remove &}7">; +def note_ovl_candidate_bad_list_argument : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "cannot convert initializer list argument to %4">; +def note_ovl_candidate_bad_overload : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "no overload of %4 matching %3 for %ordinal5 argument">; +def note_ovl_candidate_bad_conv : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "no known conversion " + "%diff{from $ to $|from argument type to parameter type}3,4 for " + "%select{%ordinal6 argument|object argument}5" "%select{|; dereference the argument with *|" "; take the address of the argument with &|" "; remove *|" - "; remove &}6">; -def note_ovl_candidate_bad_arc_conv : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1" - " not viable: cannot implicitly convert argument " - "%diff{of type $ to $|type to parameter type}2,3 for " - "%select{%ordinal5 argument|object argument}4 under ARC">; -def note_ovl_candidate_bad_lvalue : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1" - " not viable: expects an l-value for " - "%select{%ordinal3 argument|object argument}2">; -def note_ovl_candidate_bad_addrspace : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 not viable: " - "%select{%ordinal6|'this'}5 argument (%2) is in " - "address space %3, but parameter must be in address space %4">; -def note_ovl_candidate_bad_gc : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 not viable: " - "%select{%ordinal6|'this'}5 argument (%2) has %select{no|__weak|__strong}3 " - "ownership, but parameter has %select{no|__weak|__strong}4 ownership">; -def note_ovl_candidate_bad_ownership : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 not viable: " - "%select{%ordinal6|'this'}5 argument (%2) has " - "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}3 ownership," + "; remove &}7">; +def note_ovl_candidate_bad_arc_conv : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "cannot implicitly convert argument " + "%diff{of type $ to $|type to parameter type}3,4 for " + "%select{%ordinal6 argument|object argument}5 under ARC">; +def note_ovl_candidate_bad_lvalue : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "expects an l-value for " + "%select{%ordinal4 argument|object argument}3">; +def note_ovl_candidate_bad_addrspace : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "address space mismatch in %select{%ordinal6|'this'}5 argument (%3), " + "parameter type must be %4">; +def note_ovl_candidate_bad_gc : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "%select{%ordinal7|'this'}6 argument (%3) has %select{no|__weak|__strong}4 " + "ownership, but parameter has %select{no|__weak|__strong}5 ownership">; +def note_ovl_candidate_bad_ownership : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "%select{%ordinal7|'this'}6 argument (%3) has " + "%select{no|__unsafe_unretained|__strong|__weak|__autoreleasing}4 ownership," " but parameter has %select{no|__unsafe_unretained|__strong|__weak|" - "__autoreleasing}4 ownership">; -def note_ovl_candidate_bad_cvr_this : Note<"candidate " - "%select{|function|||function|||||" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)||}0 not viable: " - "'this' argument has type %2, but method is not marked " + "__autoreleasing}5 ownership">; +def note_ovl_candidate_bad_cvr_this : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "'this' argument has type %3, but method is not marked " "%select{const|restrict|const or restrict|volatile|const or volatile|" - "volatile or restrict|const, volatile, or restrict}3">; -def note_ovl_candidate_bad_cvr : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 not viable: " - "%ordinal4 argument (%2) would lose " + "volatile or restrict|const, volatile, or restrict}4">; +def note_ovl_candidate_bad_cvr : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "%ordinal5 argument (%3) would lose " "%select{const|restrict|const and restrict|volatile|const and volatile|" - "volatile and restrict|const, volatile, and restrict}3 qualifier" - "%select{||s||s|s|s}3">; -def note_ovl_candidate_bad_unaligned : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 not viable: " - "%ordinal4 argument (%2) would lose __unaligned qualifier">; -def note_ovl_candidate_bad_base_to_derived_conv : Note<"candidate " - "%select{function|function|constructor|" - "function |function |constructor |" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor }0%1 not viable: " - "cannot %select{convert from|convert from|bind}2 " - "%select{base class pointer|superclass|base class object of type}2 %3 to " - "%select{derived class pointer|subclass|derived class reference}2 %4 for " - "%ordinal5 argument">; + "volatile and restrict|const, volatile, and restrict}4 qualifier" + "%select{||s||s|s|s}4">; +def note_ovl_candidate_bad_unaligned : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "%ordinal5 argument (%3) would lose __unaligned qualifier">; +def note_ovl_candidate_bad_base_to_derived_conv : Note< + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " + "cannot %select{convert from|convert from|bind}3 " + "%select{base class pointer|superclass|base class object of type}3 %4 to " + "%select{derived class pointer|subclass|derived class reference}3 %5 for " + "%ordinal6 argument">; def note_ovl_candidate_bad_target : Note< - "candidate %select{function|function|constructor|" - "function|function|constructor|" - "constructor (the implicit default constructor)|" - "constructor (the implicit copy constructor)|" - "constructor (the implicit move constructor)|" - "function (the implicit copy assignment operator)|" - "function (the implicit move assignment operator)|" - "inherited constructor|" - "inherited constructor}0 not viable: " + "candidate %sub{select_ovl_candidate_kind}0,1,2 not viable: " "call to " - "%select{__device__|__global__|__host__|__host__ __device__|invalid}1 function from" - " %select{__device__|__global__|__host__|__host__ __device__|invalid}2 function">; + "%select{__device__|__global__|__host__|__host__ __device__|invalid}3 function from" + " %select{__device__|__global__|__host__|__host__ __device__|invalid}4 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 " + "implicit %sub{select_special_member_kind}0 inferred target collision: call to both " "%select{__device__|__global__|__host__|__host__ __device__}1 and " "%select{__device__|__global__|__host__|__host__ __device__}2 members">; @@ -3842,16 +3784,14 @@ def err_ovl_deleted_oper : Error< "overload resolution selected %select{unavailable|deleted}0 operator '%1'%2">; def err_ovl_deleted_special_oper : Error< "object of type %0 cannot be %select{constructed|copied|moved|assigned|" - "assigned|destroyed}1 because its %select{default constructor|" - "copy constructor|move constructor|copy assignment operator|" - "move assignment operator|destructor}1 is implicitly deleted">; + "assigned|destroyed}1 because its %sub{select_special_member_kind}1 is implicitly deleted">; def err_ovl_no_viable_subscript : Error<"no viable overloaded operator[] for type %0">; def err_ovl_no_oper : Error<"type %0 does not provide a %select{subscript|call}1 operator">; def err_ovl_unresolvable : Error< - "reference to overloaded function could not be resolved; " - "did you mean to call it%select{| with no arguments}0?">; + "reference to %select{overloaded|multiversioned}1 function could not be " + "resolved; did you mean to call it%select{| with no arguments}0?">; def err_bound_member_function : Error< "reference to non-static member function must be called" "%select{|; did you mean to call it with no arguments?}0">; @@ -3961,8 +3901,6 @@ def err_template_member_noparams : Error< "extraneous 'template<>' in declaration of member %0">; def err_template_tag_noparams : Error< "extraneous 'template<>' in declaration of %0 %1">; -def err_template_decl_ref : Error< - "cannot refer to %select{class|variable}0 template %1 without a template argument list">; // C++ Template Argument Lists def err_template_missing_args : Error< @@ -4130,42 +4068,20 @@ def note_explicit_specialization_declared_here : Note< "explicit specialization declared here">; def err_template_spec_decl_function_scope : Error< "explicit specialization of %0 in function scope">; -def err_template_spec_decl_class_scope : Error< - "explicit specialization of %0 in class scope">; def err_template_spec_decl_friend : Error< "cannot declare an explicit specialization in a friend">; -def err_template_spec_decl_out_of_scope_global : Error< - "%select{class template|class template partial|variable template|" - "variable template partial|function template|member function|" - "static data member|member class|member enumeration}0 " - "specialization of %1 must originally be declared in the global scope">; -def err_template_spec_decl_out_of_scope : Error< - "%select{class template|class template partial|variable template|" - "variable template partial|function template|member " - "function|static data member|member class|member enumeration}0 " - "specialization of %1 must originally be declared in namespace %2">; -def ext_template_spec_decl_out_of_scope : ExtWarn< - "first declaration of %select{class template|class template partial|" - "variable template|variable template partial|" - "function template|member function|static data member|member class|" - "member enumeration}0 specialization of %1 outside namespace %2 is a " - "C++11 extension">, InGroup<CXX11>; -def warn_cxx98_compat_template_spec_decl_out_of_scope : Warning< - "%select{class template|class template partial|variable template|" - "variable template partial|function template|member " - "function|static data member|member class|member enumeration}0 " - "specialization of %1 outside namespace %2 is incompatible with C++98">, - InGroup<CXX98Compat>, DefaultIgnore; def err_template_spec_redecl_out_of_scope : Error< "%select{class template|class template partial|variable template|" "variable template partial|function template|member " "function|static data member|member class|member enumeration}0 " - "specialization of %1 not in a namespace enclosing %2">; + "specialization of %1 not in %select{a namespace enclosing %2|" + "class %2 or an enclosing namespace}3">; def ext_ms_template_spec_redecl_out_of_scope: ExtWarn< "%select{class template|class template partial|variable template|" "variable template partial|function template|member " "function|static data member|member class|member enumeration}0 " - "specialization of %1 outside namespace enclosing %2 " + "specialization of %1 not in %select{a namespace enclosing %2|" + "class %2 or an enclosing namespace}3 " "is a Microsoft extension">, InGroup<MicrosoftTemplate>; def err_template_spec_redecl_global_scope : Error< "%select{class template|class template partial|variable template|" @@ -4187,16 +4103,18 @@ def err_template_spec_default_arg : Error< def err_not_class_template_specialization : Error< "cannot specialize a %select{dependent template|template template " "parameter}0">; -def err_function_specialization_in_class : Error< - "cannot specialize a function %0 within class scope">; -def ext_function_specialization_in_class : ExtWarn< - "explicit specialization of %0 within class scope is a Microsoft extension">, - InGroup<MicrosoftTemplate>; def ext_explicit_specialization_storage_class : ExtWarn< "explicit specialization cannot have a storage class">; def err_explicit_specialization_inconsistent_storage_class : Error< "explicit specialization has extraneous, inconsistent storage class " "'%select{none|extern|static|__private_extern__|auto|register}0'">; +def err_dependent_function_template_spec_no_match : Error< + "no candidate function template was found for dependent" + " friend function template specialization">; +def note_dependent_function_template_spec_discard_reason : Note< + "candidate ignored: %select{not a function template" + "|not a member of the enclosing namespace;" + " did you mean to explicitly qualify the specialization?}0">; // C++ class template specializations and out-of-line definitions def err_template_spec_needs_header : Error< @@ -4493,6 +4411,8 @@ def note_using_value_decl_missing_typename : Note< def err_template_kw_refers_to_non_template : Error< "%0 following the 'template' keyword does not refer to a template">; +def note_template_kw_refers_to_non_template : Note< + "declared as a non-template here">; def err_template_kw_refers_to_class_template : Error< "'%0%1' instantiated to a class template, not a function template">; def note_referenced_class_template : Note< @@ -4554,6 +4474,9 @@ def err_pack_expansion_length_conflict : Error< def err_pack_expansion_length_conflict_multilevel : Error< "pack expansion contains parameter pack %0 that has a different " "length (%1 vs. %2) from outer parameter packs">; +def err_pack_expansion_length_conflict_partial : Error< + "pack expansion contains parameter pack %0 that has a different " + "length (at least %1 vs. %2) from outer parameter packs">; def err_pack_expansion_member_init : Error< "pack expansion for initialization of member %0">; @@ -5112,12 +5035,17 @@ def note_protected_by_objc_strong_init : Note< "jump bypasses initialization of __strong variable">; def note_protected_by_objc_weak_init : Note< "jump bypasses initialization of __weak variable">; +def note_protected_by_non_trivial_c_struct_init : Note< + "jump bypasses initialization of variable of non-trivial C struct type">; def note_enters_block_captures_cxx_obj : Note< "jump enters lifetime of block which captures a destructible C++ object">; def note_enters_block_captures_strong : Note< "jump enters lifetime of block which strongly captures a variable">; def note_enters_block_captures_weak : Note< "jump enters lifetime of block which weakly captures a variable">; +def note_enters_block_captures_non_trivial_c_struct : Note< + "jump enters lifetime of block which captures a C struct that is non-trivial " + "to destroy">; def note_exits_cleanup : Note< "jump exits scope of variable with __attribute__((cleanup))">; @@ -5158,6 +5086,9 @@ def note_exits_block_captures_strong : Note< "jump exits lifetime of block which strongly captures a variable">; def note_exits_block_captures_weak : Note< "jump exits lifetime of block which weakly captures a variable">; +def note_exits_block_captures_non_trivial_c_struct : Note< + "jump exits lifetime of block which captures a C struct that is non-trivial " + "to destroy">; def err_func_returning_qualified_void : ExtWarn< "function cannot return qualified void type %0">, @@ -5411,8 +5342,6 @@ def warn_block_capture_autoreleasing : Warning< "block captures an autoreleasing out-parameter, which may result in " "use-after-free bugs">, InGroup<BlockCaptureAutoReleasing>; -def note_declare_parameter_autoreleasing : Note< - "declare the parameter __autoreleasing explicitly to suppress this warning">; def note_declare_parameter_strong : Note< "declare the parameter __strong or capture a __block __strong variable to " "keep values alive across autorelease pools">; @@ -5601,9 +5530,12 @@ def warn_addition_in_bitshift : Warning< "operator '%0' has lower precedence than '%1'; " "'%1' will be evaluated first">, InGroup<ShiftOpParentheses>; -def warn_self_assignment : Warning< +def warn_self_assignment_builtin : Warning< "explicitly assigning value of variable of type %0 to itself">, InGroup<SelfAssignment>, DefaultIgnore; +def warn_self_assignment_overloaded : Warning< + "explicitly assigning value of variable of type %0 to itself">, + InGroup<SelfAssignmentOverloaded>, DefaultIgnore; def warn_self_move : Warning< "explicitly moving variable of type %0 to itself">, InGroup<SelfMove>, DefaultIgnore; @@ -5619,6 +5551,19 @@ def warn_pessimizing_move_on_initialization : Warning< InGroup<PessimizingMove>, DefaultIgnore; def note_remove_move : Note<"remove std::move call here">; +def warn_return_std_move : Warning< + "local variable %0 will be copied despite being %select{returned|thrown}1 by name">, + InGroup<ReturnStdMove>, DefaultIgnore; +def note_add_std_move : Note< + "call 'std::move' explicitly to avoid copying">; +def warn_return_std_move_in_cxx11 : Warning< + "prior to the resolution of a defect report against ISO C++11, " + "local variable %0 would have been copied despite being returned by name, " + "due to its not matching the function return type%diff{ ($ vs $)|}1,2">, + InGroup<ReturnStdMoveInCXX11>, DefaultIgnore; +def note_add_std_move_in_cxx11 : Note< + "call 'std::move' explicitly to avoid copying on older compilers">; + def warn_string_plus_int : Warning< "adding %0 to a string does not append to the string">, InGroup<StringPlusInt>; @@ -5797,6 +5742,13 @@ def err_array_init_wide_string_into_char : Error< "initializing char array with wide string literal">; def err_array_init_incompat_wide_string_into_wchar : Error< "initializing wide char array with incompatible wide string literal">; +def err_array_init_plain_string_into_char8_t : Error< + "initializing 'char8_t' array with plain string literal">; +def note_array_init_plain_string_into_char8_t : Note< + "add 'u8' prefix to form a 'char8_t' string literal">; +def err_array_init_utf8_string_into_char : Error< + "initialization of char array with UTF-8 string literal is not permitted " + "by '-fchar8_t'">; def err_array_init_different_type : Error< "cannot initialize array %diff{of type $ with array of type $|" "with different type of array}0,1">; @@ -5881,6 +5833,8 @@ def err_objc_object_assignment : Error< "cannot assign to class object (%0 invalid)">; def err_typecheck_invalid_operands : Error< "invalid operands to binary expression (%0 and %1)">; +def note_typecheck_invalid_operands_converted : Note< + "%select{first|second}0 operand was implicitly converted to type %1">; def err_typecheck_logical_vector_expr_gnu_cpp_restrict : Error< "logical expression with vector %select{type %1 and non-vector type %2|types" " %1 and %2}0 is only supported in C++">; @@ -5894,7 +5848,8 @@ def ext_typecheck_ordered_comparison_of_pointer_and_zero : Extension< def err_typecheck_ordered_comparison_of_pointer_and_zero : Error< "ordered comparison between pointer and zero (%0 and %1)">; def ext_typecheck_ordered_comparison_of_function_pointers : ExtWarn< - "ordered comparison of function pointers (%0 and %1)">; + "ordered comparison of function pointers (%0 and %1)">, + InGroup<DiagGroup<"ordered-compare-function-pointers">>; def ext_typecheck_comparison_of_fptr_to_void : Extension< "equality comparison between function pointer and void pointer (%0 and %1)">; def err_typecheck_comparison_of_fptr_to_void : Error< @@ -5942,15 +5897,15 @@ def note_typecheck_assign_const : Note< def warn_unsigned_always_true_comparison : Warning< "result of comparison of %select{%3|unsigned expression}0 %2 " "%select{unsigned expression|%3}0 is always %4">, - InGroup<TautologicalUnsignedZeroCompare>; + InGroup<TautologicalUnsignedZeroCompare>, DefaultIgnore; def warn_unsigned_enum_always_true_comparison : Warning< "result of comparison of %select{%3|unsigned enum expression}0 %2 " "%select{unsigned enum expression|%3}0 is always %4">, - InGroup<TautologicalUnsignedEnumZeroCompare>; + InGroup<TautologicalUnsignedEnumZeroCompare>, DefaultIgnore; def warn_tautological_constant_compare : Warning< "result of comparison %select{%3|%1}0 %2 " "%select{%1|%3}0 is always %4">, - InGroup<TautologicalConstantCompare>; + InGroup<TautologicalTypeLimitCompare>, DefaultIgnore; def warn_mixed_sign_comparison : Warning< "comparison of integers of different signs: %0 and %1">, @@ -6186,9 +6141,9 @@ def err_objc_object_catch : Error< def err_incomplete_type_objc_at_encode : Error< "'@encode' of incomplete type %0">; def warn_objc_circular_container : Warning< - "adding '%0' to '%1' might cause circular dependency in container">, + "adding %0 to %1 might cause circular dependency in container">, InGroup<DiagGroup<"objc-circular-container">>; -def note_objc_circular_container_declared_here : Note<"'%0' declared here">; +def note_objc_circular_container_declared_here : Note<"%0 declared here">; def warn_objc_unsafe_perform_selector : Warning< "%0 is incompatible with selectors that return a " "%select{struct|union|vector}1 type">, @@ -6260,6 +6215,12 @@ def err_bad_cxx_cast_bitfield : Error< def err_bad_cxx_cast_qualifiers_away : Error< "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" "functional-style cast}0 from %1 to %2 casts away qualifiers">; +def ext_bad_cxx_cast_qualifiers_away_incoherent : ExtWarn< + "ISO C++ does not allow " + "%select{const_cast|static_cast|reinterpret_cast|dynamic_cast|C-style cast|" + "functional-style cast}0 from %1 to %2 because it casts away qualifiers, " + "even though the source and destination types are unrelated">, + SFINAEFailure, InGroup<DiagGroup<"cast-qual-unrelated">>; def err_bad_const_cast_dest : Error< "%select{const_cast||||C-style cast|functional-style cast}0 to %2, " "which is not a reference, pointer-to-object, or pointer-to-data-member">; @@ -6440,6 +6401,8 @@ def err_bad_memptr_rhs : Error< def err_bad_memptr_lhs : Error< "left hand operand to %0 must be a %select{|pointer to }1class " "compatible with the right hand operand, but is %2">; +def err_memptr_incomplete : Error< + "member pointer has incomplete base type %0">; def warn_exception_caught_by_earlier_handler : Warning< "exception of type %0 will be caught by earlier handler">, InGroup<Exceptions>; @@ -6561,6 +6524,8 @@ let CategoryName = "Lambda Issue" in { "lambda expression in an unevaluated operand">; def err_lambda_in_constant_expression : Error< "a lambda expression may not appear inside of a constant expression">; + def err_lambda_in_invalid_context : Error< + "a lambda expression cannot appear in this context">; def err_lambda_return_init_list : Error< "cannot deduce lambda return type from initializer list">; def err_lambda_capture_default_arg : Error< @@ -6619,6 +6584,11 @@ let CategoryName = "Lambda Issue" in { def ext_equals_this_lambda_capture_cxx2a : ExtWarn< "explicit capture of 'this' with a capture default of '=' " "is a C++2a extension">, InGroup<CXX2a>; + def warn_deprecated_this_capture : Warning< + "implicit capture of 'this' with a capture default of '=' is deprecated">, + InGroup<DeprecatedThisCapture>, DefaultIgnore; + def note_deprecated_this_capture : Note< + "add an explicit capture of 'this' to capture '*this' by reference">; } def err_return_in_captured_stmt : Error< @@ -6688,9 +6658,9 @@ def err_not_tag_in_scope : Error< "no %select{struct|interface|union|class|enum}0 named %1 in %2">; def err_no_typeid_with_fno_rtti : Error< - "cannot use typeid with -fno-rtti">; + "use of typeid requires -frtti">; def err_no_dynamic_cast_with_fno_rtti : Error< - "cannot use dynamic_cast with -fno-rtti">; + "use of dynamic_cast requires -frtti">; def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; @@ -7055,6 +7025,8 @@ def err_atomic_builtin_must_be_pointer : Error< def err_atomic_builtin_must_be_pointer_intptr : Error< "address argument to atomic builtin must be a pointer to integer or pointer" " (%0 invalid)">; +def err_atomic_builtin_cannot_be_const : Error< + "address argument to atomic builtin cannot be const-qualified (%0 invalid)">; def err_atomic_builtin_must_be_pointer_intfltptr : Error< "address argument to atomic builtin must be a pointer to integer," " floating-point or pointer (%0 invalid)">; @@ -7079,6 +7051,8 @@ def err_atomic_op_needs_trivial_copy : Error< def err_atomic_op_needs_atomic_int_or_ptr : Error< "address argument to atomic operation must be a pointer to %select{|atomic }0" "integer or pointer (%1 invalid)">; +def err_atomic_op_needs_int32_or_ptr : Error< + "address argument to atomic operation must be a pointer to signed or unsigned 32-bit integer">; def err_atomic_op_bitwise_needs_atomic_int : Error< "address argument to bitwise atomic operation must be a pointer to " "%select{|atomic }0integer (%1 invalid)">; @@ -7087,6 +7061,9 @@ def warn_atomic_op_has_invalid_memory_order : Warning< InGroup<DiagGroup<"atomic-memory-ordering">>; def err_atomic_op_has_invalid_synch_scope : Error< "synchronization scope argument to atomic operation is invalid">; +def warn_atomic_op_misaligned : Warning< + "misaligned or large atomic operation may incur significant performance penalty">, + InGroup<DiagGroup<"atomic-alignment">>; def err_overflow_builtin_must_be_int : Error< "operand argument to overflow builtin must be an integer (%0 invalid)">; @@ -7137,7 +7114,7 @@ def err_va_arg_in_device : Error< "CUDA device code does not support va_arg">; def err_alias_not_supported_on_nvptx : Error<"CUDA does not support aliases">; def err_cuda_unattributed_constexpr_cannot_overload_device : Error< - "constexpr function '%0' without __host__ or __device__ attributes cannot " + "constexpr function %0 without __host__ or __device__ attributes cannot " "overload __device__ function with same signature. Add a __host__ " "attribute, or build with -fno-cuda-host-device-constexpr.">; def note_cuda_conflicting_device_function_declared_here : Note< @@ -7176,6 +7153,10 @@ def err_cannot_pass_objc_interface_to_vararg_format : Error< "cannot pass object with interface type %1 by value to variadic " "%select{function|block|method|constructor}2; expected type from format " "string was %3">; +def err_cannot_pass_non_trivial_c_struct_to_vararg : Error< + "cannot pass non-trivial C object of type %0 by value to variadic " + "%select{function|block|method|constructor}1">; + def err_cannot_pass_objc_interface_to_vararg : Error< "cannot pass object with interface type %0 by value through variadic " @@ -7623,6 +7604,11 @@ def err_destroying_operator_delete_not_usual : Error< "alignment parameter">; def note_implicit_delete_this_in_destructor_here : Note< "while checking implicit 'delete this' for virtual destructor">; +def err_builtin_operator_new_delete_not_usual : Error< + "call to '%select{__builtin_operator_new|__builtin_operator_delete}0' " + "selects non-usual %select{allocation|deallocation}0 function">; +def note_non_usual_function_declared_here : Note< + "non-usual %0 declared here">; // C++ literal operators def err_literal_operator_outside_namespace : Error< @@ -7705,9 +7691,8 @@ def err_defaulted_special_member_quals : Error< "an explicitly-defaulted %select{copy|move}0 assignment operator may not " "have 'const'%select{, 'constexpr'|}1 or 'volatile' qualifiers">; def err_defaulted_special_member_volatile_param : Error< - "the parameter for an explicitly-defaulted %select{<<ERROR>>|" - "copy constructor|move constructor|copy assignment operator|" - "move assignment operator|<<ERROR>>}0 may not be volatile">; + "the parameter for an explicitly-defaulted %sub{select_special_member_kind}0 " + "may not be volatile">; def err_defaulted_special_member_move_const_param : Error< "the parameter for an explicitly-defaulted move " "%select{constructor|assignment operator}0 may not be const">; @@ -7719,17 +7704,13 @@ def err_defaulted_copy_assign_not_ref : Error< "the parameter for an explicitly-defaulted copy assignment operator must be an " "lvalue reference type">; def err_incorrect_defaulted_exception_spec : Error< - "exception specification of explicitly defaulted %select{default constructor|" - "copy constructor|move constructor|copy assignment operator|move assignment " - "operator|destructor}0 does not match the " - "calculated one">; + "exception specification of explicitly defaulted " + "%sub{select_special_member_kind}0 does not match the calculated one">; def err_incorrect_defaulted_constexpr : Error< - "defaulted definition of %select{default constructor|copy constructor|" - "move constructor|copy assignment operator|move assignment operator}0 " + "defaulted definition of %sub{select_special_member_kind}0 " "is not constexpr">; def err_out_of_line_default_deletes : Error< - "defaulting this %select{default constructor|copy constructor|move " - "constructor|copy assignment operator|move assignment operator|destructor}0 " + "defaulting this %sub{select_special_member_kind}0 " "would delete it after its first declaration">; def warn_vbase_moved_multiple_times : Warning< "defaulted move assignment operator of %0 will move assign virtual base " @@ -7784,6 +7765,10 @@ def warn_format_argument_needs_cast : Warning< "%select{values of type|enum values with underlying type}2 '%0' should not " "be used as format arguments; add an explicit cast to %1 instead">, InGroup<Format>; +def warn_format_argument_needs_cast_pedantic : Warning< + "%select{values of type|enum values with underlying type}2 '%0' should not " + "be used as format arguments; add an explicit cast to %1 instead">, + InGroup<FormatPedantic>, DefaultIgnore; def warn_printf_positional_arg_exceeds_data_args : Warning < "data argument position '%0' exceeds the number of data arguments (%1)">, InGroup<Format>; @@ -7868,8 +7853,8 @@ def warn_null_ret : Warning< // CHECK: returning address/reference of stack memory def warn_ret_stack_addr_ref : Warning< - "%select{address of|reference to}0 stack memory associated with local " - "variable %1 returned">, + "%select{address of|reference to}0 stack memory associated with " + "%select{local variable|parameter}2 %1 returned">, InGroup<ReturnStackAddress>; def warn_ret_local_temp_addr_ref : Warning< "returning %select{address of|reference to}0 local temporary object">, @@ -7879,30 +7864,69 @@ def warn_ret_addr_label : Warning< InGroup<ReturnStackAddress>; def err_ret_local_block : Error< "returning block that lives on the local stack">; -def note_ref_var_local_bind : Note< - "binding reference variable %0 here">; +def note_local_var_initializer : Note< + "%select{via initialization of|binding reference}0 variable %1 here">; +def note_init_with_default_member_initalizer : Note< + "initializing field %0 with default member initializer">; // Check for initializing a member variable with the address or a reference to // a constructor parameter. def warn_bind_ref_member_to_parameter : Warning< - "binding reference member %0 to stack allocated parameter %1">, - InGroup<DanglingField>; + "binding reference member %0 to stack allocated " + "%select{variable|parameter}2 %1">, InGroup<DanglingField>; def warn_init_ptr_member_to_parameter_addr : Warning< - "initializing pointer member %0 with the stack address of parameter %1">, - InGroup<DanglingField>; -def warn_bind_ref_member_to_temporary : Warning< - "binding reference %select{|subobject of }1member %0 to a temporary value">, - InGroup<DanglingField>; + "initializing pointer member %0 with the stack address of " + "%select{variable|parameter}2 %1">, InGroup<DanglingField>; def note_ref_or_ptr_member_declared_here : Note< "%select{reference|pointer}0 member declared here">; -def note_ref_subobject_of_member_declared_here : Note< - "member with reference subobject declared here">; + +def err_dangling_member : Error< + "%select{reference|backing array for 'std::initializer_list'}2 " + "%select{|subobject of }1member %0 " + "%select{binds to|is}2 a temporary object " + "whose lifetime would be shorter than the lifetime of " + "the constructed object">; +def warn_dangling_member : Warning< + "%select{reference|backing array for 'std::initializer_list'}2 " + "%select{|subobject of }1member %0 " + "%select{binds to|is}2 a temporary object " + "whose lifetime is shorter than the lifetime of the constructed object">, + InGroup<DanglingField>; +def note_lifetime_extending_member_declared_here : Note< + "%select{%select{reference|'std::initializer_list'}0 member|" + "member with %select{reference|'std::initializer_list'}0 subobject}1 " + "declared here">; +def warn_dangling_variable : Warning< + "%select{temporary %select{whose address is used as value of|bound to}3 " + "%select{%select{|reference }3member of local variable|" + "local %select{variable|reference}3}1|" + "array backing " + "%select{initializer list subobject of local variable|" + "local initializer list}1}0 " + "%2 will be destroyed at the end of the full-expression">, + InGroup<Dangling>; +def warn_new_dangling_reference : Warning< + "temporary bound to reference member of allocated object " + "will be destroyed at the end of the full-expression">, + InGroup<DanglingField>; +def warn_new_dangling_initializer_list : Warning< + "array backing " + "%select{initializer list subobject of the allocated object|" + "the allocated initializer list}0 " + "will be destroyed at the end of the full-expression">, + InGroup<DanglingInitializerList>; +def warn_unsupported_lifetime_extension : Warning< + "sorry, lifetime extension of " + "%select{temporary|backing array of initializer list}0 created " + "by aggregate initialization using default member initializer " + "is not supported; lifetime of %select{temporary|backing array}0 " + "will end at the end of the full-expression">, InGroup<Dangling>; // For non-floating point, expressions of the form x == x or x != x // should result in a warning, since these always evaluate to a constant. // Array comparisons have similar warnings def warn_comparison_always : Warning< - "%select{self-|array }0comparison always evaluates to %select{false|true|a constant}1">, + "%select{self-|array }0comparison always evaluates to %select{a constant|%2}1">, InGroup<TautologicalCompare>; def warn_comparison_bitwise_always : Warning< "bitwise comparison always evaluates to %select{false|true}0">, @@ -7958,7 +7982,7 @@ def err_generic_sel_multi_match : Error< // Blocks def err_blocks_disable : Error<"blocks support disabled - compile with -fblocks" - " or %select{pick a deployment target that supports them|for OpenCL 2.0 or above}0">; + " or %select{pick a deployment target that supports them|for OpenCL 2.0}0">; def err_block_returning_array_function : Error< "block cannot return %select{array|function}0 type %1">; @@ -8197,7 +8221,10 @@ def err_altivec_empty_initializer : Error<"expected initializer">; def err_invalid_neon_type_code : Error< "incompatible constant for this __builtin_neon function">; def err_argument_invalid_range : Error< - "argument should be a value from %0 to %1">; + "argument value %0 is outside the valid range [%1, %2]">; +def warn_argument_invalid_range : Warning< + "argument value %0 is outside the valid range [%1, %2]">, DefaultError, + InGroup<DiagGroup<"argument-outside-range">>; def err_argument_not_multiple : Error< "argument should be a multiple of %0">; def warn_neon_vector_initializer_non_portable : Warning< @@ -8214,6 +8241,8 @@ def err_systemz_invalid_tabort_code : Error< "invalid transaction abort code">; def err_64_bit_builtin_32_bit_tgt : Error< "this builtin is only available on 64-bit targets">; +def err_32_bit_builtin_64_bit_tgt : Error< + "this builtin is only available on 32-bit targets">; def err_builtin_x64_aarch64_only : Error< "this builtin is only available on x86-64 and aarch64 targets">; def err_ppc_builtin_only_on_pwr7 : Error< @@ -8222,7 +8251,15 @@ def err_x86_builtin_invalid_rounding : Error< "invalid rounding argument">; def err_x86_builtin_invalid_scale : Error< "scale argument must be 1, 2, 4, or 8">; - +def err_hexagon_builtin_unsupported_cpu : Error< + "builtin is not supported on this CPU">; +def err_hexagon_builtin_requires_hvx : Error< + "builtin requires HVX">; +def err_hexagon_builtin_unsupported_hvx : Error< + "builtin is not supported on this version of HVX">; + +def err_builtin_target_unsupported : Error< + "builtin is not supported on this target">; def err_builtin_longjmp_unsupported : Error< "__builtin_longjmp is not supported for the current target">; def err_builtin_setjmp_unsupported : Error< @@ -8296,12 +8333,16 @@ def err_c99_array_usage_cxx : Error< "feature, not permitted in C++">; def err_type_unsupported : Error< "%0 is not supported on this target">; -def warn_nsconsumed_attribute_mismatch : Warning< +def err_nsconsumed_attribute_mismatch : Error< "overriding method has mismatched ns_consumed attribute on its" - " parameter">, InGroup<NSConsumedMismatch>; -def warn_nsreturns_retained_attribute_mismatch : Warning< + " parameter">; +def err_nsreturns_retained_attribute_mismatch : Error< "overriding method has mismatched ns_returns_%select{not_retained|retained}0" - " attributes">, InGroup<NSReturnsMismatch>; + " attributes">; +def warn_nsconsumed_attribute_mismatch : Warning< + err_nsconsumed_attribute_mismatch.Text>, InGroup<NSConsumedMismatch>; +def warn_nsreturns_retained_attribute_mismatch : Warning< + err_nsreturns_retained_attribute_mismatch.Text>, InGroup<NSReturnsMismatch>; def note_getter_unavailable : Note< "or because setter is declared here, but no getter method %0 is found">; @@ -8497,7 +8538,7 @@ def err_reference_pipe_type : Error < "pipes packet types cannot be of reference type">; def err_opencl_no_main : Error<"%select{function|kernel}0 cannot be called 'main'">; def err_opencl_kernel_attr : - Error<"attribute %0 can only be applied to a kernel function">; + Error<"attribute %0 can only be applied to an OpenCL kernel function">; def err_opencl_return_value_with_address_space : Error< "return value cannot be qualified with address space">; def err_opencl_constant_no_init : Error< @@ -8545,7 +8586,8 @@ def note_opencl_typedef_access_qualifier : Note< // OpenCL Section 6.8.g def err_opencl_unknown_type_specifier : Error< - "OpenCL version %0 does not support the '%1' %select{type qualifier|storage class specifier}2">; + "OpenCL %select{C|C++}0 version %1 does not support the '%2' " + "%select{type qualifier|storage class specifier}3">; // OpenCL v2.0 s6.12.5 Blocks restrictions def err_opencl_block_storage_type : Error< @@ -8635,8 +8677,8 @@ def err_omp_pointer_mapped_along_with_derived_section : Error< "pointer cannot be mapped along with a section derived from itself">; def err_omp_original_storage_is_shared_and_does_not_contain : Error< "original storage of expression in data environment is shared but data environment do not fully contain mapped expression storage">; -def err_omp_same_pointer_derreferenced : Error< - "same pointer derreferenced in multiple different ways in map clause expressions">; +def err_omp_same_pointer_dereferenced : Error< + "same pointer dereferenced in multiple different ways in map clause expressions">; def note_omp_task_predetermined_firstprivate_here : Note< "predetermined as a firstprivate in a task construct here">; def err_omp_threadprivate_incomplete_type : Error< @@ -8972,6 +9014,9 @@ def err_omp_reduction_vla_unsupported : Error< "cannot generate code for reduction on %select{|array section, which requires a }0variable length array">; def err_omp_linear_distribute_var_non_loop_iteration : Error< "only loop iteration variables are allowed in 'linear' clause in distribute directives">; +def warn_omp_non_trivial_type_mapped : Warning< + "Non-trivial type %0 is mapped, only trivial types are guaranteed to be mapped correctly">, + InGroup<OpenMPTarget>; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { @@ -9072,9 +9117,9 @@ def note_equivalent_internal_linkage_decl : Note< "declared here%select{ in module '%1'|}0">; def note_redefinition_modules_same_file : Note< - "'%0' included multiple times, additional include site in header from module '%1'">; + "'%0' included multiple times, additional include site in header from module '%1'">; def note_redefinition_include_same_file : Note< - "'%0' included multiple times, additional include site here">; + "'%0' included multiple times, additional include site here">; } let CategoryName = "Coroutines Issue" in { @@ -9115,7 +9160,7 @@ def err_coroutine_promise_type_incomplete : Error< "this function cannot be a coroutine: %0 is an incomplete type">; def err_coroutine_type_missing_specialization : Error< "this function cannot be a coroutine: missing definition of " - "specialization %q0">; + "specialization %0">; def err_coroutine_promise_incompatible_return_functions : Error< "the coroutine promise type %0 declares both 'return_value' and 'return_void'">; def err_coroutine_promise_requires_return_function : Error< @@ -9320,8 +9365,67 @@ def ext_warn_gnu_final : ExtWarn< InGroup<GccCompat>; def warn_shadow_field : - Warning<"non-static data member '%0' of '%1' shadows member inherited from type '%2'">, + Warning<"non-static data member %0 of %1 shadows member inherited from " + "type %2">, InGroup<ShadowField>, DefaultIgnore; def note_shadow_field : Note<"declared here">; +def err_multiversion_required_in_redecl : Error< + "function declaration is missing %select{'target'|'cpu_specific' or " + "'cpu_dispatch'}0 attribute in a multiversioned function">; +def note_multiversioning_caused_here : Note< + "function multiversioning caused by this declaration">; +def err_multiversion_after_used : Error< + "function declaration cannot become a multiversioned function after first " + "usage">; +def err_bad_multiversion_option : Error< + "function multiversioning doesn't support %select{feature|architecture}0 " + "'%1'">; +def err_multiversion_duplicate : Error< + "multiversioned function redeclarations require identical target attributes">; +def err_multiversion_noproto : Error< + "multiversioned function must have a prototype">; +def err_multiversion_no_other_attrs : Error< + "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioning cannot be combined" + " with other attributes">; +def err_multiversion_diff : Error< + "multiversioned function declaration has a different %select{calling convention" + "|return type|constexpr specification|inline specification|storage class|" + "linkage}0">; +def err_multiversion_doesnt_support : Error< + "attribute '%select{target|cpu_specific|cpu_dispatch}0' multiversioned functions do not " + "yet support %select{function templates|virtual functions|" + "deduced return types|constructors|destructors|deleted functions|" + "defaulted functions|constexpr functions}1">; +def err_multiversion_not_allowed_on_main : Error< + "'main' cannot be a multiversioned function">; +def err_multiversion_not_supported : Error< + "function multiversioning is not supported on the current target">; +def err_multiversion_types_mixed : Error< + "multiversioning attributes cannot be combined">; +def err_cpu_dispatch_mismatch : Error< + "'cpu_dispatch' function redeclared with different CPUs">; +def err_cpu_specific_multiple_defs : Error< + "multiple 'cpu_specific' functions cannot specify the same CPU: %0">; +def warn_multiversion_duplicate_entries : Warning< + "CPU list contains duplicate entries; attribute ignored">, + InGroup<FunctionMultiVersioning>; +def warn_dispatch_body_ignored : Warning< + "body of cpu_dispatch function will be ignored">, + InGroup<FunctionMultiVersioning>; + +// three-way comparison operator diagnostics +def err_implied_comparison_category_type_not_found : Error< + "cannot deduce return type of 'operator<=>' because type '%0' was not found; " + "include <compare>">; +def err_spaceship_argument_narrowing : Error< + "argument to 'operator<=>' " + "%select{cannot be narrowed from type %1 to %2|" + "evaluates to %1, which cannot be narrowed to type %2}0">; +def err_std_compare_type_not_supported : Error< + "standard library implementation of %0 is not supported; " + "%select{member '%2' does not have expected form|" + "member '%2' is missing|" + "the type is not trivially copyable|" + "the type does not have the expected form}1">; } // end of sema component. diff --git a/include/clang/Basic/DiagnosticSerializationKinds.td b/include/clang/Basic/DiagnosticSerializationKinds.td index 250b49f2cac45..3a552e2f3db42 100644 --- a/include/clang/Basic/DiagnosticSerializationKinds.td +++ b/include/clang/Basic/DiagnosticSerializationKinds.td @@ -38,8 +38,8 @@ def err_pch_targetopt_mismatch : Error< "PCH file was compiled for the %0 '%1' but the current translation " "unit is being compiled for target '%2'">; def err_pch_targetopt_feature_mismatch : Error< - "%select{AST file|current translation unit}0 was compiled with the target " - "feature'%1' but the %select{current translation unit is|AST file was}0 " + "%select{AST file was|current translation unit is}0 compiled with the target " + "feature '%1' but the %select{current translation unit is|AST file was}0 " "not">; def err_pch_langopt_mismatch : Error<"%0 was %select{disabled|enabled}1 in " "PCH file but is currently %select{disabled|enabled}2">; @@ -168,11 +168,11 @@ def err_module_odr_violation_mismatch_decl : Error< "%select{definition in module '%2'|defined here}1 found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration}3">; + "data member|friend declaration|function template}3">; def note_module_odr_violation_mismatch_decl : Note<"but in '%0' found " "%select{end of class|public access specifier|private access specifier|" "protected access specifier|static assert|field|method|type alias|typedef|" - "data member|friend declaration}1">; + "data member|friend declaration|function template}1">; def err_module_odr_violation_mismatch_decl_diff : Error< "%q0 has different definitions in different modules; first difference is " @@ -192,6 +192,8 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "%select{method %5|constructor|destructor}4 " "is %select{not deleted|deleted}6|" "%select{method %5|constructor|destructor}4 " + "is %select{not defaulted|defaulted}6|" + "%select{method %5|constructor|destructor}4 " "is %select{|pure }6%select{not virtual|virtual}7|" "%select{method %5|constructor|destructor}4 " "is %select{not static|static}6|" @@ -211,6 +213,16 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "with %ordinal6 parameter with%select{out|}7 a default argument|" "%select{method %5|constructor|destructor}4 " "with %ordinal6 parameter with a default argument|" + "%select{method %5|constructor|destructor}4 " + "with %select{no |}6template arguments|" + "%select{method %5|constructor|destructor}4 " + "with %6 template argument%s6|" + "%select{method %5|constructor|destructor}4 " + "with %6 for %ordinal7 template argument|" + "%select{method %5|constructor|destructor}4 " + "with %select{no body|body}6|" + "%select{method %5|constructor|destructor}4 " + "with body|" "%select{typedef|type alias}4 name %5|" "%select{typedef|type alias}4 %5 with underlying type %6|" "data member with name %4|" @@ -221,6 +233,18 @@ def err_module_odr_violation_mismatch_decl_diff : Error< "friend %select{class|function}4|" "friend %4|" "friend function %4|" + "function template %4 with %5 template parameter%s5|" + "function template %4 with %ordinal5 template parameter being a " + "%select{type|non-type|template}6 template parameter|" + "function template %4 with %ordinal5 template parameter " + "%select{with no name|named %7}6|" + "function template %4 with %ordinal5 template parameter with " + "%select{no |}6default argument|" + "function template %4 with %ordinal5 template parameter with " + "default argument %6|" + "function template %4 with %ordinal5 template parameter with one type|" + "function template %4 with %ordinal5 template parameter %select{not |}6" + "being a template parameter pack|" "}3">; def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " @@ -239,6 +263,8 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "%select{method %3|constructor|destructor}2 " "is %select{not deleted|deleted}4|" "%select{method %3|constructor|destructor}2 " + "is %select{not defaulted|defaulted}4|" + "%select{method %3|constructor|destructor}2 " "is %select{|pure }4%select{not virtual|virtual}5|" "%select{method %3|constructor|destructor}2 " "is %select{not static|static}4|" @@ -258,6 +284,16 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "with %ordinal4 parameter with%select{out|}5 a default argument|" "%select{method %3|constructor|destructor}2 " "with %ordinal4 parameter with a different default argument|" + "%select{method %3|constructor|destructor}2 " + "with %select{no |}4template arguments|" + "%select{method %3|constructor|destructor}2 " + "with %4 template argument%s4|" + "%select{method %3|constructor|destructor}2 " + "with %4 for %ordinal5 template argument|" + "%select{method %3|constructor|destructor}2 " + "with %select{no body|body}4|" + "%select{method %3|constructor|destructor}2 " + "with different body|" "%select{typedef|type alias}2 name %3|" "%select{typedef|type alias}2 %3 with different underlying type %4|" "data member with name %2|" @@ -268,6 +304,18 @@ def note_module_odr_violation_mismatch_decl_diff : Note<"but in '%0' found " "friend %select{class|function}2|" "friend %2|" "friend function %2|" + "function template %2 with %3 template parameter%s3|" + "function template %2 with %ordinal3 template paramter being a " + "%select{type|non-type|template}4 template parameter|" + "function template %2 with %ordinal3 template parameter " + "%select{with no name|named %5}4|" + "function template %2 with %ordinal3 template parameter with " + "%select{no |}4default argument|" + "function template %2 with %ordinal3 template parameter with " + "default argument %4|" + "function template %2 with %ordinal3 template parameter with different type|" + "function template %2 with %ordinal3 template parameter %select{not |}4" + "being a template parameter pack|" "}1">; def err_module_odr_violation_function : Error< @@ -293,6 +341,33 @@ def note_module_odr_violation_function : Note<"but in '%0' found " "a different body" "}1">; +def err_module_odr_violation_enum : Error< + "%q0 has different definitions in different modules; " + "%select{definition in module '%2'|defined here}1 " + "first difference is " + "%select{" + "enum that is %select{not scoped|scoped}4|" + "enum scoped with keyword %select{struct|class}4|" + "enum %select{without|with}4 specified type|" + "enum with specified type %4|" + "enum with %4 element%s4|" + "%ordinal4 element has name %5|" + "%ordinal4 element %5 %select{has|does not have}6 an initilizer|" + "%ordinal4 element %5 has an initializer|" + "}3">; + +def note_module_odr_violation_enum : Note<"but in '%0' found " + "%select{" + "enum that is %select{not scoped|scoped}2|" + "enum scoped with keyword %select{struct|class}2|" + "enum %select{without|with}2 specified type|" + "enum with specified type %2|" + "enum with %2 element%s2|" + "%ordinal2 element has name %3|" + "%ordinal2 element %3 %select{has|does not have}4 an initializer|" + "%ordinal2 element %3 has different initializer|" + "}1">; + def err_module_odr_violation_mismatch_decl_unknown : Error< "%q0 %select{with definition in module '%2'|defined here}1 has different " "definitions in different modules; first difference is this " diff --git a/include/clang/Basic/ExceptionSpecificationType.h b/include/clang/Basic/ExceptionSpecificationType.h index 132b5ba1e5a79..0c2c8e6d860af 100644 --- a/include/clang/Basic/ExceptionSpecificationType.h +++ b/include/clang/Basic/ExceptionSpecificationType.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the ExceptionSpecificationType enumeration and various +/// Defines the ExceptionSpecificationType enumeration and various /// utility functions. /// //===----------------------------------------------------------------------===// @@ -17,14 +17,16 @@ namespace clang { -/// \brief The various types of exception specifications that exist in C++11. +/// The various types of exception specifications that exist in C++11. enum ExceptionSpecificationType { EST_None, ///< no exception specification EST_DynamicNone, ///< throw() EST_Dynamic, ///< throw(T1, T2) EST_MSAny, ///< Microsoft throw(...) extension EST_BasicNoexcept, ///< noexcept - EST_ComputedNoexcept, ///< noexcept(expression) + EST_DependentNoexcept,///< noexcept(expression), value-dependent + EST_NoexceptFalse, ///< noexcept(expression), evals to 'false' + EST_NoexceptTrue, ///< noexcept(expression), evals to 'true' EST_Unevaluated, ///< not evaluated yet, for special member function EST_Uninstantiated, ///< not instantiated yet EST_Unparsed ///< not parsed yet @@ -34,15 +36,20 @@ inline bool isDynamicExceptionSpec(ExceptionSpecificationType ESpecType) { return ESpecType >= EST_DynamicNone && ESpecType <= EST_MSAny; } +inline bool isComputedNoexcept(ExceptionSpecificationType ESpecType) { + return ESpecType >= EST_DependentNoexcept && + ESpecType <= EST_NoexceptTrue; +} + inline bool isNoexceptExceptionSpec(ExceptionSpecificationType ESpecType) { - return ESpecType == EST_BasicNoexcept || ESpecType == EST_ComputedNoexcept; + return ESpecType == EST_BasicNoexcept || isComputedNoexcept(ESpecType); } inline bool isUnresolvedExceptionSpec(ExceptionSpecificationType ESpecType) { return ESpecType == EST_Unevaluated || ESpecType == EST_Uninstantiated; } -/// \brief Possible results from evaluation of a noexcept expression. +/// Possible results from evaluation of a noexcept expression. enum CanThrowResult { CT_Cannot, CT_Dependent, diff --git a/include/clang/Basic/ExpressionTraits.h b/include/clang/Basic/ExpressionTraits.h index 0363a1d2c74c2..2983adde1ed65 100644 --- a/include/clang/Basic/ExpressionTraits.h +++ b/include/clang/Basic/ExpressionTraits.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines enumerations for expression traits intrinsics. +/// Defines enumerations for expression traits intrinsics. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/Features.def b/include/clang/Basic/Features.def new file mode 100644 index 0000000000000..a0e0ce4560abe --- /dev/null +++ b/include/clang/Basic/Features.def @@ -0,0 +1,238 @@ +//===--- Features.def - Features and Extensions 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 features exposed via __has_feature and extensions exposed +// via __has_extension. Users of this file must either define the FEATURE or +// EXTENSION macros (or both) to make use of this information. Note that these +// macros expect the following declarations to be available for the Predicate: +// +// const LangOptions &LangOpts; +// const Preprocessor &PP; +// +// The Predicate field dictates the conditions under which the feature or +// extension will be made available. +//===----------------------------------------------------------------------===// + +#if !defined(FEATURE) && !defined(EXTENSION) +# error Define either the FEATURE or EXTENSION macro to handle features +#endif + +#ifndef FEATURE +#define FEATURE(Name, Predicate) +#endif + +#ifndef EXTENSION +#define EXTENSION(Name, Predicate) +#endif + +FEATURE(address_sanitizer, + LangOpts.Sanitize.hasOneOf(SanitizerKind::Address | + SanitizerKind::KernelAddress)) +FEATURE(hwaddress_sanitizer, + LangOpts.Sanitize.hasOneOf(SanitizerKind::HWAddress | + SanitizerKind::KernelHWAddress)) +FEATURE(assume_nonnull, true) +FEATURE(attribute_analyzer_noreturn, true) +FEATURE(attribute_availability, true) +FEATURE(attribute_availability_with_message, true) +FEATURE(attribute_availability_app_extension, true) +FEATURE(attribute_availability_with_version_underscores, true) +FEATURE(attribute_availability_tvos, true) +FEATURE(attribute_availability_watchos, true) +FEATURE(attribute_availability_with_strict, true) +FEATURE(attribute_availability_with_replacement, true) +FEATURE(attribute_availability_in_templates, true) +FEATURE(attribute_cf_returns_not_retained, true) +FEATURE(attribute_cf_returns_retained, true) +FEATURE(attribute_cf_returns_on_parameters, true) +FEATURE(attribute_deprecated_with_message, true) +FEATURE(attribute_deprecated_with_replacement, true) +FEATURE(attribute_ext_vector_type, true) +FEATURE(attribute_ns_returns_not_retained, true) +FEATURE(attribute_ns_returns_retained, true) +FEATURE(attribute_ns_consumes_self, true) +FEATURE(attribute_ns_consumed, true) +FEATURE(attribute_cf_consumed, true) +FEATURE(attribute_objc_ivar_unused, true) +FEATURE(attribute_objc_method_family, true) +FEATURE(attribute_overloadable, true) +FEATURE(attribute_unavailable_with_message, true) +FEATURE(attribute_unused_on_fields, true) +FEATURE(attribute_diagnose_if_objc, true) +FEATURE(blocks, LangOpts.Blocks) +FEATURE(c_thread_safety_attributes, true) +FEATURE(cxx_exceptions, LangOpts.CXXExceptions) +FEATURE(cxx_rtti, LangOpts.RTTI &&LangOpts.RTTIData) +FEATURE(enumerator_attributes, true) +FEATURE(nullability, true) +FEATURE(nullability_on_arrays, true) +FEATURE(memory_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Memory)) +FEATURE(thread_sanitizer, LangOpts.Sanitize.has(SanitizerKind::Thread)) +FEATURE(dataflow_sanitizer, LangOpts.Sanitize.has(SanitizerKind::DataFlow)) +FEATURE(efficiency_sanitizer, + LangOpts.Sanitize.hasOneOf(SanitizerKind::Efficiency)) +FEATURE(scudo, LangOpts.Sanitize.hasOneOf(SanitizerKind::Scudo)) +// Objective-C features +FEATURE(objc_arr, LangOpts.ObjCAutoRefCount) // FIXME: REMOVE? +FEATURE(objc_arc, LangOpts.ObjCAutoRefCount) +FEATURE(objc_arc_fields, true) +FEATURE(objc_arc_weak, LangOpts.ObjCWeak) +FEATURE(objc_default_synthesize_properties, LangOpts.ObjC2) +FEATURE(objc_fixed_enum, LangOpts.ObjC2) +FEATURE(objc_instancetype, LangOpts.ObjC2) +FEATURE(objc_kindof, LangOpts.ObjC2) +FEATURE(objc_modules, LangOpts.ObjC2 &&LangOpts.Modules) +FEATURE(objc_nonfragile_abi, LangOpts.ObjCRuntime.isNonFragile()) +FEATURE(objc_property_explicit_atomic, true) +FEATURE(objc_protocol_qualifier_mangling, true) +FEATURE(objc_weak_class, LangOpts.ObjCRuntime.hasWeakClassImport()) +FEATURE(ownership_holds, true) +FEATURE(ownership_returns, true) +FEATURE(ownership_takes, true) +FEATURE(objc_bool, true) +FEATURE(objc_subscripting, LangOpts.ObjCRuntime.isNonFragile()) +FEATURE(objc_array_literals, LangOpts.ObjC2) +FEATURE(objc_dictionary_literals, LangOpts.ObjC2) +FEATURE(objc_boxed_expressions, LangOpts.ObjC2) +FEATURE(objc_boxed_nsvalue_expressions, LangOpts.ObjC2) +FEATURE(arc_cf_code_audited, true) +FEATURE(objc_bridge_id, true) +FEATURE(objc_bridge_id_on_typedefs, true) +FEATURE(objc_generics, LangOpts.ObjC2) +FEATURE(objc_generics_variance, LangOpts.ObjC2) +FEATURE(objc_class_property, LangOpts.ObjC2) +// C11 features +FEATURE(c_alignas, LangOpts.C11) +FEATURE(c_alignof, LangOpts.C11) +FEATURE(c_atomic, LangOpts.C11) +FEATURE(c_generic_selections, LangOpts.C11) +FEATURE(c_static_assert, LangOpts.C11) +FEATURE(c_thread_local, LangOpts.C11 &&PP.getTargetInfo().isTLSSupported()) +// C++11 features +FEATURE(cxx_access_control_sfinae, LangOpts.CPlusPlus11) +FEATURE(cxx_alias_templates, LangOpts.CPlusPlus11) +FEATURE(cxx_alignas, LangOpts.CPlusPlus11) +FEATURE(cxx_alignof, LangOpts.CPlusPlus11) +FEATURE(cxx_atomic, LangOpts.CPlusPlus11) +FEATURE(cxx_attributes, LangOpts.CPlusPlus11) +FEATURE(cxx_auto_type, LangOpts.CPlusPlus11) +FEATURE(cxx_constexpr, LangOpts.CPlusPlus11) +FEATURE(cxx_constexpr_string_builtins, LangOpts.CPlusPlus11) +FEATURE(cxx_decltype, LangOpts.CPlusPlus11) +FEATURE(cxx_decltype_incomplete_return_types, LangOpts.CPlusPlus11) +FEATURE(cxx_default_function_template_args, LangOpts.CPlusPlus11) +FEATURE(cxx_defaulted_functions, LangOpts.CPlusPlus11) +FEATURE(cxx_delegating_constructors, LangOpts.CPlusPlus11) +FEATURE(cxx_deleted_functions, LangOpts.CPlusPlus11) +FEATURE(cxx_explicit_conversions, LangOpts.CPlusPlus11) +FEATURE(cxx_generalized_initializers, LangOpts.CPlusPlus11) +FEATURE(cxx_implicit_moves, LangOpts.CPlusPlus11) +FEATURE(cxx_inheriting_constructors, LangOpts.CPlusPlus11) +FEATURE(cxx_inline_namespaces, LangOpts.CPlusPlus11) +FEATURE(cxx_lambdas, LangOpts.CPlusPlus11) +FEATURE(cxx_local_type_template_args, LangOpts.CPlusPlus11) +FEATURE(cxx_nonstatic_member_init, LangOpts.CPlusPlus11) +FEATURE(cxx_noexcept, LangOpts.CPlusPlus11) +FEATURE(cxx_nullptr, LangOpts.CPlusPlus11) +FEATURE(cxx_override_control, LangOpts.CPlusPlus11) +FEATURE(cxx_range_for, LangOpts.CPlusPlus11) +FEATURE(cxx_raw_string_literals, LangOpts.CPlusPlus11) +FEATURE(cxx_reference_qualified_functions, LangOpts.CPlusPlus11) +FEATURE(cxx_rvalue_references, LangOpts.CPlusPlus11) +FEATURE(cxx_strong_enums, LangOpts.CPlusPlus11) +FEATURE(cxx_static_assert, LangOpts.CPlusPlus11) +FEATURE(cxx_thread_local, + LangOpts.CPlusPlus11 &&PP.getTargetInfo().isTLSSupported()) +FEATURE(cxx_trailing_return, LangOpts.CPlusPlus11) +FEATURE(cxx_unicode_literals, LangOpts.CPlusPlus11) +FEATURE(cxx_unrestricted_unions, LangOpts.CPlusPlus11) +FEATURE(cxx_user_literals, LangOpts.CPlusPlus11) +FEATURE(cxx_variadic_templates, LangOpts.CPlusPlus11) +// C++14 features +FEATURE(cxx_aggregate_nsdmi, LangOpts.CPlusPlus14) +FEATURE(cxx_binary_literals, LangOpts.CPlusPlus14) +FEATURE(cxx_contextual_conversions, LangOpts.CPlusPlus14) +FEATURE(cxx_decltype_auto, LangOpts.CPlusPlus14) +FEATURE(cxx_generic_lambdas, LangOpts.CPlusPlus14) +FEATURE(cxx_init_captures, LangOpts.CPlusPlus14) +FEATURE(cxx_relaxed_constexpr, LangOpts.CPlusPlus14) +FEATURE(cxx_return_type_deduction, LangOpts.CPlusPlus14) +FEATURE(cxx_variable_templates, LangOpts.CPlusPlus14) +// NOTE: For features covered by SD-6, it is preferable to provide *only* +// the SD-6 macro and not a __has_feature check. + +// C++ TSes +// FEATURE(cxx_runtime_arrays, LangOpts.CPlusPlusTSArrays) +// FEATURE(cxx_concepts, LangOpts.CPlusPlusTSConcepts) +// FIXME: Should this be __has_feature or __has_extension? +// FEATURE(raw_invocation_type, LangOpts.CPlusPlus) +// Type traits +// N.B. Additional type traits should not be added to the following list. +// Instead, they should be detected by has_extension. +FEATURE(has_nothrow_assign, LangOpts.CPlusPlus) +FEATURE(has_nothrow_copy, LangOpts.CPlusPlus) +FEATURE(has_nothrow_constructor, LangOpts.CPlusPlus) +FEATURE(has_trivial_assign, LangOpts.CPlusPlus) +FEATURE(has_trivial_copy, LangOpts.CPlusPlus) +FEATURE(has_trivial_constructor, LangOpts.CPlusPlus) +FEATURE(has_trivial_destructor, LangOpts.CPlusPlus) +FEATURE(has_virtual_destructor, LangOpts.CPlusPlus) +FEATURE(is_abstract, LangOpts.CPlusPlus) +FEATURE(is_base_of, LangOpts.CPlusPlus) +FEATURE(is_class, LangOpts.CPlusPlus) +FEATURE(is_constructible, LangOpts.CPlusPlus) +FEATURE(is_convertible_to, LangOpts.CPlusPlus) +FEATURE(is_empty, LangOpts.CPlusPlus) +FEATURE(is_enum, LangOpts.CPlusPlus) +FEATURE(is_final, LangOpts.CPlusPlus) +FEATURE(is_literal, LangOpts.CPlusPlus) +FEATURE(is_standard_layout, LangOpts.CPlusPlus) +FEATURE(is_pod, LangOpts.CPlusPlus) +FEATURE(is_polymorphic, LangOpts.CPlusPlus) +FEATURE(is_sealed, LangOpts.CPlusPlus &&LangOpts.MicrosoftExt) +FEATURE(is_trivial, LangOpts.CPlusPlus) +FEATURE(is_trivially_assignable, LangOpts.CPlusPlus) +FEATURE(is_trivially_constructible, LangOpts.CPlusPlus) +FEATURE(is_trivially_copyable, LangOpts.CPlusPlus) +FEATURE(is_union, LangOpts.CPlusPlus) +FEATURE(modules, LangOpts.Modules) +FEATURE(safe_stack, LangOpts.Sanitize.has(SanitizerKind::SafeStack)) +FEATURE(shadow_call_stack, + LangOpts.Sanitize.has(SanitizerKind::ShadowCallStack)) +FEATURE(tls, PP.getTargetInfo().isTLSSupported()) +FEATURE(underlying_type, LangOpts.CPlusPlus) + +// C11 features supported by other languages as extensions. +EXTENSION(c_alignas, true) +EXTENSION(c_alignof, true) +EXTENSION(c_atomic, true) +EXTENSION(c_generic_selections, true) +EXTENSION(c_static_assert, true) +EXTENSION(c_thread_local, PP.getTargetInfo().isTLSSupported()) +// C++11 features supported by other languages as extensions. +EXTENSION(cxx_atomic, LangOpts.CPlusPlus) +EXTENSION(cxx_deleted_functions, LangOpts.CPlusPlus) +EXTENSION(cxx_explicit_conversions, LangOpts.CPlusPlus) +EXTENSION(cxx_inline_namespaces, LangOpts.CPlusPlus) +EXTENSION(cxx_local_type_template_args, LangOpts.CPlusPlus) +EXTENSION(cxx_nonstatic_member_init, LangOpts.CPlusPlus) +EXTENSION(cxx_override_control, LangOpts.CPlusPlus) +EXTENSION(cxx_range_for, LangOpts.CPlusPlus) +EXTENSION(cxx_reference_qualified_functions, LangOpts.CPlusPlus) +EXTENSION(cxx_rvalue_references, LangOpts.CPlusPlus) +EXTENSION(cxx_variadic_templates, LangOpts.CPlusPlus) +// C++14 features supported by other languages as extensions. +EXTENSION(cxx_binary_literals, true) +EXTENSION(cxx_init_captures, LangOpts.CPlusPlus11) +EXTENSION(cxx_variable_templates, LangOpts.CPlusPlus) +// Miscellaneous language extensions +EXTENSION(overloadable_unmarked, true) + +#undef EXTENSION +#undef FEATURE diff --git a/include/clang/Basic/FileManager.h b/include/clang/Basic/FileManager.h index b817dd20c3013..ab5dfca716397 100644 --- a/include/clang/Basic/FileManager.h +++ b/include/clang/Basic/FileManager.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::FileManager interface and associated types. +/// Defines the clang::FileManager interface and associated types. /// //===----------------------------------------------------------------------===// @@ -40,7 +40,7 @@ namespace clang { class FileSystemStatCache; -/// \brief Cached information about one directory (either on disk or in +/// Cached information about one directory (either on disk or in /// the virtual file system). class DirectoryEntry { friend class FileManager; @@ -51,7 +51,7 @@ public: StringRef getName() const { return Name; } }; -/// \brief Cached information about one file (either on disk +/// Cached information about one file (either on disk /// or in the virtual file system). /// /// If the 'File' member is valid, then this FileEntry has an open file @@ -70,7 +70,7 @@ class FileEntry { bool InPCH; bool IsValid; // Is this \c FileEntry initialized and valid? - /// \brief The open file, if it is owned by the \p FileEntry. + /// The open file, if it is owned by the \p FileEntry. mutable std::unique_ptr<vfs::File> File; public: @@ -90,12 +90,12 @@ public: bool isInPCH() const { return InPCH; } time_t getModificationTime() const { return ModTime; } - /// \brief Return the directory the file lives in. + /// Return the directory the file lives in. const DirectoryEntry *getDir() const { return Dir; } bool operator<(const FileEntry &RHS) const { return UniqueID < RHS.UniqueID; } - /// \brief Check whether the file is a named pipe (and thus can't be opened by + /// Check whether the file is a named pipe (and thus can't be opened by /// the native FileManager methods). bool isNamedPipe() const { return IsNamedPipe; } @@ -106,7 +106,7 @@ public: struct FileData; -/// \brief Implements support for file system lookup, file system caching, +/// Implements support for file system lookup, file system caching, /// and directory search management. /// /// This also handles more advanced properties, such as uniquing files based @@ -117,21 +117,21 @@ class FileManager : public RefCountedBase<FileManager> { IntrusiveRefCntPtr<vfs::FileSystem> FS; FileSystemOptions FileSystemOpts; - /// \brief Cache for existing real directories. + /// Cache for existing real directories. std::map<llvm::sys::fs::UniqueID, DirectoryEntry> UniqueRealDirs; - /// \brief Cache for existing real files. + /// Cache for existing real files. std::map<llvm::sys::fs::UniqueID, FileEntry> UniqueRealFiles; - /// \brief The virtual directories that we have allocated. + /// The virtual directories that we have allocated. /// /// For each virtual file (e.g. foo/bar/baz.cpp), we add all of its parent /// directories (foo/ and foo/bar/) here. SmallVector<std::unique_ptr<DirectoryEntry>, 4> VirtualDirectoryEntries; - /// \brief The virtual files that we have allocated. + /// The virtual files that we have allocated. SmallVector<std::unique_ptr<FileEntry>, 4> VirtualFileEntries; - /// \brief A cache that maps paths to directory entries (either real or + /// A cache that maps paths to directory entries (either real or /// virtual) we have looked up /// /// The actual Entries for real directories/files are @@ -141,19 +141,19 @@ class FileManager : public RefCountedBase<FileManager> { /// llvm::StringMap<DirectoryEntry*, llvm::BumpPtrAllocator> SeenDirEntries; - /// \brief A cache that maps paths to file entries (either real or + /// A cache that maps paths to file entries (either real or /// virtual) we have looked up. /// /// \see SeenDirEntries llvm::StringMap<FileEntry*, llvm::BumpPtrAllocator> SeenFileEntries; - /// \brief The canonical names of directories. + /// The canonical names of directories. llvm::DenseMap<const DirectoryEntry *, llvm::StringRef> CanonicalDirNames; - /// \brief Storage for canonical names that we have computed. + /// Storage for canonical names that we have computed. llvm::BumpPtrAllocator CanonicalNameStorage; - /// \brief Each FileEntry we create is assigned a unique ID #. + /// Each FileEntry we create is assigned a unique ID #. /// unsigned NextFileUID; @@ -176,7 +176,7 @@ public: IntrusiveRefCntPtr<vfs::FileSystem> FS = nullptr); ~FileManager(); - /// \brief Installs the provided FileSystemStatCache object within + /// Installs the provided FileSystemStatCache object within /// the FileManager. /// /// Ownership of this object is transferred to the FileManager. @@ -190,13 +190,13 @@ public: void addStatCache(std::unique_ptr<FileSystemStatCache> statCache, bool AtBeginning = false); - /// \brief Removes the specified FileSystemStatCache object from the manager. + /// Removes the specified FileSystemStatCache object from the manager. void removeStatCache(FileSystemStatCache *statCache); - /// \brief Removes all FileSystemStatCache objects from the manager. + /// Removes all FileSystemStatCache objects from the manager. void clearStatCaches(); - /// \brief Lookup, cache, and verify the specified directory (real or + /// Lookup, cache, and verify the specified directory (real or /// virtual). /// /// This returns NULL if the directory doesn't exist. @@ -206,7 +206,7 @@ public: const DirectoryEntry *getDirectory(StringRef DirName, bool CacheFailure = true); - /// \brief Lookup, cache, and verify the specified file (real or + /// Lookup, cache, and verify the specified file (real or /// virtual). /// /// This returns NULL if the file doesn't exist. @@ -218,7 +218,7 @@ public: const FileEntry *getFile(StringRef Filename, bool OpenFile = false, bool CacheFailure = true); - /// \brief Returns the current file system options + /// Returns the current file system options FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; } const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } @@ -226,22 +226,22 @@ public: return FS; } - /// \brief Retrieve a file entry for a "virtual" file that acts as + /// Retrieve a file entry for a "virtual" file that acts as /// if there were a file with the given name on disk. /// /// The file itself is not accessed. const FileEntry *getVirtualFile(StringRef Filename, off_t Size, time_t ModificationTime); - /// \brief Open the specified file as a MemoryBuffer, returning a new + /// Open the specified file as a MemoryBuffer, returning a new /// MemoryBuffer if successful, otherwise returning null. 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); + getBufferForFile(StringRef Filename, bool isVolatile = false); - /// \brief Get the 'stat' information for the given \p Path. + /// Get the 'stat' information for the given \p Path. /// /// If the path is relative, it will be resolved against the WorkingDir of the /// FileManager's FileSystemOptions. @@ -250,10 +250,10 @@ public: bool getNoncachedStatValue(StringRef Path, vfs::Status &Result); - /// \brief Remove the real file \p Entry from the cache. + /// Remove the real file \p Entry from the cache. void invalidateCache(const FileEntry *Entry); - /// \brief If path is not absolute and FileSystemOptions set the working + /// If path is not absolute and FileSystemOptions set the working /// directory, the path is modified to be relative to the given /// working directory. /// \returns true if \c path changed. @@ -264,17 +264,17 @@ public: /// \returns true if \c Path changed to absolute. bool makeAbsolutePath(SmallVectorImpl<char> &Path) const; - /// \brief Produce an array mapping from the unique IDs assigned to each + /// Produce an array mapping from the unique IDs assigned to each /// file to the corresponding FileEntry pointer. void GetUniqueIDMapping( SmallVectorImpl<const FileEntry *> &UIDToFiles) const; - /// \brief Modifies the size and modification time of a previously created + /// Modifies the size and modification time of a previously created /// FileEntry. Use with caution. static void modifyFileEntry(FileEntry *File, off_t Size, time_t ModificationTime); - /// \brief Retrieve the canonical name for a given directory. + /// Retrieve the canonical name for a given directory. /// /// This is a very expensive operation, despite its results being cached, /// and should only be used when the physical layout of the file system is diff --git a/include/clang/Basic/FileSystemOptions.h b/include/clang/Basic/FileSystemOptions.h index 38f1346312489..8b8b13bb56869 100644 --- a/include/clang/Basic/FileSystemOptions.h +++ b/include/clang/Basic/FileSystemOptions.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::FileSystemOptions interface. +/// Defines the clang::FileSystemOptions interface. /// //===----------------------------------------------------------------------===// @@ -19,10 +19,10 @@ namespace clang { -/// \brief Keeps track of options that affect how file operations are performed. +/// Keeps track of options that affect how file operations are performed. class FileSystemOptions { public: - /// \brief If set, paths are resolved as if the working directory was + /// If set, paths are resolved as if the working directory was /// set to the value of WorkingDir. std::string WorkingDir; }; diff --git a/include/clang/Basic/FileSystemStatCache.h b/include/clang/Basic/FileSystemStatCache.h index 75f986b59bddc..45aded527c1bd 100644 --- a/include/clang/Basic/FileSystemStatCache.h +++ b/include/clang/Basic/FileSystemStatCache.h @@ -1,4 +1,4 @@ -//===--- FileSystemStatCache.h - Caching for 'stat' calls -------*- C++ -*-===// +//===- FileSystemStatCache.h - Caching for 'stat' calls ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the FileSystemStatCache interface. -/// +/// Defines the FileSystemStatCache interface. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H @@ -17,48 +17,61 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" #include "llvm/Support/FileSystem.h" +#include <cstdint> +#include <ctime> #include <memory> +#include <string> +#include <utility> namespace clang { namespace vfs { + class File; class FileSystem; -} + +} // namespace vfs // FIXME: should probably replace this with vfs::Status struct FileData { std::string Name; - uint64_t Size; - time_t ModTime; + uint64_t Size = 0; + time_t ModTime = 0; llvm::sys::fs::UniqueID UniqueID; - bool IsDirectory; - bool IsNamedPipe; - bool InPCH; - bool IsVFSMapped; // FIXME: remove this when files support multiple names - FileData() - : Size(0), ModTime(0), IsDirectory(false), IsNamedPipe(false), - InPCH(false), IsVFSMapped(false) {} + bool IsDirectory = false; + bool IsNamedPipe = false; + bool InPCH = false; + + // FIXME: remove this when files support multiple names + bool IsVFSMapped = false; + + FileData() = default; }; -/// \brief Abstract interface for introducing a FileManager cache for 'stat' +/// Abstract interface for introducing a FileManager cache for 'stat' /// system calls, which is used by precompiled and pretokenized headers to /// improve performance. class FileSystemStatCache { virtual void anchor(); + protected: std::unique_ptr<FileSystemStatCache> NextStatCache; public: - virtual ~FileSystemStatCache() {} + virtual ~FileSystemStatCache() = default; enum LookupResult { - CacheExists, ///< We know the file exists and its cached stat data. - CacheMissing ///< We know that the file doesn't exist. + /// We know the file exists and its cached stat data. + CacheExists, + + /// We know that the file doesn't exist. + CacheMissing }; - /// \brief Get the 'stat' information for the specified path, using the cache + /// Get the 'stat' information for the specified path, using the cache /// to accelerate it if possible. /// /// \returns \c true if the path does not exist or \c false if it exists. @@ -72,16 +85,16 @@ public: std::unique_ptr<vfs::File> *F, FileSystemStatCache *Cache, vfs::FileSystem &FS); - /// \brief Sets the next stat call cache in the chain of stat caches. + /// Sets the next stat call cache in the chain of stat caches. /// Takes ownership of the given stat cache. void setNextStatCache(std::unique_ptr<FileSystemStatCache> Cache) { NextStatCache = std::move(Cache); } - /// \brief Retrieve the next stat call cache in the chain. + /// Retrieve the next stat call cache in the chain. FileSystemStatCache *getNextStatCache() { return NextStatCache.get(); } - /// \brief Retrieve the next stat call cache in the chain, transferring + /// Retrieve the next stat call cache in the chain, transferring /// ownership of this cache (and, transitively, all of the remaining caches) /// to the caller. std::unique_ptr<FileSystemStatCache> takeNextStatCache() { @@ -107,16 +120,16 @@ protected: } }; -/// \brief A stat "cache" that can be used by FileManager to keep +/// A stat "cache" that can be used by FileManager to keep /// track of the results of stat() calls that occur throughout the /// execution of the front end. class MemorizeStatCalls : public FileSystemStatCache { public: - /// \brief The set of stat() calls that have been seen. + /// The set of stat() calls that have been seen. llvm::StringMap<FileData, llvm::BumpPtrAllocator> StatCalls; - typedef llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator - iterator; + using iterator = + llvm::StringMap<FileData, llvm::BumpPtrAllocator>::const_iterator; iterator begin() const { return StatCalls.begin(); } iterator end() const { return StatCalls.end(); } @@ -126,6 +139,6 @@ public: vfs::FileSystem &FS) override; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_FILESYSTEMSTATCACHE_H diff --git a/include/clang/Basic/IdentifierTable.h b/include/clang/Basic/IdentifierTable.h index 8e3c15afbfcd4..f43df5c64829d 100644 --- a/include/clang/Basic/IdentifierTable.h +++ b/include/clang/Basic/IdentifierTable.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::IdentifierInfo, clang::IdentifierTable, and +/// Defines the clang::IdentifierInfo, clang::IdentifierTable, and /// clang::Selector interfaces. // //===----------------------------------------------------------------------===// @@ -39,7 +39,7 @@ class LangOptions; class MultiKeywordSelector; class SourceLocation; -/// \brief A simple pair of identifier info and location. +/// A simple pair of identifier info and location. using IdentifierLocPair = std::pair<IdentifierInfo *, SourceLocation>; /// One of these records is kept for each identifier that @@ -89,7 +89,7 @@ public: IdentifierInfo(const IdentifierInfo &) = delete; IdentifierInfo &operator=(const IdentifierInfo &) = delete; - /// \brief Return true if this is the identifier for the specified string. + /// Return true if this is the identifier for the specified string. /// /// This is intended to be used for string literals only: II->isStr("foo"). template <std::size_t StrLen> @@ -98,7 +98,13 @@ public: memcmp(getNameStart(), Str, StrLen-1) == 0; } - /// \brief Return the beginning of the actual null-terminated string for this + /// Return true if this is the identifier for the specified StringRef. + bool isStr(llvm::StringRef Str) const { + llvm::StringRef ThisStr(getNameStart(), getLength()); + return ThisStr == Str; + } + + /// Return the beginning of the actual null-terminated string for this /// identifier. const char *getNameStart() const { if (Entry) return Entry->getKeyData(); @@ -112,7 +118,7 @@ public: return ((const actualtype*) this)->second; } - /// \brief Efficiently return the length of this identifier info. + /// Efficiently return the length of this identifier info. unsigned getLength() const { if (Entry) return Entry->getKeyLength(); // FIXME: This is gross. It would be best not to embed specific details @@ -126,12 +132,12 @@ public: return (((unsigned) p[0]) | (((unsigned) p[1]) << 8)) - 1; } - /// \brief Return the actual identifier string. + /// Return the actual identifier string. StringRef getName() const { return StringRef(getNameStart(), getLength()); } - /// \brief Return true if this identifier is \#defined to some other value. + /// Return true if this identifier is \#defined to some other value. /// \note The current definition may be in a module and not currently visible. bool hasMacroDefinition() const { return HasMacro; @@ -147,7 +153,7 @@ public: RecomputeNeedsHandleIdentifier(); } } - /// \brief Returns true if this identifier was \#defined to some value at any + /// Returns true if this identifier was \#defined to some value at any /// moment. In this case there should be an entry for the identifier in the /// macro history table in Preprocessor. bool hadMacroDefinition() const { @@ -159,10 +165,10 @@ public: /// tokens. tok::TokenKind getTokenID() const { return (tok::TokenKind)TokenID; } - /// \brief True if revertTokenIDToIdentifier() was called. + /// True if revertTokenIDToIdentifier() was called. bool hasRevertedTokenIDToIdentifier() const { return RevertedTokenID; } - /// \brief Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2 + /// Revert TokenID to tok::identifier; used for GNU libstdc++ 4.2 /// compatibility. /// /// TokenID is normally read-only but there are 2 instances where we revert it @@ -179,12 +185,12 @@ public: RevertedTokenID = false; } - /// \brief Return the preprocessor keyword ID for this identifier. + /// Return the preprocessor keyword ID for this identifier. /// /// For example, "define" will return tok::pp_define. tok::PPKeywordKind getPPKeywordID() const; - /// \brief Return the Objective-C keyword ID for the this identifier. + /// Return the Objective-C keyword ID for the this identifier. /// /// For example, 'class' will return tok::objc_class if ObjC is enabled. tok::ObjCKeywordKind getObjCKeywordID() const { @@ -195,19 +201,19 @@ public: } void setObjCKeywordID(tok::ObjCKeywordKind ID) { ObjCOrBuiltinID = ID; } - /// \brief True if setNotBuiltin() was called. + /// True if setNotBuiltin() was called. bool hasRevertedBuiltin() const { return ObjCOrBuiltinID == tok::NUM_OBJC_KEYWORDS; } - /// \brief Revert the identifier to a non-builtin identifier. We do this if + /// Revert the identifier to a non-builtin identifier. We do this if /// the name of a known builtin library function is used to declare that /// function, but an unexpected type is specified. void revertBuiltin() { setBuiltinID(0); } - /// \brief Return a value indicating whether this is a builtin function. + /// Return a value indicating whether this is a builtin function. /// /// 0 is not-built-in. 1+ are specific builtin functions. unsigned getBuiltinID() const { @@ -261,7 +267,7 @@ public: RecomputeNeedsHandleIdentifier(); } - /// \brief Return true if this token has been poisoned. + /// Return true if this token has been poisoned. bool isPoisoned() const { return IsPoisoned; } /// isCPlusPlusOperatorKeyword/setIsCPlusPlusOperatorKeyword controls whether @@ -271,10 +277,10 @@ public: } bool isCPlusPlusOperatorKeyword() const { return IsCPPOperatorKeyword; } - /// \brief Return true if this token is a keyword in the specified language. + /// Return true if this token is a keyword in the specified language. bool isKeyword(const LangOptions &LangOpts) const; - /// \brief Return true if this token is a C++ keyword in the specified + /// Return true if this token is a C++ keyword in the specified /// language. bool isCPlusPlusKeyword(const LangOptions &LangOpts) const; @@ -284,48 +290,48 @@ public: T *getFETokenInfo() const { return static_cast<T*>(FETokenInfo); } void setFETokenInfo(void *T) { FETokenInfo = T; } - /// \brief Return true if the Preprocessor::HandleIdentifier must be called + /// Return true if the Preprocessor::HandleIdentifier must be called /// on a token of this identifier. /// /// If this returns false, we know that HandleIdentifier will not affect /// the token. bool isHandleIdentifierCase() const { return NeedsHandleIdentifier; } - /// \brief Return true if the identifier in its current state was loaded + /// Return true if the identifier in its current state was loaded /// from an AST file. bool isFromAST() const { return IsFromAST; } void setIsFromAST() { IsFromAST = true; } - /// \brief Determine whether this identifier has changed since it was loaded + /// Determine whether this identifier has changed since it was loaded /// from an AST file. bool hasChangedSinceDeserialization() const { return ChangedAfterLoad; } - /// \brief Note that this identifier has changed since it was loaded from + /// Note that this identifier has changed since it was loaded from /// an AST file. void setChangedSinceDeserialization() { ChangedAfterLoad = true; } - /// \brief Determine whether the frontend token information for this + /// Determine whether the frontend token information for this /// identifier has changed since it was loaded from an AST file. bool hasFETokenInfoChangedSinceDeserialization() const { return FEChangedAfterLoad; } - /// \brief Note that the frontend token information for this identifier has + /// Note that the frontend token information for this identifier has /// changed since it was loaded from an AST file. void setFETokenInfoChangedSinceDeserialization() { FEChangedAfterLoad = true; } - /// \brief Determine whether the information for this identifier is out of + /// Determine whether the information for this identifier is out of /// date with respect to the external source. bool isOutOfDate() const { return OutOfDate; } - /// \brief Set whether the information for this identifier is out of + /// Set whether the information for this identifier is out of /// date with respect to the external source. void setOutOfDate(bool OOD) { OutOfDate = OOD; @@ -335,10 +341,10 @@ public: RecomputeNeedsHandleIdentifier(); } - /// \brief Determine whether this is the contextual keyword \c import. + /// Determine whether this is the contextual keyword \c import. bool isModulesImport() const { return IsModulesImport; } - /// \brief Set whether this identifier is the contextual keyword \c import. + /// Set whether this identifier is the contextual keyword \c import. void setModulesImport(bool I) { IsModulesImport = I; if (I) @@ -360,7 +366,7 @@ public: return getName().startswith("<#") && getName().endswith("#>"); } - /// \brief Provide less than operator for lexicographical sorting. + /// Provide less than operator for lexicographical sorting. bool operator<(const IdentifierInfo &RHS) const { return getName() < RHS.getName(); } @@ -379,7 +385,7 @@ private: } }; -/// \brief An RAII object for [un]poisoning an identifier within a scope. +/// An RAII object for [un]poisoning an identifier within a scope. /// /// \p II is allowed to be null, in which case objects of this type have /// no effect. @@ -400,7 +406,7 @@ public: } }; -/// \brief An iterator that walks over all of the known identifiers +/// An iterator that walks over all of the known identifiers /// in the lookup table. /// /// Since this iterator uses an abstract interface via virtual @@ -420,7 +426,7 @@ public: virtual ~IdentifierIterator(); - /// \brief Retrieve the next string in the identifier table and + /// Retrieve the next string in the identifier table and /// advances the iterator for the following string. /// /// \returns The next string in the identifier table. If there is @@ -428,19 +434,19 @@ public: virtual StringRef Next() = 0; }; -/// \brief Provides lookups to, and iteration over, IdentiferInfo objects. +/// Provides lookups to, and iteration over, IdentiferInfo objects. class IdentifierInfoLookup { public: virtual ~IdentifierInfoLookup(); - /// \brief Return the IdentifierInfo for the specified named identifier. + /// Return the IdentifierInfo for the specified named identifier. /// /// Unlike the version in IdentifierTable, this returns a pointer instead /// of a reference. If the pointer is null then the IdentifierInfo cannot /// be found. virtual IdentifierInfo* get(StringRef Name) = 0; - /// \brief Retrieve an iterator into the set of all identifiers + /// Retrieve an iterator into the set of all identifiers /// known to this identifier lookup source. /// /// This routine provides access to all of the identifiers known to @@ -453,7 +459,7 @@ public: virtual IdentifierIterator *getIdentifiers(); }; -/// \brief Implements an efficient mapping from strings to IdentifierInfo nodes. +/// Implements an efficient mapping from strings to IdentifierInfo nodes. /// /// This has no other purpose, but this is an extremely performance-critical /// piece of the code, as each occurrence of every identifier goes through @@ -467,17 +473,20 @@ class IdentifierTable { IdentifierInfoLookup* ExternalLookup; public: - /// \brief Create the identifier table, populating it with info about the + /// Create the identifier table. + explicit IdentifierTable(IdentifierInfoLookup *ExternalLookup = nullptr); + + /// Create the identifier table, populating it with info about the /// language keywords for the language specified by \p LangOpts. - IdentifierTable(const LangOptions &LangOpts, - IdentifierInfoLookup* externalLookup = nullptr); + explicit IdentifierTable(const LangOptions &LangOpts, + IdentifierInfoLookup *ExternalLookup = nullptr); - /// \brief Set the external identifier lookup mechanism. + /// Set the external identifier lookup mechanism. void setExternalIdentifierLookup(IdentifierInfoLookup *IILookup) { ExternalLookup = IILookup; } - /// \brief Retrieve the external identifier lookup object, if any. + /// Retrieve the external identifier lookup object, if any. IdentifierInfoLookup *getExternalIdentifierLookup() const { return ExternalLookup; } @@ -486,7 +495,7 @@ public: return HashTable.getAllocator(); } - /// \brief Return the identifier token info for the specified named + /// Return the identifier token info for the specified named /// identifier. IdentifierInfo &get(StringRef Name) { auto &Entry = *HashTable.insert(std::make_pair(Name, nullptr)).first; @@ -519,7 +528,7 @@ public: return II; } - /// \brief Gets an IdentifierInfo for the given name without consulting + /// Gets an IdentifierInfo for the given name without consulting /// external sources. /// /// This is a version of get() meant for external sources that want to @@ -554,14 +563,16 @@ public: iterator end() const { return HashTable.end(); } unsigned size() const { return HashTable.size(); } - /// \brief Print some statistics to stderr that indicate how well the + /// Print some statistics to stderr that indicate how well the /// hashing is doing. void PrintStats() const; + /// Populate the identifier table with info about the language keywords + /// for the language specified by \p LangOpts. void AddKeywords(const LangOptions &LangOpts); }; -/// \brief A family of Objective-C methods. +/// A family of Objective-C methods. /// /// These families have no inherent meaning in the language, but are /// nonetheless central enough in the existing implementations to @@ -579,7 +590,7 @@ public: /// explicitly change or remove a method's family. Therefore the /// method's family should be considered the single source of truth. enum ObjCMethodFamily { - /// \brief No particular method family. + /// No particular method family. OMF_None, // Selectors in these families may have arbitrary arity, may be @@ -611,10 +622,10 @@ enum ObjCMethodFamily { /// InvalidObjCMethodFamily. enum { ObjCMethodFamilyBitWidth = 4 }; -/// \brief An invalid value of ObjCMethodFamily. +/// An invalid value of ObjCMethodFamily. enum { InvalidObjCMethodFamily = (1 << ObjCMethodFamilyBitWidth) - 1 }; -/// \brief A family of Objective-C methods. +/// A family of Objective-C methods. /// /// These are family of methods whose result type is initially 'id', but /// but are candidate for the result type to be changed to 'instancetype'. @@ -633,7 +644,7 @@ enum ObjCStringFormatFamily { SFF_CFString }; -/// \brief Smart pointer class that efficiently represents Objective-C method +/// Smart pointer class that efficiently represents Objective-C method /// names. /// /// This class will either point to an IdentifierInfo or a @@ -706,7 +717,7 @@ public: return reinterpret_cast<void*>(InfoPtr); } - /// \brief Determine whether this is the empty selector. + /// Determine whether this is the empty selector. bool isNull() const { return InfoPtr == 0; } // Predicates to identify the selector type. @@ -720,7 +731,7 @@ public: unsigned getNumArgs() const; - /// \brief Retrieve the identifier at a given position in the selector. + /// Retrieve the identifier at a given position in the selector. /// /// Note that the identifier pointer returned may be NULL. Clients that only /// care about the text of the identifier string, and not the specific, @@ -735,7 +746,7 @@ public: /// no corresponding identifier. IdentifierInfo *getIdentifierInfoForSlot(unsigned argIndex) const; - /// \brief Retrieve the name at a given position in the selector. + /// Retrieve the name at a given position in the selector. /// /// \param argIndex The index for which we want to retrieve the name. /// This index shall be less than \c getNumArgs() unless this is a keyword @@ -745,14 +756,16 @@ public: /// name was supplied. StringRef getNameForSlot(unsigned argIndex) const; - /// \brief Derive the full selector name (e.g. "foo:bar:") and return + /// Derive the full selector name (e.g. "foo:bar:") and return /// it as an std::string. std::string getAsString() const; - /// \brief Prints the full selector name (e.g. "foo:bar:"). + /// Prints the full selector name (e.g. "foo:bar:"). void print(llvm::raw_ostream &OS) const; - /// \brief Derive the conventional family of this method. + void dump() const; + + /// Derive the conventional family of this method. ObjCMethodFamily getMethodFamily() const { return getMethodFamilyImpl(*this); } @@ -772,7 +785,7 @@ public: static ObjCInstanceTypeFamily getInstTypeMethodFamily(Selector sel); }; -/// \brief This table allows us to fully hide how we implement +/// This table allows us to fully hide how we implement /// multi-keyword caching. class SelectorTable { // Actually a SelectorTableImpl @@ -784,7 +797,7 @@ public: SelectorTable &operator=(const SelectorTable &) = delete; ~SelectorTable(); - /// \brief Can create any sort of selector. + /// Can create any sort of selector. /// /// \p NumArgs indicates whether this is a no argument selector "foo", a /// single argument selector "foo:" or multi-argument "foo:bar:". @@ -798,22 +811,25 @@ public: return Selector(ID, 0); } - /// \brief Return the total amount of memory allocated for managing selectors. + /// Return the total amount of memory allocated for managing selectors. size_t getTotalMemory() const; - /// \brief Return the default setter name for the given identifier. + /// Return the default setter name for the given identifier. /// /// This is "set" + \p Name where the initial character of \p Name /// has been capitalized. static SmallString<64> constructSetterName(StringRef Name); - /// \brief Return the default setter selector for the given identifier. + /// Return the default setter selector for the given identifier. /// /// This is "set" + \p Name where the initial character of \p Name /// has been capitalized. static Selector constructSetterSelector(IdentifierTable &Idents, SelectorTable &SelTable, const IdentifierInfo *Name); + + /// Return the property name for the given setter selector. + static std::string getPropertyNameFromSetterSelector(Selector Sel); }; /// DeclarationNameExtra - Common base of the MultiKeywordSelector, diff --git a/include/clang/Basic/LLVM.h b/include/clang/Basic/LLVM.h index e60284d1b4459..8a432db911daf 100644 --- a/include/clang/Basic/LLVM.h +++ b/include/clang/Basic/LLVM.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Forward-declares and imports various common LLVM datatypes that +/// Forward-declares and imports various common LLVM datatypes that /// clang wants to use unqualified. /// //===----------------------------------------------------------------------===// @@ -28,6 +28,7 @@ namespace llvm { // ADT's. class StringRef; class Twine; + class VersionTuple; template<typename T> class ArrayRef; template<typename T> class MutableArrayRef; template<typename T> class OwningArrayRef; @@ -60,17 +61,18 @@ namespace clang { using llvm::cast_or_null; // ADT's. - using llvm::None; - using llvm::Optional; - using llvm::StringRef; - using llvm::Twine; using llvm::ArrayRef; using llvm::MutableArrayRef; + using llvm::None; + using llvm::Optional; using llvm::OwningArrayRef; + using llvm::SaveAndRestore; using llvm::SmallString; using llvm::SmallVector; using llvm::SmallVectorImpl; - using llvm::SaveAndRestore; + using llvm::StringRef; + using llvm::Twine; + using llvm::VersionTuple; // Error handling. using llvm::Expected; diff --git a/include/clang/Basic/Lambda.h b/include/clang/Basic/Lambda.h index 1c19f1dcc8b1c..675854e67e7ad 100644 --- a/include/clang/Basic/Lambda.h +++ b/include/clang/Basic/Lambda.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines several types used to describe C++ lambda expressions +/// Defines several types used to describe C++ lambda expressions /// that are shared between the parser and AST. /// //===----------------------------------------------------------------------===// @@ -19,14 +19,14 @@ namespace clang { -/// \brief The default, if any, capture method for a lambda expression. +/// The default, if any, capture method for a lambda expression. enum LambdaCaptureDefault { LCD_None, LCD_ByCopy, LCD_ByRef }; -/// \brief The different capture forms in a lambda introducer +/// The different capture forms in a lambda introducer /// /// C++11 allows capture of \c this, or of local variables by copy or /// by reference. C++1y also allows "init-capture", where the initializer diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index ca3a0e349d62f..fc38af5b03f6e 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -106,6 +106,7 @@ LANGOPT(LineComment , 1, 0, "'//' comments") LANGOPT(Bool , 1, 0, "bool, true, and false keywords") LANGOPT(Half , 1, 0, "half keyword") LANGOPT(WChar , 1, CPlusPlus, "wchar_t keyword") +LANGOPT(Char8 , 1, 0, "char8_t keyword") LANGOPT(DeclSpecKeyword , 1, 0, "__declspec keyword") BENIGN_LANGOPT(DollarIdents , 1, 1, "'$' in identifiers") BENIGN_LANGOPT(AsmPreprocessor, 1, 0, "preprocessor in asm mode") @@ -153,6 +154,7 @@ COMPATIBLE_LANGOPT(ModulesTS , 1, 0, "C++ Modules TS") BENIGN_ENUM_LANGOPT(CompilingModule, CompilingModuleKind, 2, CMK_None, "compiling a module interface") BENIGN_LANGOPT(CompilingPCH, 1, 0, "building a pch") +BENIGN_LANGOPT(BuildingPCHWithObjectFile, 1, 0, "building a pch which has a corresponding object file") COMPATIBLE_LANGOPT(ModulesDeclUse , 1, 0, "require declaration of module uses") BENIGN_LANGOPT(ModulesSearchAll , 1, 1, "searching even non-imported modules to find unresolved references") COMPATIBLE_LANGOPT(ModulesStrictDeclUse, 1, 0, "requiring declaration of module uses and all headers to be in modules") @@ -188,21 +190,27 @@ ENUM_LANGOPT(DefaultCallingConv, DefaultCallingConvention, 3, DCC_None, "default LANGOPT(ShortEnums , 1, 0, "short enum types") LANGOPT(OpenCL , 1, 0, "OpenCL") -LANGOPT(OpenCLVersion , 32, 0, "OpenCL version") +LANGOPT(OpenCLVersion , 32, 0, "OpenCL C version") +LANGOPT(OpenCLCPlusPlus , 1, 0, "OpenCL C++") +LANGOPT(OpenCLCPlusPlusVersion , 32, 0, "OpenCL C++ version") LANGOPT(NativeHalfType , 1, 0, "Native half type support") LANGOPT(NativeHalfArgsAndReturns, 1, 0, "Native half args and returns") LANGOPT(HalfArgsAndReturns, 1, 0, "half args and returns") LANGOPT(CUDA , 1, 0, "CUDA") +LANGOPT(HIP , 1, 0, "HIP") LANGOPT(OpenMP , 32, 0, "OpenMP support and version of OpenMP (31, 40 or 45)") +LANGOPT(OpenMPSimd , 1, 0, "Use SIMD only OpenMP support.") LANGOPT(OpenMPUseTLS , 1, 0, "Use TLS for threadprivates or runtime calls") LANGOPT(OpenMPIsDevice , 1, 0, "Generate code only for OpenMP target device") +LANGOPT(OpenMPCUDAMode , 1, 0, "Generate code for OpenMP pragmas in SIMT/SPMD mode") +LANGOPT(OpenMPHostCXXExceptions , 1, 0, "C++ exceptions handling in the host code.") LANGOPT(RenderScript , 1, 0, "RenderScript") LANGOPT(CUDAIsDevice , 1, 0, "compiling for CUDA device") LANGOPT(CUDAAllowVariadicFunctions, 1, 0, "allowing variadic functions in CUDA device code") LANGOPT(CUDAHostDeviceConstexpr, 1, 1, "treating unattributed constexpr functions as __host__ __device__") -LANGOPT(CUDADeviceFlushDenormalsToZero, 1, 0, "flushing denormals to zero") LANGOPT(CUDADeviceApproxTranscendentals, 1, 0, "using approximate transcendental functions") +LANGOPT(CUDARelocatableDeviceCode, 1, 0, "generate relocatable device code") LANGOPT(SizedDeallocation , 1, 0, "sized deallocation") LANGOPT(AlignedAllocation , 1, 0, "aligned allocation") @@ -225,7 +233,7 @@ BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger Objective-C literals and su BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking") LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating point constants as single precision constants") LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math") -/// \brief FP_CONTRACT mode (on/off/fast). +/// FP_CONTRACT mode (on/off/fast). ENUM_LANGOPT(DefaultFPContractMode, FPContractModeKind, 2, FPC_Off, "FP contraction type") LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") @@ -233,11 +241,16 @@ LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") LANGOPT(ObjCWeakRuntime , 1, 0, "__weak support in the ARC runtime") LANGOPT(ObjCWeak , 1, 0, "Objective-C __weak in ARC and MRC files") LANGOPT(ObjCSubscriptingLegacyRuntime , 1, 0, "Subscripting support in legacy ObjectiveC runtime") +LANGOPT(CFProtectionBranch , 1, 0, "Control-Flow Branch Protection enabled") LANGOPT(FakeAddressSpaceMap , 1, 0, "OpenCL fake address space map") ENUM_LANGOPT(AddressSpaceMapMangling , AddrSpaceMapMangling, 2, ASMM_Target, "OpenCL address space map mangling mode") LANGOPT(IncludeDefaultHeader, 1, 0, "Include default header file for OpenCL") BENIGN_LANGOPT(DelayedTemplateParsing , 1, 0, "delayed template parsing") LANGOPT(BlocksRuntimeOptional , 1, 0, "optional blocks runtime") +LANGOPT( + CompleteMemberPointers, 1, 0, + "Require member pointer base types to be complete at the point where the " + "type's inheritance model would be determined under the Microsoft ABI") ENUM_LANGOPT(GC, GCMode, 2, NonGC, "Objective-C Garbage Collection mode") ENUM_LANGOPT(ValueVisibilityMode, Visibility, 3, DefaultVisibility, @@ -276,10 +289,25 @@ LANGOPT(XRayInstrument, 1, 0, "controls whether to do XRay instrumentation") LANGOPT(XRayAlwaysEmitCustomEvents, 1, 0, "controls whether to always emit intrinsic calls to " "__xray_customevent(...) builtin.") +LANGOPT(XRayAlwaysEmitTypedEvents, 1, 0, + "controls whether to always emit intrinsic calls to " + "__xray_typedevent(...) builtin.") + +LANGOPT(ForceEmitVTables, 1, 0, "whether to emit all vtables") BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, "allow editor placeholders in source") +ENUM_LANGOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest, + "version of Clang that we should attempt to be ABI-compatible " + "with") + +COMPATIBLE_VALUE_LANGOPT(FunctionAlignment, 5, 0, "Default alignment for functions") + +LANGOPT(FixedPoint, 1, 0, "fixed point types") +LANGOPT(PaddingOnUnsignedFixedPoint, 1, 0, + "unsigned fixed point types having one extra padding bit") + #undef LANGOPT #undef COMPATIBLE_LANGOPT #undef BENIGN_LANGOPT @@ -289,4 +317,3 @@ BENIGN_LANGOPT(AllowEditorPlaceholders, 1, 0, #undef VALUE_LANGOPT #undef COMPATIBLE_VALUE_LANGOPT #undef BENIGN_VALUE_LANGOPT - diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index f7a43adefad0c..f3a6292e5adea 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -1,4 +1,4 @@ -//===--- LangOptions.h - C Language Family Language Options -----*- C++ -*-===// +//===- LangOptions.h - C Language Family Language Options -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the clang::LangOptions interface. -/// +/// Defines the clang::LangOptions interface. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_LANGOPTIONS_H @@ -20,6 +20,8 @@ #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Sanitizers.h" #include "clang/Basic/Visibility.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" #include <string> #include <vector> @@ -43,26 +45,36 @@ protected: #include "clang/Basic/LangOptions.def" }; -/// \brief Keeps track of the various options that can be +/// Keeps track of the various options that can be /// enabled, which controls the dialect of C or C++ that is accepted. class LangOptions : public LangOptionsBase { public: - typedef clang::Visibility Visibility; + using Visibility = clang::Visibility; enum GCMode { NonGC, GCOnly, HybridGC }; enum StackProtectorMode { SSPOff, SSPOn, SSPStrong, SSPReq }; enum SignedOverflowBehaviorTy { - SOB_Undefined, // Default C standard behavior. - SOB_Defined, // -fwrapv - SOB_Trapping // -ftrapv + // Default C standard behavior. + SOB_Undefined, + + // -fwrapv + SOB_Defined, + + // -ftrapv + SOB_Trapping }; // FIXME: Unify with TUKind. enum CompilingModuleKind { - CMK_None, ///< Not compiling a module interface at all. - CMK_ModuleMap, ///< Compiling a module from a module map. - CMK_ModuleInterface ///< Compiling a C++ modules TS module interface unit. + /// Not compiling a module interface at all. + CMK_None, + + /// Compiling a module from a module map. + CMK_ModuleMap, + + /// Compiling a C++ modules TS module interface unit. + CMK_ModuleInterface }; enum PragmaMSPointersToMembersKind { @@ -90,69 +102,109 @@ public: MSVC2015 = 19 }; + /// Clang versions with different platform ABI conformance. + enum class ClangABI { + /// Attempt to be ABI-compatible with code generated by Clang 3.8.x + /// (SVN r257626). This causes <1 x long long> to be passed in an + /// integer register instead of an SSE register on x64_64. + Ver3_8, + + /// Attempt to be ABI-compatible with code generated by Clang 4.0.x + /// (SVN r291814). This causes move operations to be ignored when + /// determining whether a class type can be passed or returned directly. + Ver4, + + /// Attempt to be ABI-compatible with code generated by Clang 6.0.x + /// (SVN r321711). This causes determination of whether a type is + /// standard-layout to ignore collisions between empty base classes + /// and between base classes and member subobjects, which affects + /// whether we reuse base class tail padding in some ABIs. + Ver6, + + /// Conform to the underlying platform's C and C++ ABIs as closely + /// as we can. + Latest + }; + enum FPContractModeKind { - FPC_Off, // Form fused FP ops only where result will not be affected. - FPC_On, // Form fused FP ops according to FP_CONTRACT rules. - FPC_Fast // Aggressively fuse FP ops (E.g. FMA). + // Form fused FP ops only where result will not be affected. + FPC_Off, + + // Form fused FP ops according to FP_CONTRACT rules. + FPC_On, + + // Aggressively fuse FP ops (E.g. FMA). + FPC_Fast }; public: - /// \brief Set of enabled sanitizers. + /// Set of enabled sanitizers. SanitizerSet Sanitize; - /// \brief Paths to blacklist files specifying which objects + /// Paths to blacklist files specifying which objects /// (files, functions, variables) should not be instrumented. std::vector<std::string> SanitizerBlacklistFiles; - /// \brief Paths to the XRay "always instrument" files specifying which + /// Paths to the XRay "always instrument" files specifying which /// objects (files, functions, variables) should be imbued with the XRay /// "always instrument" attribute. + /// WARNING: This is a deprecated field and will go away in the future. std::vector<std::string> XRayAlwaysInstrumentFiles; - /// \brief Paths to the XRay "never instrument" files specifying which + /// Paths to the XRay "never instrument" files specifying which /// objects (files, functions, variables) should be imbued with the XRay /// "never instrument" attribute. + /// WARNING: This is a deprecated field and will go away in the future. std::vector<std::string> XRayNeverInstrumentFiles; + /// Paths to the XRay attribute list files, specifying which objects + /// (files, functions, variables) should be imbued with the appropriate XRay + /// attribute(s). + std::vector<std::string> XRayAttrListFiles; + clang::ObjCRuntime ObjCRuntime; std::string ObjCConstantStringClass; - /// \brief The name of the handler function to be called when -ftrapv is + /// The name of the handler function to be called when -ftrapv is /// specified. /// /// If none is specified, abort (GCC-compatible behaviour). std::string OverflowHandler; - /// \brief The name of the current module, of which the main source file + /// The module currently being compiled as speficied by -fmodule-name. + std::string ModuleName; + + /// The name of the current module, of which the main source file /// is a part. If CompilingModule is set, we are compiling the interface /// of this module, otherwise we are compiling an implementation file of - /// it. + /// it. This starts as ModuleName in case -fmodule-name is provided and + /// changes during compilation to reflect the current module. std::string CurrentModule; - /// \brief The names of any features to enable in module 'requires' decls + /// The names of any features to enable in module 'requires' decls /// in addition to the hard-coded list in Module.cpp and the target features. /// /// This list is sorted. std::vector<std::string> ModuleFeatures; - /// \brief Options for parsing comments. + /// Options for parsing comments. CommentOptions CommentOpts; - /// \brief A list of all -fno-builtin-* function names (e.g., memset). + /// A list of all -fno-builtin-* function names (e.g., memset). std::vector<std::string> NoBuiltinFuncs; - /// \brief Triples of the OpenMP targets that the host code codegen should + /// Triples of the OpenMP targets that the host code codegen should /// take into account in order to generate accurate offloading descriptors. std::vector<llvm::Triple> OMPTargetTriples; - /// \brief Name of the IR file that contains the result of the OpenMP target + /// Name of the IR file that contains the result of the OpenMP target /// host code generation. std::string OMPHostIRFile; - /// \brief Indicates whether the front-end is explicitly told that the + /// Indicates whether the front-end is explicitly told that the /// input is a header file (i.e. -x c-header). - bool IsHeaderFile; + bool IsHeaderFile = false; LangOptions(); @@ -186,15 +238,15 @@ public: return MSCompatibilityVersion >= MajorVersion * 10000000U; } - /// \brief Reset all of the options that are not considered when building a + /// Reset all of the options that are not considered when building a /// module. void resetNonModularOptions(); - /// \brief Is this a libc/libm function that is no longer recognized as a + /// Is this a libc/libm function that is no longer recognized as a /// builtin because a -fno-builtin-* option has been specified? bool isNoBuiltinFunc(StringRef Name) const; - /// \brief True if any ObjC types may have non-trivial lifetime qualifiers. + /// True if any ObjC types may have non-trivial lifetime qualifiers. bool allowsNonTrivialObjCLifetimeQualifiers() const { return ObjCAutoRefCount || ObjCWeak; } @@ -202,9 +254,12 @@ public: bool assumeFunctionsAreConvergent() const { return (CUDA && CUDAIsDevice) || OpenCL; } + + /// Return the OpenCL C or C++ version as a VersionTuple. + VersionTuple getOpenCLVersionTuple() const; }; -/// \brief Floating point control options +/// Floating point control options class FPOptions { public: FPOptions() : fp_contract(LangOptions::FPC_Off) {} @@ -219,15 +274,19 @@ public: bool allowFPContractWithinStatement() const { return fp_contract == LangOptions::FPC_On; } + bool allowFPContractAcrossStatement() const { return fp_contract == LangOptions::FPC_Fast; } + void setAllowFPContractWithinStatement() { fp_contract = LangOptions::FPC_On; } + void setAllowFPContractAcrossStatement() { fp_contract = LangOptions::FPC_Fast; } + void setDisallowFPContract() { fp_contract = LangOptions::FPC_Off; } /// Used to serialize this. @@ -238,17 +297,19 @@ private: unsigned fp_contract : 2; }; -/// \brief Describes the kind of translation unit being processed. +/// Describes the kind of translation unit being processed. enum TranslationUnitKind { - /// \brief The translation unit is a complete translation unit. + /// The translation unit is a complete translation unit. TU_Complete, - /// \brief The translation unit is a prefix to a translation unit, and is + + /// The translation unit is a prefix to a translation unit, and is /// not complete. TU_Prefix, - /// \brief The translation unit is a module. + + /// The translation unit is a module. TU_Module }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_LANGOPTIONS_H diff --git a/include/clang/Basic/Linkage.h b/include/clang/Basic/Linkage.h index 6ec8763f24910..94dcfd445b0b7 100644 --- a/include/clang/Basic/Linkage.h +++ b/include/clang/Basic/Linkage.h @@ -1,4 +1,4 @@ -//===--- Linkage.h - Linkage enumeration and utilities ----------*- C++ -*-===// +//===- Linkage.h - Linkage enumeration and utilities ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,33 +6,32 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the Linkage enumeration and various utility functions. -/// +/// Defines the Linkage enumeration and various utility functions. +// //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_BASIC_LINKAGE_H #define LLVM_CLANG_BASIC_LINKAGE_H -#include <assert.h> -#include <stdint.h> #include <utility> namespace clang { -/// \brief Describes the different kinds of linkage +/// Describes the different kinds of linkage /// (C++ [basic.link], C99 6.2.2) that an entity may have. enum Linkage : unsigned char { - /// \brief No linkage, which means that the entity is unique and + /// No linkage, which means that the entity is unique and /// can only be referred to from within its scope. NoLinkage = 0, - /// \brief Internal linkage, which indicates that the entity can + /// Internal linkage, which indicates that the entity can /// be referred to from within the translation unit (but not other /// translation units). InternalLinkage, - /// \brief External linkage within a unique namespace. + /// External linkage within a unique namespace. /// /// From the language perspective, these entities have external /// linkage. However, since they reside in an anonymous namespace, @@ -41,27 +40,27 @@ enum Linkage : unsigned char { /// point of view. UniqueExternalLinkage, - /// \brief No linkage according to the standard, but is visible from other + /// No linkage according to the standard, but is visible from other /// translation units because of types defined in a inline function. VisibleNoLinkage, - /// \brief Internal linkage according to the Modules TS, but can be referred + /// Internal linkage according to the Modules TS, but can be referred /// to from other translation units indirectly through inline functions and /// templates in the module interface. ModuleInternalLinkage, - /// \brief Module linkage, which indicates that the entity can be referred + /// Module linkage, which indicates that the entity can be referred /// to from other translation units within the same module, and indirectly /// from arbitrary other translation units through inline functions and /// templates in the module interface. ModuleLinkage, - /// \brief External linkage, which indicates that the entity can + /// External linkage, which indicates that the entity can /// be referred to from other translation units. ExternalLinkage }; -/// \brief Describes the different kinds of language linkage +/// Describes the different kinds of language linkage /// (C++ [dcl.link]) that an entity may have. enum LanguageLinkage { CLanguageLinkage, @@ -69,7 +68,7 @@ enum LanguageLinkage { NoLanguageLinkage }; -/// \brief A more specific kind of linkage than enum Linkage. +/// A more specific kind of linkage than enum Linkage. /// /// This is relevant to CodeGen and AST file reading. enum GVALinkage { @@ -105,7 +104,7 @@ inline bool isExternalFormalLinkage(Linkage L) { return getFormalLinkage(L) == ExternalLinkage; } -/// \brief Compute the minimum linkage given two linkages. +/// Compute the minimum linkage given two linkages. /// /// The linkage can be interpreted as a pair formed by the formal linkage and /// a boolean for external visibility. This is just what getFormalLinkage and @@ -125,6 +124,6 @@ inline Linkage minLinkage(Linkage L1, Linkage L2) { return L1 < L2 ? L1 : L2; } -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_BASIC_LINKAGE_H diff --git a/include/clang/Basic/MacroBuilder.h b/include/clang/Basic/MacroBuilder.h index 9a9eaa24983ca..b2edc972fee22 100644 --- a/include/clang/Basic/MacroBuilder.h +++ b/include/clang/Basic/MacroBuilder.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::MacroBuilder utility class. +/// Defines the clang::MacroBuilder utility class. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/Module.h b/include/clang/Basic/Module.h index 6631721e35314..4aebda1887c45 100644 --- a/include/clang/Basic/Module.h +++ b/include/clang/Basic/Module.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::Module class, which describes a module in the +/// Defines the clang::Module class, which describes a module in the /// source code. // //===----------------------------------------------------------------------===// @@ -48,7 +48,7 @@ namespace clang { class LangOptions; class TargetInfo; -/// \brief Describes the name of a module. +/// Describes the name of a module. using ModuleId = SmallVector<std::pair<std::string, SourceLocation>, 2>; /// The signature of a module, which is a hash of the AST content. @@ -61,76 +61,76 @@ struct ASTFileSignature : std::array<uint32_t, 5> { } }; -/// \brief Describes a module or submodule. +/// Describes a module or submodule. class Module { public: - /// \brief The name of this module. + /// The name of this module. std::string Name; - /// \brief The location of the module definition. + /// The location of the module definition. SourceLocation DefinitionLoc; enum ModuleKind { - /// \brief This is a module that was defined by a module map and built out + /// This is a module that was defined by a module map and built out /// of header files. ModuleMapModule, - /// \brief This is a C++ Modules TS module interface unit. + /// This is a C++ Modules TS module interface unit. ModuleInterfaceUnit, - /// \brief This is a fragment of the global module within some C++ Modules + /// This is a fragment of the global module within some C++ Modules /// TS module. GlobalModuleFragment, }; - /// \brief The kind of this module. + /// The kind of this module. ModuleKind Kind = ModuleMapModule; - /// \brief The parent of this module. This will be NULL for the top-level + /// The parent of this module. This will be NULL for the top-level /// module. Module *Parent; - /// \brief The build directory of this module. This is the directory in + /// 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 = nullptr; - /// \brief The presumed file name for the module map defining this module. + /// The presumed file name for the module map defining this module. /// Only non-empty when building from preprocessed source. std::string PresumedModuleMapFile; - /// \brief The umbrella header or directory. + /// The umbrella header or directory. llvm::PointerUnion<const DirectoryEntry *, const FileEntry *> Umbrella; - /// \brief The module signature. + /// The module signature. ASTFileSignature Signature; - /// \brief The name of the umbrella entry, as written in the module map. + /// The name of the umbrella entry, as written in the module map. std::string UmbrellaAsWritten; - /// \brief The module through which entities defined in this module will + /// The module through which entities defined in this module will /// eventually be exposed, for use in "private" modules. std::string ExportAsModule; private: - /// \brief The submodules of this module, indexed by name. + /// The submodules of this module, indexed by name. std::vector<Module *> SubModules; - /// \brief A mapping from the submodule name to the index into the + /// A mapping from the submodule name to the index into the /// \c SubModules vector at which that submodule resides. llvm::StringMap<unsigned> SubModuleIndex; - /// \brief The AST file if this is a top-level module which has a + /// The AST file if this is a top-level module which has a /// corresponding serialized AST file, or null otherwise. const FileEntry *ASTFile = nullptr; - /// \brief The top-level headers associated with this module. + /// The top-level headers associated with this module. llvm::SmallSetVector<const FileEntry *, 2> TopHeaders; - /// \brief top-level header filenames that aren't resolved to FileEntries yet. + /// top-level header filenames that aren't resolved to FileEntries yet. std::vector<std::string> TopHeaderNames; - /// \brief Cache of modules visible to lookup in this module. + /// Cache of modules visible to lookup in this module. mutable llvm::DenseSet<const Module*> VisibleModulesCache; /// The ID used when referencing this module within a VisibleModuleSet. @@ -146,7 +146,7 @@ public: }; static const int NumHeaderKinds = HK_Excluded + 1; - /// \brief Information about a header directive as found in the module map + /// Information about a header directive as found in the module map /// file. struct Header { std::string NameAsWritten; @@ -155,7 +155,7 @@ public: explicit operator bool() { return Entry; } }; - /// \brief Information about a directory name as found in the module map + /// Information about a directory name as found in the module map /// file. struct DirectoryName { std::string NameAsWritten; @@ -164,10 +164,10 @@ public: explicit operator bool() { return Entry; } }; - /// \brief The headers that are part of this module. + /// 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 + /// Stored information about a header directive that was found in the /// module map file but has not been resolved to a file. struct UnresolvedHeaderDirective { HeaderKind Kind = HK_Normal; @@ -183,191 +183,202 @@ public: /// yet attempted to resolve to a file on the file system. SmallVector<UnresolvedHeaderDirective, 1> UnresolvedHeaders; - /// \brief Headers that are mentioned in the module map file but could not be + /// Headers that are mentioned in the module map file but could not be /// found on the file system. SmallVector<UnresolvedHeaderDirective, 1> MissingHeaders; - /// \brief An individual requirement: a feature name and a flag indicating + /// An individual requirement: a feature name and a flag indicating /// the required state of that feature. using Requirement = std::pair<std::string, bool>; - /// \brief The set of language features required to use this module. + /// The set of language features required to use this module. /// /// If any of these requirements are not available, the \c IsAvailable bit /// will be false to indicate that this (sub)module is not available. SmallVector<Requirement, 2> Requirements; - /// \brief Whether this module is missing a feature from \c Requirements. + /// A module with the same name that shadows this module. + Module *ShadowingModule = nullptr; + + /// Whether this module is missing a feature from \c Requirements. unsigned IsMissingRequirement : 1; - /// \brief Whether we tried and failed to load a module file for this module. + /// Whether we tried and failed to load a module file for this module. unsigned HasIncompatibleModuleFile : 1; - /// \brief Whether this module is available in the current translation unit. + /// Whether this module is available in the current translation unit. /// /// If the module is missing headers or does not meet all requirements then /// this bit will be 0. unsigned IsAvailable : 1; - /// \brief Whether this module was loaded from a module file. + /// Whether this module was loaded from a module file. unsigned IsFromModuleFile : 1; - /// \brief Whether this is a framework module. + /// Whether this is a framework module. unsigned IsFramework : 1; - /// \brief Whether this is an explicit submodule. + /// Whether this is an explicit submodule. unsigned IsExplicit : 1; - /// \brief Whether this is a "system" module (which assumes that all + /// Whether this is a "system" module (which assumes that all /// headers in it are system headers). unsigned IsSystem : 1; - /// \brief Whether this is an 'extern "C"' module (which implicitly puts all + /// Whether this is an 'extern "C"' module (which implicitly puts all /// headers in it within an 'extern "C"' block, and allows the module to be /// imported within such a block). unsigned IsExternC : 1; - /// \brief Whether this is an inferred submodule (module * { ... }). + /// Whether this is an inferred submodule (module * { ... }). unsigned IsInferred : 1; - /// \brief Whether we should infer submodules for this module based on + /// Whether we should infer submodules for this module based on /// the headers. /// /// Submodules can only be inferred for modules with an umbrella header. unsigned InferSubmodules : 1; - /// \brief Whether, when inferring submodules, the inferred submodules + /// Whether, when inferring submodules, the inferred submodules /// should be explicit. unsigned InferExplicitSubmodules : 1; - /// \brief Whether, when inferring submodules, the inferr submodules should + /// Whether, when inferring submodules, the inferr submodules should /// export all modules they import (e.g., the equivalent of "export *"). unsigned InferExportWildcard : 1; - /// \brief Whether the set of configuration macros is exhaustive. + /// Whether the set of configuration macros is exhaustive. /// /// When the set of configuration macros is exhaustive, meaning /// that no identifier not in this list should affect how the module is /// built. unsigned ConfigMacrosExhaustive : 1; - /// \brief Whether files in this module can only include non-modular headers + /// Whether files in this module can only include non-modular headers /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; - /// \brief Describes the visibility of the various names within a + /// Whether this module came from a "private" module map, found next + /// to a regular (public) module map. + unsigned ModuleMapIsPrivate : 1; + + /// Describes the visibility of the various names within a /// particular module. enum NameVisibilityKind { - /// \brief All of the names in this module are hidden. + /// All of the names in this module are hidden. Hidden, - /// \brief All of the names in this module are visible. + /// All of the names in this module are visible. AllVisible }; - /// \brief The visibility of names within this particular module. + /// The visibility of names within this particular module. NameVisibilityKind NameVisibility; - /// \brief The location of the inferred submodule. + /// The location of the inferred submodule. SourceLocation InferredSubmoduleLoc; - /// \brief The set of modules imported by this module, and on which this + /// The set of modules imported by this module, and on which this /// module depends. llvm::SmallSetVector<Module *, 2> Imports; - /// \brief Describes an exported module. + /// Describes an exported module. /// /// The pointer is the module being re-exported, while the bit will be true /// to indicate that this is a wildcard export. using ExportDecl = llvm::PointerIntPair<Module *, 1, bool>; - /// \brief The set of export declarations. + /// The set of export declarations. SmallVector<ExportDecl, 2> Exports; - /// \brief Describes an exported module that has not yet been resolved + /// Describes an exported module that has not yet been resolved /// (perhaps because the module it refers to has not yet been loaded). struct UnresolvedExportDecl { - /// \brief The location of the 'export' keyword in the module map file. + /// The location of the 'export' keyword in the module map file. SourceLocation ExportLoc; - /// \brief The name of the module. + /// The name of the module. ModuleId Id; - /// \brief Whether this export declaration ends in a wildcard, indicating + /// Whether this export declaration ends in a wildcard, indicating /// that all of its submodules should be exported (rather than the named /// module itself). bool Wildcard; }; - /// \brief The set of export declarations that have yet to be resolved. + /// The set of export declarations that have yet to be resolved. SmallVector<UnresolvedExportDecl, 2> UnresolvedExports; - /// \brief The directly used modules. + /// The directly used modules. SmallVector<Module *, 2> DirectUses; - /// \brief The set of use declarations that have yet to be resolved. + /// The set of use declarations that have yet to be resolved. SmallVector<ModuleId, 2> UnresolvedDirectUses; - /// \brief A library or framework to link against when an entity from this + /// A library or framework to link against when an entity from this /// module is used. struct LinkLibrary { LinkLibrary() = default; LinkLibrary(const std::string &Library, bool IsFramework) : Library(Library), IsFramework(IsFramework) {} - /// \brief The library to link against. + /// The library to link against. /// /// This will typically be a library or framework name, but can also /// be an absolute path to the library or framework. std::string Library; - /// \brief Whether this is a framework rather than a library. + /// Whether this is a framework rather than a library. bool IsFramework = false; }; - /// \brief The set of libraries or frameworks to link against when + /// The set of libraries or frameworks to link against when /// an entity from this module is used. llvm::SmallVector<LinkLibrary, 2> LinkLibraries; - /// \brief The set of "configuration macros", which are macros that + /// Autolinking uses the framework name for linking purposes + /// when this is false and the export_as name otherwise. + bool UseExportAsModuleLinkName = false; + + /// The set of "configuration macros", which are macros that /// (intentionally) change how this module is built. std::vector<std::string> ConfigMacros; - /// \brief An unresolved conflict with another module. + /// An unresolved conflict with another module. struct UnresolvedConflict { - /// \brief The (unresolved) module id. + /// The (unresolved) module id. ModuleId Id; - /// \brief The message provided to the user when there is a conflict. + /// The message provided to the user when there is a conflict. std::string Message; }; - /// \brief The list of conflicts for which the module-id has not yet been + /// The list of conflicts for which the module-id has not yet been /// resolved. std::vector<UnresolvedConflict> UnresolvedConflicts; - /// \brief A conflict between two modules. + /// A conflict between two modules. struct Conflict { - /// \brief The module that this module conflicts with. + /// The module that this module conflicts with. Module *Other; - /// \brief The message provided to the user when there is a conflict. + /// The message provided to the user when there is a conflict. std::string Message; }; - /// \brief The list of conflicts. + /// The list of conflicts. std::vector<Conflict> Conflicts; - /// \brief Construct a new module or submodule. + /// Construct a new module or submodule. Module(StringRef Name, SourceLocation DefinitionLoc, Module *Parent, bool IsFramework, bool IsExplicit, unsigned VisibilityID); ~Module(); - /// \brief Determine whether this module is available for use within the + /// Determine whether this module is available for use within the /// current translation unit. bool isAvailable() const { return IsAvailable; } - /// \brief Determine whether this module is available for use within the + /// Determine whether this module is available for use within the /// current translation unit. /// /// \param LangOpts The language options used for the current @@ -375,22 +386,29 @@ public: /// /// \param Target The target options used for the current translation unit. /// - /// \param Req If this module is unavailable, this parameter - /// will be set to one of the requirements that is not met for use of - /// this module. + /// \param Req If this module is unavailable because of a missing requirement, + /// this parameter will be set to one of the requirements that is not met for + /// use of this module. + /// + /// \param MissingHeader If this module is unavailable because of a missing + /// header, this parameter will be set to one of the missing headers. + /// + /// \param ShadowingModule If this module is unavailable because it is + /// shadowed, this parameter will be set to the shadowing module. bool isAvailable(const LangOptions &LangOpts, const TargetInfo &Target, Requirement &Req, - UnresolvedHeaderDirective &MissingHeader) const; + UnresolvedHeaderDirective &MissingHeader, + Module *&ShadowingModule) const; - /// \brief Determine whether this module is a submodule. + /// Determine whether this module is a submodule. bool isSubModule() const { return Parent != nullptr; } - /// \brief Determine whether this module is a submodule of the given other + /// Determine whether this module is a submodule of the given other /// module. bool isSubModuleOf(const Module *Other) const; - /// \brief Determine whether this module is a part of a framework, + /// Determine whether this module is a part of a framework, /// either because it is a framework module or because it is a submodule /// of a framework module. bool isPartOfFramework() const { @@ -401,7 +419,7 @@ public: return false; } - /// \brief Determine whether this module is a subframework of another + /// Determine whether this module is a subframework of another /// framework. bool isSubFramework() const { return IsFramework && Parent && Parent->isPartOfFramework(); @@ -416,51 +434,51 @@ public: Parent->SubModules.push_back(this); } - /// \brief Retrieve the full name of this module, including the path from + /// Retrieve the full name of this module, including the path from /// its top-level module. /// \param AllowStringLiterals If \c true, components that might not be /// lexically valid as identifiers will be emitted as string literals. std::string getFullModuleName(bool AllowStringLiterals = false) const; - /// \brief Whether the full name of this module is equal to joining + /// Whether the full name of this module is equal to joining /// \p nameParts with "."s. /// /// This is more efficient than getFullModuleName(). bool fullModuleNameIs(ArrayRef<StringRef> nameParts) const; - /// \brief Retrieve the top-level module for this (sub)module, which may + /// Retrieve the top-level module for this (sub)module, which may /// be this module. Module *getTopLevelModule() { return const_cast<Module *>( const_cast<const Module *>(this)->getTopLevelModule()); } - /// \brief Retrieve the top-level module for this (sub)module, which may + /// Retrieve the top-level module for this (sub)module, which may /// be this module. const Module *getTopLevelModule() const; - /// \brief Retrieve the name of the top-level module. + /// Retrieve the name of the top-level module. StringRef getTopLevelModuleName() const { return getTopLevelModule()->Name; } - /// \brief The serialized AST file for this module, if one was created. + /// The serialized AST file for this module, if one was created. const FileEntry *getASTFile() const { return getTopLevelModule()->ASTFile; } - /// \brief Set the serialized AST file for the top-level module of this module. + /// Set the serialized AST file for the top-level module of this module. void setASTFile(const FileEntry *File) { assert((File == nullptr || getASTFile() == nullptr || getASTFile() == File) && "file path changed"); getTopLevelModule()->ASTFile = File; } - /// \brief Retrieve the directory for which this module serves as the + /// Retrieve the directory for which this module serves as the /// umbrella. DirectoryName getUmbrellaDir() const; - /// \brief Retrieve the header that serves as the umbrella header for this + /// Retrieve the header that serves as the umbrella header for this /// module. Header getUmbrellaHeader() const { if (auto *E = Umbrella.dyn_cast<const FileEntry *>()) @@ -468,31 +486,31 @@ public: return Header{}; } - /// \brief Determine whether this module has an umbrella directory that is + /// Determine whether this module has an umbrella directory that is /// not based on an umbrella header. bool hasUmbrellaDir() const { return Umbrella && Umbrella.is<const DirectoryEntry *>(); } - /// \brief Add a top-level header associated with this module. + /// Add a top-level header associated with this module. void addTopHeader(const FileEntry *File) { assert(File); TopHeaders.insert(File); } - /// \brief Add a top-level header filename associated with this module. + /// Add a top-level header filename associated with this module. void addTopHeaderFilename(StringRef Filename) { TopHeaderNames.push_back(Filename); } - /// \brief The top-level headers associated with this module. + /// The top-level headers associated with this module. ArrayRef<const FileEntry *> getTopHeaders(FileManager &FileMgr); - /// \brief Determine whether this module has declared its intention to + /// Determine whether this module has declared its intention to /// directly use another module. bool directlyUses(const Module *Requested) const; - /// \brief Add the given feature requirement to the list of features + /// Add the given feature requirement to the list of features /// required by this module. /// /// \param Feature The feature that is required by this module (and @@ -510,15 +528,15 @@ public: const LangOptions &LangOpts, const TargetInfo &Target); - /// \brief Mark this module and all of its submodules as unavailable. + /// Mark this module and all of its submodules as unavailable. void markUnavailable(bool MissingRequirement = false); - /// \brief Find the submodule with the given name. + /// Find the submodule with the given name. /// /// \returns The submodule if found, or NULL otherwise. Module *findSubmodule(StringRef Name) const; - /// \brief Determine whether the specified module would be visible to + /// Determine whether the specified module would be visible to /// a lookup at the end of this module. /// /// FIXME: This may return incorrect results for (submodules of) the @@ -547,7 +565,7 @@ public: return llvm::make_range(submodule_begin(), submodule_end()); } - /// \brief Appends this module's list of exported modules to \p Exported. + /// Appends this module's list of exported modules to \p Exported. /// /// This provides a subset of immediately imported modules (the ones that are /// directly exported), not the complete set of exported modules. @@ -557,17 +575,17 @@ public: return "<module-includes>"; } - /// \brief Print the module map for this module to the given stream. + /// Print the module map for this module to the given stream. void print(raw_ostream &OS, unsigned Indent = 0) const; - /// \brief Dump the contents of this module to the given output stream. + /// Dump the contents of this module to the given output stream. void dump() const; private: void buildVisibleModulesCache() const; }; -/// \brief A set of visible modules. +/// A set of visible modules. class VisibleModuleSet { public: VisibleModuleSet() = default; @@ -587,34 +605,34 @@ public: return *this; } - /// \brief Get the current visibility generation. Incremented each time the + /// Get the current visibility generation. Incremented each time the /// set of visible modules changes in any way. unsigned getGeneration() const { return Generation; } - /// \brief Determine whether a module is visible. + /// Determine whether a module is visible. bool isVisible(const Module *M) const { return getImportLoc(M).isValid(); } - /// \brief Get the location at which the import of a module was triggered. + /// Get the location at which the import of a module was triggered. SourceLocation getImportLoc(const Module *M) const { return M->getVisibilityID() < ImportLocs.size() ? ImportLocs[M->getVisibilityID()] : SourceLocation(); } - /// \brief A callback to call when a module is made visible (directly or + /// A callback to call when a module is made visible (directly or /// indirectly) by a call to \ref setVisible. using VisibleCallback = llvm::function_ref<void(Module *M)>; - /// \brief A callback to call when a module conflict is found. \p Path + /// A callback to call when a module conflict is found. \p Path /// consists of a sequence of modules from the conflicting module to the one /// made visible, where each was exported by the next. using ConflictCallback = llvm::function_ref<void(ArrayRef<Module *> Path, Module *Conflict, StringRef Message)>; - /// \brief Make a specific module visible. + /// Make a specific module visible. void setVisible(Module *M, SourceLocation Loc, VisibleCallback Vis = [](Module *) {}, ConflictCallback Cb = [](ArrayRef<Module *>, Module *, diff --git a/include/clang/Basic/ObjCRuntime.h b/include/clang/Basic/ObjCRuntime.h index 8dc259c7ab66f..d5f4f50fe36f5 100644 --- a/include/clang/Basic/ObjCRuntime.h +++ b/include/clang/Basic/ObjCRuntime.h @@ -1,4 +1,4 @@ -//===--- ObjCRuntime.h - Objective-C Runtime Configuration ------*- C++ -*-===// +//===- ObjCRuntime.h - Objective-C Runtime Configuration --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,25 +6,28 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines types useful for describing an Objective-C runtime. -/// +/// Defines types useful for describing an Objective-C runtime. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_OBJCRUNTIME_H #define LLVM_CLANG_BASIC_OBJCRUNTIME_H -#include "clang/Basic/VersionTuple.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/VersionTuple.h" +#include <string> namespace clang { -/// \brief The basic abstraction for the target Objective-C runtime. +/// The basic abstraction for the target Objective-C runtime. class ObjCRuntime { public: - /// \brief The basic Objective-C runtimes that we know about. + /// The basic Objective-C runtimes that we know about. enum Kind { /// 'macosx' is the Apple-provided NeXT-derived runtime on Mac OS /// X platforms that use the non-fragile ABI; the version is a @@ -57,15 +60,14 @@ public: }; private: - Kind TheKind; + Kind TheKind = MacOSX; VersionTuple Version; public: /// A bogus initialization of the runtime. - ObjCRuntime() : TheKind(MacOSX) {} - + ObjCRuntime() = default; ObjCRuntime(Kind kind, const VersionTuple &version) - : TheKind(kind), Version(version) {} + : TheKind(kind), Version(version) {} void set(Kind kind, VersionTuple version) { TheKind = kind; @@ -75,7 +77,7 @@ public: Kind getKind() const { return TheKind; } const VersionTuple &getVersion() const { return Version; } - /// \brief Does this runtime follow the set of implied behaviors for a + /// Does this runtime follow the set of implied behaviors for a /// "non-fragile" ABI? bool isNonFragile() const { switch (getKind()) { @@ -113,7 +115,7 @@ public: return true; } - /// \brief Is this runtime basically of the GNU family of runtimes? + /// Is this runtime basically of the GNU family of runtimes? bool isGNUFamily() const { switch (getKind()) { case FragileMacOSX: @@ -129,14 +131,14 @@ public: llvm_unreachable("bad kind"); } - /// \brief Is this runtime basically of the NeXT family of runtimes? + /// Is this runtime basically of the NeXT family of runtimes? bool isNeXTFamily() const { // For now, this is just the inverse of isGNUFamily(), but that's // not inherently true. return !isGNUFamily(); } - /// \brief Does this runtime allow ARC at all? + /// Does this runtime allow ARC at all? bool allowsARC() const { switch (getKind()) { case FragileMacOSX: @@ -152,7 +154,7 @@ public: llvm_unreachable("bad kind"); } - /// \brief Does this runtime natively provide the ARC entrypoints? + /// Does this runtime natively provide the ARC entrypoints? /// /// ARC cannot be directly supported on a platform that does not provide /// these entrypoints, although it may be supportable via a stub @@ -171,7 +173,7 @@ public: llvm_unreachable("bad kind"); } - /// \brief Does this runtime supports optimized setter entrypoints? + /// Does this runtime supports optimized setter entrypoints? bool hasOptimizedSetter() const { switch (getKind()) { case MacOSX: @@ -182,9 +184,8 @@ public: return true; case GNUstep: return getVersion() >= VersionTuple(1, 7); - default: - return false; + return false; } } @@ -193,7 +194,7 @@ public: return hasNativeWeak(); } - /// \brief Does this runtime natively provide ARC-compliant 'weak' + /// Does this runtime natively provide ARC-compliant 'weak' /// entrypoints? bool hasNativeWeak() const { // Right now, this is always equivalent to whether the runtime @@ -201,14 +202,14 @@ public: return hasNativeARC(); } - /// \brief Does this runtime directly support the subscripting methods? + /// Does this runtime directly support the subscripting methods? /// /// This is really a property of the library, not the runtime. bool hasSubscripting() const { switch (getKind()) { case FragileMacOSX: return false; - case MacOSX: return getVersion() >= VersionTuple(10, 8); - case iOS: return getVersion() >= VersionTuple(6); + case MacOSX: return getVersion() >= VersionTuple(10, 11); + case iOS: return getVersion() >= VersionTuple(9); case WatchOS: return true; // This is really a lie, because some implementations and versions @@ -221,12 +222,12 @@ public: llvm_unreachable("bad kind"); } - /// \brief Does this runtime allow sizeof or alignof on object types? + /// Does this runtime allow sizeof or alignof on object types? bool allowsSizeofAlignof() const { return isFragile(); } - /// \brief Does this runtime allow pointer arithmetic on objects? + /// Does this runtime allow pointer arithmetic on objects? /// /// This covers +, -, ++, --, and (if isSubscriptPointerArithmetic() /// yields true) []. @@ -245,12 +246,12 @@ public: llvm_unreachable("bad kind"); } - /// \brief Is subscripting pointer arithmetic? + /// Is subscripting pointer arithmetic? bool isSubscriptPointerArithmetic() const { return allowsPointerArithmetic(); } - /// \brief Does this runtime provide an objc_terminate function? + /// Does this runtime provide an objc_terminate function? /// /// This is used in handlers for exceptions during the unwind process; /// without it, abort() must be used in pure ObjC files. @@ -267,7 +268,7 @@ public: llvm_unreachable("bad kind"); } - /// \brief Does this runtime support weakly importing classes? + /// Does this runtime support weakly importing classes? bool hasWeakClassImport() const { switch (getKind()) { case MacOSX: return true; @@ -281,7 +282,7 @@ public: llvm_unreachable("bad kind"); } - /// \brief Does this runtime use zero-cost exceptions? + /// Does this runtime use zero-cost exceptions? bool hasUnwindExceptions() const { switch (getKind()) { case MacOSX: return true; @@ -320,7 +321,6 @@ public: return getVersion() >= VersionTuple(2); case GNUstep: return false; - default: return false; } @@ -340,7 +340,7 @@ public: } } - /// \brief Try to parse an Objective-C runtime specification from the given + /// Try to parse an Objective-C runtime specification from the given /// string. /// /// \return true on error. @@ -360,6 +360,6 @@ public: raw_ostream &operator<<(raw_ostream &out, const ObjCRuntime &value); -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_OBJCRUNTIME_H diff --git a/include/clang/Basic/OpenCLExtensions.def b/include/clang/Basic/OpenCLExtensions.def index c3319d2d808b9..13cb12e7c5811 100644 --- a/include/clang/Basic/OpenCLExtensions.def +++ b/include/clang/Basic/OpenCLExtensions.def @@ -53,6 +53,9 @@ OPENCLEXT_INTERNAL(cl_khr_icd, 100, ~0U) OPENCLEXT_INTERNAL(cl_khr_gl_event, 110, ~0U) OPENCLEXT_INTERNAL(cl_khr_d3d10_sharing, 110, ~0U) +// EMBEDDED_PROFILE +OPENCLEXT_INTERNAL(cles_khr_int64, 110, ~0U) + // OpenCL 1.2. OPENCLEXT_INTERNAL(cl_khr_context_abort, 120, ~0U) OPENCLEXT_INTERNAL(cl_khr_d3d11_sharing, 120, ~0U) diff --git a/include/clang/Basic/OpenCLOptions.h b/include/clang/Basic/OpenCLOptions.h index cc850f0b0b24a..cc4e9922dca03 100644 --- a/include/clang/Basic/OpenCLOptions.h +++ b/include/clang/Basic/OpenCLOptions.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::OpenCLOptions class. +/// Defines the clang::OpenCLOptions class. /// //===----------------------------------------------------------------------===// @@ -19,7 +19,7 @@ namespace clang { -/// \brief OpenCL supported extensions and optional core features +/// OpenCL supported extensions and optional core features class OpenCLOptions { struct Info { bool Supported; // Is this option supported @@ -67,7 +67,7 @@ public: OptMap[Ext].Enabled = V; } - /// \brief Enable or disable support for OpenCL extensions + /// Enable or disable support for OpenCL extensions /// \param Ext name of the extension optionally prefixed with /// '+' or '-' /// \param V used when \p Ext is not prefixed by '+' or '-' diff --git a/include/clang/Basic/OpenMPKinds.def b/include/clang/Basic/OpenMPKinds.def index 6a0bed7ab15fc..4ed7053b679b2 100644 --- a/include/clang/Basic/OpenMPKinds.def +++ b/include/clang/Basic/OpenMPKinds.def @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// /// \file -/// \brief This file defines the list of supported OpenMP directives and +/// This file defines the list of supported OpenMP directives and /// clauses. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Basic/OpenMPKinds.h b/include/clang/Basic/OpenMPKinds.h index e00333153f9b0..c47973e53a8a7 100644 --- a/include/clang/Basic/OpenMPKinds.h +++ b/include/clang/Basic/OpenMPKinds.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines some OpenMP-specific enums and functions. +/// Defines some OpenMP-specific enums and functions. /// //===----------------------------------------------------------------------===// @@ -19,7 +19,7 @@ namespace clang { -/// \brief OpenMP directives. +/// OpenMP directives. enum OpenMPDirectiveKind { #define OPENMP_DIRECTIVE(Name) \ OMPD_##Name, @@ -29,7 +29,7 @@ enum OpenMPDirectiveKind { OMPD_unknown }; -/// \brief OpenMP clauses. +/// OpenMP clauses. enum OpenMPClauseKind { #define OPENMP_CLAUSE(Name, Class) \ OMPC_##Name, @@ -39,7 +39,7 @@ enum OpenMPClauseKind { OMPC_unknown }; -/// \brief OpenMP attributes for 'default' clause. +/// OpenMP attributes for 'default' clause. enum OpenMPDefaultClauseKind { #define OPENMP_DEFAULT_KIND(Name) \ OMPC_DEFAULT_##Name, @@ -47,7 +47,7 @@ enum OpenMPDefaultClauseKind { OMPC_DEFAULT_unknown }; -/// \brief OpenMP attributes for 'proc_bind' clause. +/// OpenMP attributes for 'proc_bind' clause. enum OpenMPProcBindClauseKind { #define OPENMP_PROC_BIND_KIND(Name) \ OMPC_PROC_BIND_##Name, @@ -55,7 +55,7 @@ enum OpenMPProcBindClauseKind { OMPC_PROC_BIND_unknown }; -/// \brief OpenMP attributes for 'schedule' clause. +/// OpenMP attributes for 'schedule' clause. enum OpenMPScheduleClauseKind { #define OPENMP_SCHEDULE_KIND(Name) \ OMPC_SCHEDULE_##Name, @@ -63,7 +63,7 @@ enum OpenMPScheduleClauseKind { OMPC_SCHEDULE_unknown }; -/// \brief OpenMP modifiers for 'schedule' clause. +/// OpenMP modifiers for 'schedule' clause. enum OpenMPScheduleClauseModifier { OMPC_SCHEDULE_MODIFIER_unknown = OMPC_SCHEDULE_unknown, #define OPENMP_SCHEDULE_MODIFIER(Name) \ @@ -72,7 +72,7 @@ enum OpenMPScheduleClauseModifier { OMPC_SCHEDULE_MODIFIER_last }; -/// \brief OpenMP attributes for 'depend' clause. +/// OpenMP attributes for 'depend' clause. enum OpenMPDependClauseKind { #define OPENMP_DEPEND_KIND(Name) \ OMPC_DEPEND_##Name, @@ -80,7 +80,7 @@ enum OpenMPDependClauseKind { OMPC_DEPEND_unknown }; -/// \brief OpenMP attributes for 'linear' clause. +/// OpenMP attributes for 'linear' clause. enum OpenMPLinearClauseKind { #define OPENMP_LINEAR_KIND(Name) \ OMPC_LINEAR_##Name, @@ -88,7 +88,7 @@ enum OpenMPLinearClauseKind { OMPC_LINEAR_unknown }; -/// \brief OpenMP mapping kind for 'map' clause. +/// OpenMP mapping kind for 'map' clause. enum OpenMPMapClauseKind { #define OPENMP_MAP_KIND(Name) \ OMPC_MAP_##Name, @@ -96,14 +96,14 @@ enum OpenMPMapClauseKind { OMPC_MAP_unknown }; -/// \brief OpenMP attributes for 'dist_schedule' clause. +/// OpenMP attributes for 'dist_schedule' clause. enum OpenMPDistScheduleClauseKind { #define OPENMP_DIST_SCHEDULE_KIND(Name) OMPC_DIST_SCHEDULE_##Name, #include "clang/Basic/OpenMPKinds.def" OMPC_DIST_SCHEDULE_unknown }; -/// \brief OpenMP attributes for 'defaultmap' clause. +/// OpenMP attributes for 'defaultmap' clause. enum OpenMPDefaultmapClauseKind { #define OPENMP_DEFAULTMAP_KIND(Name) \ OMPC_DEFAULTMAP_##Name, @@ -111,7 +111,7 @@ enum OpenMPDefaultmapClauseKind { OMPC_DEFAULTMAP_unknown }; -/// \brief OpenMP modifiers for 'defaultmap' clause. +/// OpenMP modifiers for 'defaultmap' clause. enum OpenMPDefaultmapClauseModifier { OMPC_DEFAULTMAP_MODIFIER_unknown = OMPC_DEFAULTMAP_unknown, #define OPENMP_DEFAULTMAP_MODIFIER(Name) \ @@ -139,39 +139,39 @@ const char *getOpenMPSimpleClauseTypeName(OpenMPClauseKind Kind, unsigned Type); bool isAllowedClauseForDirective(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind); -/// \brief Checks if the specified directive is a directive with an associated +/// Checks if the specified directive is a directive with an associated /// loop construct. /// \param DKind Specified directive. /// \return true - the directive is a loop-associated directive like 'omp simd' /// or 'omp for' directive, otherwise - false. bool isOpenMPLoopDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a worksharing directive. +/// Checks if the specified directive is a worksharing directive. /// \param DKind Specified directive. /// \return true - the directive is a worksharing directive like 'omp for', /// otherwise - false. bool isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a taskloop directive. +/// Checks if the specified directive is a taskloop directive. /// \param DKind Specified directive. /// \return true - the directive is a worksharing directive like 'omp taskloop', /// otherwise - false. bool isOpenMPTaskLoopDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a parallel-kind directive. +/// Checks if the specified directive is a parallel-kind directive. /// \param DKind Specified directive. /// \return true - the directive is a parallel-like directive like 'omp /// parallel', otherwise - false. bool isOpenMPParallelDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a target code offload directive. +/// Checks if the specified directive is a target code offload directive. /// \param DKind Specified directive. /// \return true - the directive is a target code offload directive like /// 'omp target', 'omp target parallel', 'omp target xxx' /// otherwise - false. bool isOpenMPTargetExecutionDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a target data offload directive. +/// Checks if the specified directive is a target data offload directive. /// \param DKind Specified directive. /// \return true - the directive is a target data offload directive like /// 'omp target data', 'omp target update', 'omp target enter data', @@ -193,13 +193,13 @@ bool isOpenMPNestingTeamsDirective(OpenMPDirectiveKind DKind); /// \return true - the directive is a teams-like directive, otherwise - false. bool isOpenMPTeamsDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a simd directive. +/// Checks if the specified directive is a simd directive. /// \param DKind Specified directive. /// \return true - the directive is a simd directive like 'omp simd', /// otherwise - false. bool isOpenMPSimdDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified directive is a distribute directive. +/// Checks if the specified directive is a distribute directive. /// \param DKind Specified directive. /// \return true - the directive is a distribute-directive like 'omp /// distribute', @@ -214,13 +214,13 @@ bool isOpenMPDistributeDirective(OpenMPDirectiveKind DKind); /// otherwise - false. bool isOpenMPNestingDistributeDirective(OpenMPDirectiveKind DKind); -/// \brief Checks if the specified clause is one of private clauses like +/// Checks if the specified clause is one of private clauses like /// 'private', 'firstprivate', 'reduction' etc.. /// \param Kind Clause kind. /// \return true - the clause is a private clause, otherwise - false. bool isOpenMPPrivate(OpenMPClauseKind Kind); -/// \brief Checks if the specified clause is one of threadprivate clauses like +/// Checks if the specified clause is one of threadprivate clauses like /// 'threadprivate', 'copyin' or 'copyprivate'. /// \param Kind Clause kind. /// \return true - the clause is a threadprivate clause, otherwise - false. diff --git a/include/clang/Basic/OperatorKinds.h b/include/clang/Basic/OperatorKinds.h index 7120baeef675a..b0064cfb4e5a7 100644 --- a/include/clang/Basic/OperatorKinds.h +++ b/include/clang/Basic/OperatorKinds.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines an enumeration for C++ overloaded operators. +/// Defines an enumeration for C++ overloaded operators. /// //===----------------------------------------------------------------------===// @@ -17,7 +17,7 @@ namespace clang { -/// \brief Enumeration specifying the different kinds of C++ overloaded +/// Enumeration specifying the different kinds of C++ overloaded /// operators. enum OverloadedOperatorKind : int { OO_None, ///< Not an overloaded operator @@ -27,7 +27,7 @@ enum OverloadedOperatorKind : int { NUM_OVERLOADED_OPERATORS }; -/// \brief Retrieve the spelling of the given overloaded operator, without +/// Retrieve the spelling of the given overloaded operator, without /// the preceding "operator" keyword. const char *getOperatorSpelling(OverloadedOperatorKind Operator); diff --git a/include/clang/Basic/OperatorPrecedence.h b/include/clang/Basic/OperatorPrecedence.h index 94978f81e543a..4389e3bbd2576 100644 --- a/include/clang/Basic/OperatorPrecedence.h +++ b/include/clang/Basic/OperatorPrecedence.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines and computes precedence levels for binary/ternary operators. +/// Defines and computes precedence levels for binary/ternary operators. /// //===----------------------------------------------------------------------===// @@ -44,7 +44,7 @@ namespace prec { }; } -/// \brief Return the precedence of the specified binary operator token. +/// Return the precedence of the specified binary operator token. prec::Level getBinOpPrecedence(tok::TokenKind Kind, bool GreaterThanIsOperator, bool CPlusPlus11); diff --git a/include/clang/Basic/PartialDiagnostic.h b/include/clang/Basic/PartialDiagnostic.h index b2f14afe5695a..9727af86f6494 100644 --- a/include/clang/Basic/PartialDiagnostic.h +++ b/include/clang/Basic/PartialDiagnostic.h @@ -1,4 +1,4 @@ -//===--- PartialDiagnostic.h - Diagnostic "closures" ------------*- C++ -*-===// +//===- PartialDiagnostic.h - Diagnostic "closures" --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,25 +6,32 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Implements a partial diagnostic that can be emitted anwyhere +/// Implements a partial diagnostic that can be emitted anwyhere /// in a DiagnosticBuilder stream. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H #define LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "llvm/ADT/STLExtras.h" -#include "llvm/Support/Compiler.h" -#include "llvm/Support/DataTypes.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include <cassert> +#include <cstdint> +#include <string> +#include <type_traits> +#include <utility> namespace clang { +class DeclContext; +class IdentifierInfo; + class PartialDiagnostic { public: enum { @@ -36,10 +43,8 @@ public: }; struct Storage { - Storage() : NumDiagArgs(0) { } - enum { - /// \brief The maximum number of arguments we can hold. We + /// The maximum number of arguments we can hold. We /// currently only support up to 10 arguments (%0-%9). /// /// A single diagnostic with more than that almost certainly has to @@ -47,33 +52,35 @@ public: MaxArguments = PartialDiagnostic::MaxArguments }; - /// \brief The number of entries in Arguments. - unsigned char NumDiagArgs; + /// The number of entries in Arguments. + unsigned char NumDiagArgs = 0; - /// \brief Specifies for each argument whether it is in DiagArgumentsStr + /// Specifies for each argument whether it is in DiagArgumentsStr /// or in DiagArguments. unsigned char DiagArgumentsKind[MaxArguments]; - /// \brief The values for the various substitution positions. + /// The values for the various substitution positions. /// /// This is used when the argument is not an std::string. The specific value /// is mangled into an intptr_t and the interpretation depends on exactly /// what sort of argument kind it is. intptr_t DiagArgumentsVal[MaxArguments]; - /// \brief The values for the various substitution positions that have + /// The values for the various substitution positions that have /// string arguments. std::string DiagArgumentsStr[MaxArguments]; - /// \brief The list of ranges added to this diagnostic. + /// The list of ranges added to this diagnostic. SmallVector<CharSourceRange, 8> DiagRanges; - /// \brief If valid, provides a hint with some code to insert, remove, or + /// If valid, provides a hint with some code to insert, remove, or /// modify at a particular position. SmallVector<FixItHint, 6> FixItHints; + + Storage() = default; }; - /// \brief An allocator for Storage objects, which uses a small cache to + /// An allocator for Storage objects, which uses a small cache to /// objects, used to reduce malloc()/free() traffic for partial diagnostics. class StorageAllocator { static const unsigned NumCached = 16; @@ -85,7 +92,7 @@ public: StorageAllocator(); ~StorageAllocator(); - /// \brief Allocate new storage. + /// Allocate new storage. Storage *Allocate() { if (NumFreeListEntries == 0) return new Storage; @@ -97,7 +104,7 @@ public: return Result; } - /// \brief Free the given storage object. + /// Free the given storage object. void Deallocate(Storage *S) { if (S >= Cached && S <= Cached + NumCached) { FreeList[NumFreeListEntries++] = S; @@ -113,16 +120,16 @@ private: // in the sense that its bits can be safely memcpy'ed and destructed // in the new location. - /// \brief The diagnostic ID. - mutable unsigned DiagID; + /// The diagnostic ID. + mutable unsigned DiagID = 0; - /// \brief Storage for args and ranges. - mutable Storage *DiagStorage; + /// Storage for args and ranges. + mutable Storage *DiagStorage = nullptr; - /// \brief Allocator used to allocate storage for this diagnostic. - StorageAllocator *Allocator; + /// Allocator used to allocate storage for this diagnostic. + StorageAllocator *Allocator = nullptr; - /// \brief Retrieve storage for this particular diagnostic. + /// Retrieve storage for this particular diagnostic. Storage *getStorage() const { if (DiagStorage) return DiagStorage; @@ -176,17 +183,16 @@ private: public: struct NullDiagnostic {}; - /// \brief Create a null partial diagnostic, which cannot carry a payload, + + /// Create a null partial diagnostic, which cannot carry a payload, /// and only exists to be swapped with a real partial diagnostic. - PartialDiagnostic(NullDiagnostic) - : DiagID(0), DiagStorage(nullptr), Allocator(nullptr) { } + PartialDiagnostic(NullDiagnostic) {} PartialDiagnostic(unsigned DiagID, StorageAllocator &Allocator) - : DiagID(DiagID), DiagStorage(nullptr), Allocator(&Allocator) { } + : DiagID(DiagID), Allocator(&Allocator) {} PartialDiagnostic(const PartialDiagnostic &Other) - : DiagID(Other.DiagID), DiagStorage(nullptr), Allocator(Other.Allocator) - { + : DiagID(Other.DiagID), Allocator(Other.Allocator) { if (Other.DiagStorage) { DiagStorage = getStorage(); *DiagStorage = *Other.DiagStorage; @@ -194,22 +200,20 @@ public: } PartialDiagnostic(PartialDiagnostic &&Other) - : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage), - Allocator(Other.Allocator) { + : DiagID(Other.DiagID), DiagStorage(Other.DiagStorage), + Allocator(Other.Allocator) { Other.DiagStorage = nullptr; } PartialDiagnostic(const PartialDiagnostic &Other, Storage *DiagStorage) - : DiagID(Other.DiagID), DiagStorage(DiagStorage), - Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) - { + : DiagID(Other.DiagID), DiagStorage(DiagStorage), + Allocator(reinterpret_cast<StorageAllocator *>(~uintptr_t(0))) { if (Other.DiagStorage) *this->DiagStorage = *Other.DiagStorage; } PartialDiagnostic(const Diagnostic &Other, StorageAllocator &Allocator) - : DiagID(Other.getID()), DiagStorage(nullptr), Allocator(&Allocator) - { + : DiagID(Other.getID()), Allocator(&Allocator) { // Copy arguments. for (unsigned I = 0, N = Other.getNumArgs(); I != N; ++I) { if (Other.getArgKind(I) == DiagnosticsEngine::ak_std_string) @@ -320,7 +324,7 @@ public: Diags.Clear(); } - /// \brief Clear out this partial diagnostic, giving it a new diagnostic ID + /// Clear out this partial diagnostic, giving it a new diagnostic ID /// and removing all of its arguments, ranges, and fix-it hints. void Reset(unsigned DiagID = 0) { this->DiagID = DiagID; @@ -402,7 +406,6 @@ public: PD.AddFixItHint(Hint); return PD; } - }; inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, @@ -411,9 +414,10 @@ inline const DiagnosticBuilder &operator<<(const DiagnosticBuilder &DB, return DB; } -/// \brief A partial diagnostic along with the source location where this +/// A partial diagnostic along with the source location where this /// diagnostic occurs. -typedef std::pair<SourceLocation, PartialDiagnostic> PartialDiagnosticAt; +using PartialDiagnosticAt = std::pair<SourceLocation, PartialDiagnostic>; + +} // namespace clang -} // end namespace clang -#endif +#endif // LLVM_CLANG_BASIC_PARTIALDIAGNOSTIC_H diff --git a/include/clang/Basic/PlistSupport.h b/include/clang/Basic/PlistSupport.h index 61de82450cf78..be92bbfde1853 100644 --- a/include/clang/Basic/PlistSupport.h +++ b/include/clang/Basic/PlistSupport.h @@ -1,4 +1,4 @@ -//===---------- PlistSupport.h - Plist Output Utilities ---------*- C++ -*-===// +//===- PlistSupport.h - Plist Output Utilities ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,12 +10,20 @@ #ifndef LLVM_CLANG_BASIC_PLISTSUPPORT_H #define LLVM_CLANG_BASIC_PLISTSUPPORT_H +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/raw_ostream.h" +#include <cassert> +#include <cstdint> namespace clang { namespace markup { -typedef llvm::DenseMap<FileID, unsigned> FIDMap; + +using FIDMap = llvm::DenseMap<FileID, unsigned>; inline void AddFID(FIDMap &FIDs, SmallVectorImpl<FileID> &V, const SourceManager &SM, SourceLocation L) { @@ -112,7 +120,8 @@ inline void EmitRange(raw_ostream &o, const SourceManager &SM, EmitLocation(o, SM, R.getEnd(), FM, indent + 1); Indent(o, indent) << "</array>\n"; } -} -} -#endif +} // namespace markup +} // namespace clang + +#endif // LLVM_CLANG_BASIC_PLISTSUPPORT_H diff --git a/include/clang/Basic/PrettyStackTrace.h b/include/clang/Basic/PrettyStackTrace.h index 6badae5c03496..e652f52055d6a 100644 --- a/include/clang/Basic/PrettyStackTrace.h +++ b/include/clang/Basic/PrettyStackTrace.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the PrettyStackTraceEntry class, which is used to make +/// Defines the PrettyStackTraceEntry class, which is used to make /// crashes give more contextual information about what the program was doing /// when it crashed. /// diff --git a/include/clang/Basic/Sanitizers.def b/include/clang/Basic/Sanitizers.def index 30d5cc8166dc6..5a36822a63035 100644 --- a/include/clang/Basic/Sanitizers.def +++ b/include/clang/Basic/Sanitizers.def @@ -44,8 +44,12 @@ SANITIZER("address", Address) // Kernel AddressSanitizer (KASan) SANITIZER("kernel-address", KernelAddress) +// Hardware-assisted AddressSanitizer SANITIZER("hwaddress", HWAddress) +// Kernel Hardware-assisted AddressSanitizer (KHWASan) +SANITIZER("kernel-hwaddress", KernelHWAddress) + // MemorySanitizer SANITIZER("memory", Memory) @@ -100,16 +104,20 @@ SANITIZER("dataflow", DataFlow) SANITIZER("cfi-cast-strict", CFICastStrict) SANITIZER("cfi-derived-cast", CFIDerivedCast) SANITIZER("cfi-icall", CFIICall) +SANITIZER("cfi-mfcall", CFIMFCall) SANITIZER("cfi-unrelated-cast", CFIUnrelatedCast) SANITIZER("cfi-nvcall", CFINVCall) SANITIZER("cfi-vcall", CFIVCall) SANITIZER_GROUP("cfi", CFI, - CFIDerivedCast | CFIICall | CFIUnrelatedCast | CFINVCall | - CFIVCall) + CFIDerivedCast | CFIICall | CFIMFCall | CFIUnrelatedCast | + CFINVCall | CFIVCall) // Safe Stack SANITIZER("safe-stack", SafeStack) +// Shadow Call Stack +SANITIZER("shadow-call-stack", ShadowCallStack) + // -fsanitize=undefined includes all the sanitizers which have low overhead, no // ABI or address space layout implications, and only catch undefined behavior. SANITIZER_GROUP("undefined", Undefined, diff --git a/include/clang/Basic/Sanitizers.h b/include/clang/Basic/Sanitizers.h index 1b936c7d115cf..469d9e2e95917 100644 --- a/include/clang/Basic/Sanitizers.h +++ b/include/clang/Basic/Sanitizers.h @@ -1,4 +1,4 @@ -//===--- Sanitizers.h - C Language Family Language Options ------*- C++ -*-===// +//===- Sanitizers.h - C Language Family Language Options --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,10 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the clang::SanitizerKind enum. -/// +/// Defines the clang::SanitizerKind enum. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SANITIZERS_H @@ -18,10 +18,12 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstdint> namespace clang { -typedef uint64_t SanitizerMask; +using SanitizerMask = uint64_t; namespace SanitizerKind { @@ -43,19 +45,19 @@ enum SanitizerOrdinal : uint64_t { const SanitizerMask ID##Group = 1ULL << SO_##ID##Group; #include "clang/Basic/Sanitizers.def" -} +} // namespace SanitizerKind struct SanitizerSet { - /// \brief Check if a certain (single) sanitizer is enabled. + /// Check if a certain (single) sanitizer is enabled. bool has(SanitizerMask K) const { assert(llvm::isPowerOf2_64(K)); return Mask & K; } - /// \brief Check if one or more sanitizers are enabled. + /// Check if one or more sanitizers are enabled. bool hasOneOf(SanitizerMask K) const { return Mask & K; } - /// \brief Enable or disable a certain (single) sanitizer. + /// Enable or disable a certain (single) sanitizer. void set(SanitizerMask K, bool Value) { assert(llvm::isPowerOf2_64(K)); Mask = Value ? (Mask | K) : (Mask & ~K); @@ -64,10 +66,10 @@ struct SanitizerSet { /// Disable the sanitizers specified in \p K. void clear(SanitizerMask K = SanitizerKind::All) { Mask &= ~K; } - /// \brief Returns true if at least one sanitizer is enabled. + /// Returns true if at least one sanitizer is enabled. bool empty() const { return Mask == 0; } - /// \brief Bitmask of enabled sanitizers. + /// Bitmask of enabled sanitizers. SanitizerMask Mask = 0; }; @@ -85,6 +87,6 @@ inline SanitizerMask getPPTransparentSanitizers() { SanitizerKind::Nullability | SanitizerKind::Undefined; } -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_BASIC_SANITIZERS_H diff --git a/include/clang/Basic/SourceLocation.h b/include/clang/Basic/SourceLocation.h index 7418b50f9d83b..f174f83abf4a0 100644 --- a/include/clang/Basic/SourceLocation.h +++ b/include/clang/Basic/SourceLocation.h @@ -1,4 +1,4 @@ -//===--- SourceLocation.h - Compact identifier for Source Files -*- C++ -*-===// +//===- SourceLocation.h - Compact identifier for Source Files ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,38 +6,39 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the clang::SourceLocation class and associated facilities. -/// +/// Defines the clang::SourceLocation class and associated facilities. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_SOURCELOCATION_H #define LLVM_CLANG_BASIC_SOURCELOCATION_H #include "clang/Basic/LLVM.h" -#include "llvm/Support/Compiler.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/PointerLikeTypeTraits.h" #include <cassert> -#include <functional> +#include <cstdint> #include <string> #include <utility> namespace llvm { - class MemoryBuffer; - template <typename T> struct DenseMapInfo; - template <typename T> struct isPodLike; -} + +template <typename T> struct DenseMapInfo; +template <typename T> struct isPodLike; + +} // namespace llvm namespace clang { class SourceManager; -/// \brief An opaque identifier used by SourceManager which refers to a +/// An opaque identifier used by SourceManager which refers to a /// source file (MemoryBuffer) along with its \#include path and \#line data. /// class FileID { - /// \brief A mostly-opaque identifier, where 0 is "invalid", >0 is + /// A mostly-opaque identifier, where 0 is "invalid", >0 is /// this module, and <-1 is something loaded from another module. int ID = 0; @@ -56,20 +57,20 @@ public: unsigned getHashValue() const { return static_cast<unsigned>(ID); } private: - friend class SourceManager; friend class ASTWriter; friend class ASTReader; + friend class SourceManager; static FileID get(int V) { FileID F; F.ID = V; return F; } + int getOpaqueValue() const { return ID; } }; - -/// \brief Encodes a location in the source. The SourceManager can decode this +/// Encodes a location in the source. The SourceManager can decode this /// to get at the full include stack, line and column information. /// /// Technically, a source location is simply an offset into the manager's view @@ -85,10 +86,12 @@ private: /// /// It is important that this type remains small. It is currently 32 bits wide. class SourceLocation { - unsigned ID = 0; - friend class SourceManager; friend class ASTReader; friend class ASTWriter; + friend class SourceManager; + + unsigned ID = 0; + enum : unsigned { MacroIDBit = 1U << 31 }; @@ -97,7 +100,7 @@ public: bool isFileID() const { return (ID & MacroIDBit) == 0; } bool isMacroID() const { return (ID & MacroIDBit) != 0; } - /// \brief Return true if this is a valid SourceLocation object. + /// Return true if this is a valid SourceLocation object. /// /// Invalid SourceLocations are often used when events have no corresponding /// location in the source (e.g. a diagnostic is required for a command line @@ -106,7 +109,7 @@ public: bool isInvalid() const { return ID == 0; } private: - /// \brief Return the offset into the manager's global input view. + /// Return the offset into the manager's global input view. unsigned getOffset() const { return ID & ~MacroIDBit; } @@ -124,9 +127,9 @@ private: L.ID = MacroIDBit | ID; return L; } -public: - /// \brief Return a source location with the specified offset from this +public: + /// Return a source location with the specified offset from this /// SourceLocation. SourceLocation getLocWithOffset(int Offset) const { assert(((getOffset()+Offset) & MacroIDBit) == 0 && "offset overflow"); @@ -135,14 +138,14 @@ public: return L; } - /// \brief When a SourceLocation itself cannot be used, this returns + /// When a SourceLocation itself cannot be used, this returns /// an (opaque) 32-bit integer encoding for it. /// /// This should only be passed to SourceLocation::getFromRawEncoding, it /// should not be inspected directly. unsigned getRawEncoding() const { return ID; } - /// \brief Turn a raw encoding of a SourceLocation object into + /// Turn a raw encoding of a SourceLocation object into /// a real SourceLocation. /// /// \see getRawEncoding. @@ -152,7 +155,7 @@ public: return X; } - /// \brief When a SourceLocation itself cannot be used, this returns + /// When a SourceLocation itself cannot be used, this returns /// an (opaque) pointer encoding for it. /// /// This should only be passed to SourceLocation::getFromPtrEncoding, it @@ -163,7 +166,7 @@ public: return (void*)(uintptr_t)getRawEncoding(); } - /// \brief Turn a pointer encoding of a SourceLocation object back + /// Turn a pointer encoding of a SourceLocation object back /// into a real SourceLocation. static SourceLocation getFromPtrEncoding(const void *Encoding) { return getFromRawEncoding((unsigned)(uintptr_t)Encoding); @@ -191,7 +194,7 @@ inline bool operator<(const SourceLocation &LHS, const SourceLocation &RHS) { return LHS.getRawEncoding() < RHS.getRawEncoding(); } -/// \brief A trivial tuple used to represent a source range. +/// A trivial tuple used to represent a source range. class SourceRange { SourceLocation B; SourceLocation E; @@ -219,7 +222,7 @@ public: } }; -/// \brief Represents a character-granular source range. +/// Represents a character-granular source range. /// /// The underlying SourceRange can either specify the starting/ending character /// of the range, or it can specify the start of the range and the start of the @@ -245,11 +248,12 @@ public: static CharSourceRange getTokenRange(SourceLocation B, SourceLocation E) { return getTokenRange(SourceRange(B, E)); } + static CharSourceRange getCharRange(SourceLocation B, SourceLocation E) { return getCharRange(SourceRange(B, E)); } - /// \brief Return true if the end of this range specifies the start of + /// Return true if the end of this range specifies the start of /// the last token. Return false if the end of this range specifies the last /// character in the range. bool isTokenRange() const { return IsTokenRange; } @@ -261,12 +265,13 @@ public: void setBegin(SourceLocation b) { Range.setBegin(b); } void setEnd(SourceLocation e) { Range.setEnd(e); } + void setTokenRange(bool TR) { IsTokenRange = TR; } bool isValid() const { return Range.isValid(); } bool isInvalid() const { return !isValid(); } }; -/// \brief Represents an unpacked "presumed" location which can be presented +/// Represents an unpacked "presumed" location which can be presented /// to the user. /// /// A 'presumed' location can be modified by \#line and GNU line marker @@ -274,23 +279,23 @@ public: /// /// You can get a PresumedLoc from a SourceLocation with SourceManager. class PresumedLoc { - const char *Filename; + const char *Filename = nullptr; unsigned Line, Col; SourceLocation IncludeLoc; public: - PresumedLoc() : Filename(nullptr) {} + PresumedLoc() = default; PresumedLoc(const char *FN, unsigned Ln, unsigned Co, SourceLocation IL) : Filename(FN), Line(Ln), Col(Co), IncludeLoc(IL) {} - /// \brief Return true if this object is invalid or uninitialized. + /// Return true if this object is invalid or uninitialized. /// /// This occurs when created with invalid source locations or when walking /// off the top of a \#include stack. bool isInvalid() const { return Filename == nullptr; } bool isValid() const { return Filename != nullptr; } - /// \brief Return the presumed filename of this location. + /// Return the presumed filename of this location. /// /// This can be affected by \#line etc. const char *getFilename() const { @@ -298,7 +303,7 @@ public: return Filename; } - /// \brief Return the presumed line number of this location. + /// Return the presumed line number of this location. /// /// This can be affected by \#line etc. unsigned getLine() const { @@ -306,7 +311,7 @@ public: return Line; } - /// \brief Return the presumed column number of this location. + /// Return the presumed column number of this location. /// /// This cannot be affected by \#line, but is packaged here for convenience. unsigned getColumn() const { @@ -314,7 +319,7 @@ public: return Col; } - /// \brief Return the presumed include location of this location. + /// Return the presumed include location of this location. /// /// This can be affected by GNU linemarker directives. SourceLocation getIncludeLoc() const { @@ -325,18 +330,18 @@ public: class FileEntry; -/// \brief A SourceLocation and its associated SourceManager. +/// A SourceLocation and its associated SourceManager. /// /// This is useful for argument passing to functions that expect both objects. class FullSourceLoc : public SourceLocation { const SourceManager *SrcMgr = nullptr; public: - /// \brief Creates a FullSourceLoc where isValid() returns \c false. + /// Creates a FullSourceLoc where isValid() returns \c false. FullSourceLoc() = default; explicit FullSourceLoc(SourceLocation Loc, const SourceManager &SM) - : SourceLocation(Loc), SrcMgr(&SM) {} + : SourceLocation(Loc), SrcMgr(&SM) {} bool hasManager() const { bool hasSrcMgr = SrcMgr != nullptr; @@ -355,7 +360,6 @@ public: FullSourceLoc getExpansionLoc() const; FullSourceLoc getSpellingLoc() const; FullSourceLoc getFileLoc() const; - std::pair<FullSourceLoc, FullSourceLoc> getImmediateExpansionRange() const; PresumedLoc getPresumedLoc(bool UseLineDirectives = true) const; bool isMacroArgExpansion(FullSourceLoc *StartLoc = nullptr) const; FullSourceLoc getImmediateMacroCallerLoc() const; @@ -373,15 +377,13 @@ public: unsigned getLineNumber(bool *Invalid = nullptr) const; unsigned getColumnNumber(bool *Invalid = nullptr) const; - std::pair<FullSourceLoc, FullSourceLoc> getExpansionRange() const; - const FileEntry *getFileEntry() const; - /// \brief Return a StringRef to the source buffer data for the + /// Return a StringRef to the source buffer data for the /// specified FileID. StringRef getBufferData(bool *Invalid = nullptr) const; - /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// Decompose the specified location into a raw FileID + Offset pair. /// /// The first element is the FileID, the second is the offset from the /// start of the buffer of the location. @@ -389,12 +391,12 @@ public: bool isInSystemHeader() const; - /// \brief Determines the order of 2 source locations in the translation unit. + /// Determines the order of 2 source locations in the translation unit. /// /// \returns true if this source location comes before 'Loc', false otherwise. bool isBeforeInTranslationUnitThan(SourceLocation Loc) const; - /// \brief Determines the order of 2 source locations in the translation unit. + /// Determines the order of 2 source locations in the translation unit. /// /// \returns true if this source location comes before 'Loc', false otherwise. bool isBeforeInTranslationUnitThan(FullSourceLoc Loc) const { @@ -403,44 +405,43 @@ public: return isBeforeInTranslationUnitThan((SourceLocation)Loc); } - /// \brief Comparison function class, useful for sorting FullSourceLocs. + /// Comparison function class, useful for sorting FullSourceLocs. struct BeforeThanCompare { bool operator()(const FullSourceLoc& lhs, const FullSourceLoc& rhs) const { return lhs.isBeforeInTranslationUnitThan(rhs); } }; - /// \brief Prints information about this FullSourceLoc to stderr. + /// Prints information about this FullSourceLoc to stderr. /// /// This is useful for debugging. void dump() const; - friend inline bool + friend bool operator==(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { return LHS.getRawEncoding() == RHS.getRawEncoding() && LHS.SrcMgr == RHS.SrcMgr; } - friend inline bool + friend bool operator!=(const FullSourceLoc &LHS, const FullSourceLoc &RHS) { return !(LHS == RHS); } - }; - - -} // end namespace clang +} // namespace clang namespace llvm { + /// Define DenseMapInfo so that FileID's can be used as keys in DenseMap and /// DenseSets. template <> struct DenseMapInfo<clang::FileID> { - static inline clang::FileID getEmptyKey() { - return clang::FileID(); + static clang::FileID getEmptyKey() { + return {}; } - static inline clang::FileID getTombstoneKey() { + + static clang::FileID getTombstoneKey() { return clang::FileID::getSentinel(); } @@ -461,15 +462,17 @@ namespace llvm { // Teach SmallPtrSet how to handle SourceLocation. template<> struct PointerLikeTypeTraits<clang::SourceLocation> { - static inline void *getAsVoidPointer(clang::SourceLocation L) { + enum { NumLowBitsAvailable = 0 }; + + static void *getAsVoidPointer(clang::SourceLocation L) { return L.getPtrEncoding(); } - static inline clang::SourceLocation getFromVoidPointer(void *P) { + + static clang::SourceLocation getFromVoidPointer(void *P) { return clang::SourceLocation::getFromRawEncoding((unsigned)(uintptr_t)P); } - enum { NumLowBitsAvailable = 0 }; }; -} // end namespace llvm +} // namespace llvm -#endif +#endif // LLVM_CLANG_BASIC_SOURCELOCATION_H diff --git a/include/clang/Basic/SourceManager.h b/include/clang/Basic/SourceManager.h index 397ad2e77fb5e..99c36f4cdfcc8 100644 --- a/include/clang/Basic/SourceManager.h +++ b/include/clang/Basic/SourceManager.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the SourceManager interface. +/// Defines the SourceManager interface. /// /// There are three different types of locations in a %file: a spelling /// location, an expansion location, and a presumed location. @@ -35,6 +35,7 @@ #ifndef LLVM_CLANG_BASIC_SOURCEMANAGER_H #define LLVM_CLANG_BASIC_SOURCEMANAGER_H +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/ArrayRef.h" @@ -60,15 +61,14 @@ namespace clang { class ASTReader; class ASTWriter; -class DiagnosticsEngine; class LineTableInfo; class SourceManager; -/// \brief Public enums and private classes that are part of the +/// Public enums and private classes that are part of the /// SourceManager implementation. namespace SrcMgr { - /// \brief Indicates whether a file or directory holds normal user code, + /// Indicates whether a file or directory holds normal user code, /// system code, or system code which is implicitly 'extern "C"' in C++ mode. /// /// Entire directories can be tagged with this (this is maintained by @@ -89,19 +89,19 @@ namespace SrcMgr { return CK == C_User_ModuleMap || CK == C_System_ModuleMap; } - /// \brief One instance of this struct is kept for every file loaded or used. + /// One instance of this struct is kept for every file loaded or used. /// /// This object owns the MemoryBuffer object. - class LLVM_ALIGNAS(8) ContentCache { + class alignas(8) ContentCache { enum CCFlags { - /// \brief Whether the buffer is invalid. + /// Whether the buffer is invalid. InvalidFlag = 0x01, - /// \brief Whether the buffer should not be freed on destruction. + /// Whether the buffer should not be freed on destruction. DoNotFreeFlag = 0x02 }; - /// \brief The actual buffer containing the characters from the input + /// The actual buffer containing the characters from the input /// file. /// /// This is owned by the ContentCache object. The bits indicate @@ -109,7 +109,7 @@ namespace SrcMgr { mutable llvm::PointerIntPair<llvm::MemoryBuffer *, 2> Buffer; public: - /// \brief Reference to the file entry representing this ContentCache. + /// Reference to the file entry representing this ContentCache. /// /// This reference does not own the FileEntry object. /// @@ -117,35 +117,35 @@ namespace SrcMgr { /// an imaginary text buffer. const FileEntry *OrigEntry; - /// \brief References the file which the contents were actually loaded from. + /// References the file which the contents were actually loaded from. /// /// Can be different from 'Entry' if we overridden the contents of one file /// with the contents of another file. const FileEntry *ContentsEntry; - /// \brief A bump pointer allocated array of offsets for each source line. + /// A bump pointer allocated array of offsets for each source line. /// /// This is lazily computed. This is owned by the SourceManager /// BumpPointerAllocator object. unsigned *SourceLineCache = nullptr; - /// \brief The number of lines in this ContentCache. + /// The number of lines in this ContentCache. /// /// This is only valid if SourceLineCache is non-null. unsigned NumLines = 0; - /// \brief Indicates whether the buffer itself was provided to override + /// Indicates whether the buffer itself was provided to override /// the actual file contents. /// /// When true, the original entry may be a virtual file that does not /// exist. unsigned BufferOverridden : 1; - /// \brief True if this content cache was initially created for a source + /// True if this content cache was initially created for a source /// file considered as a system one. unsigned IsSystemFile : 1; - /// \brief True if this file may be transient, that is, if it might not + /// True if this file may be transient, that is, if it might not /// exist at some later point in time when this content entry is used, /// after serialization and deserialization. unsigned IsTransient : 1; @@ -176,7 +176,7 @@ namespace SrcMgr { ~ContentCache(); - /// \brief Returns the memory buffer for the associated content. + /// Returns the memory buffer for the associated content. /// /// \param Diag Object through which diagnostics will be emitted if the /// buffer cannot be retrieved. @@ -190,7 +190,7 @@ namespace SrcMgr { SourceLocation Loc = SourceLocation(), bool *Invalid = nullptr) const; - /// \brief Returns the size of the content encapsulated by this + /// Returns the size of the content encapsulated by this /// ContentCache. /// /// This can be the size of the source file or the size of an @@ -198,7 +198,7 @@ namespace SrcMgr { /// file this size is retrieved from the file's FileEntry. unsigned getSize() const; - /// \brief Returns the number of bytes actually mapped for this + /// Returns the number of bytes actually mapped for this /// ContentCache. /// /// This can be 0 if the MemBuffer was not actually expanded. @@ -208,20 +208,20 @@ namespace SrcMgr { /// this content cache. This is used for performance analysis. llvm::MemoryBuffer::BufferKind getMemoryBufferKind() const; - /// \brief Get the underlying buffer, returning NULL if the buffer is not + /// Get the underlying buffer, returning NULL if the buffer is not /// yet available. llvm::MemoryBuffer *getRawBuffer() const { return Buffer.getPointer(); } - /// \brief Replace the existing buffer (which will be deleted) + /// Replace the existing buffer (which will be deleted) /// with the given buffer. void replaceBuffer(llvm::MemoryBuffer *B, bool DoNotFree = false); - /// \brief Determine whether the buffer itself is invalid. + /// Determine whether the buffer itself is invalid. bool isBufferInvalid() const { return Buffer.getInt() & InvalidFlag; } - /// \brief Determine whether the buffer should be freed. + /// Determine whether the buffer should be freed. bool shouldFreeBuffer() const { return (Buffer.getInt() & DoNotFreeFlag) == 0; } @@ -232,7 +232,7 @@ namespace SrcMgr { static_assert(alignof(ContentCache) >= 8, "ContentCache must be 8-byte aligned."); - /// \brief Information about a FileID, basically just the logical file + /// Information about a FileID, basically just the logical file /// that it represents and include stack information. /// /// Each FileInfo has include stack information, indicating where it came @@ -246,26 +246,26 @@ namespace SrcMgr { friend class clang::ASTWriter; friend class clang::ASTReader; - /// \brief The location of the \#include that brought in this file. + /// The location of the \#include that brought in this file. /// /// This is an invalid SLOC for the main file (top of the \#include chain). unsigned IncludeLoc; // Really a SourceLocation - /// \brief Number of FileIDs (files and macros) that were created during + /// Number of FileIDs (files and macros) that were created during /// preprocessing of this \#include, including this SLocEntry. /// /// Zero means the preprocessor didn't provide such info for this SLocEntry. unsigned NumCreatedFIDs : 31; - /// \brief Whether this FileInfo has any \#line directives. + /// Whether this FileInfo has any \#line directives. unsigned HasLineDirectives : 1; - /// \brief The content cache and the characteristic of the file. + /// The content cache and the characteristic of the file. llvm::PointerIntPair<const ContentCache*, 3, CharacteristicKind> ContentAndKind; public: - /// \brief Return a FileInfo object. + /// Return a FileInfo object. static FileInfo get(SourceLocation IL, const ContentCache *Con, CharacteristicKind FileCharacter) { FileInfo X; @@ -285,28 +285,28 @@ namespace SrcMgr { return ContentAndKind.getPointer(); } - /// \brief Return whether this is a system header or not. + /// Return whether this is a system header or not. CharacteristicKind getFileCharacteristic() const { return ContentAndKind.getInt(); } - /// \brief Return true if this FileID has \#line directives in it. + /// Return true if this FileID has \#line directives in it. bool hasLineDirectives() const { return HasLineDirectives; } - /// \brief Set the flag that indicates that this FileID has + /// Set the flag that indicates that this FileID has /// line table entries associated with it. void setHasLineDirectives() { HasLineDirectives = true; } }; - /// \brief Each ExpansionInfo encodes the expansion location - where + /// Each ExpansionInfo encodes the expansion location - where /// the token was ultimately expanded, and the SpellingLoc - where the actual /// character data for the token came from. class ExpansionInfo { // Really these are all SourceLocations. - /// \brief Where the spelling for the token can be found. + /// Where the spelling for the token can be found. unsigned SpellingLoc; /// In a macro expansion, ExpansionLocStart and ExpansionLocEnd @@ -317,9 +317,13 @@ namespace SrcMgr { /// invalid location. unsigned ExpansionLocStart, ExpansionLocEnd; + /// Whether the expansion range is a token range. + bool ExpansionIsTokenRange; + public: SourceLocation getSpellingLoc() const { - return SourceLocation::getFromRawEncoding(SpellingLoc); + SourceLocation SpellLoc = SourceLocation::getFromRawEncoding(SpellingLoc); + return SpellLoc.isInvalid() ? getExpansionLocStart() : SpellLoc; } SourceLocation getExpansionLocStart() const { @@ -332,8 +336,14 @@ namespace SrcMgr { return EndLoc.isInvalid() ? getExpansionLocStart() : EndLoc; } - std::pair<SourceLocation,SourceLocation> getExpansionLocRange() const { - return std::make_pair(getExpansionLocStart(), getExpansionLocEnd()); + bool isExpansionTokenRange() const { + return ExpansionIsTokenRange; + } + + CharSourceRange getExpansionLocRange() const { + return CharSourceRange( + SourceRange(getExpansionLocStart(), getExpansionLocEnd()), + isExpansionTokenRange()); } bool isMacroArgExpansion() const { @@ -352,22 +362,24 @@ namespace SrcMgr { getExpansionLocStart() != getExpansionLocEnd(); } - /// \brief Return a ExpansionInfo for an expansion. + /// Return a ExpansionInfo for an expansion. /// /// Start and End specify the expansion range (where the macro is /// expanded), and SpellingLoc specifies the spelling location (where /// the characters from the token come from). All three can refer to /// normal File SLocs or expansion locations. static ExpansionInfo create(SourceLocation SpellingLoc, - SourceLocation Start, SourceLocation End) { + SourceLocation Start, SourceLocation End, + bool ExpansionIsTokenRange = true) { ExpansionInfo X; X.SpellingLoc = SpellingLoc.getRawEncoding(); X.ExpansionLocStart = Start.getRawEncoding(); X.ExpansionLocEnd = End.getRawEncoding(); + X.ExpansionIsTokenRange = ExpansionIsTokenRange; return X; } - /// \brief Return a special ExpansionInfo for the expansion of + /// Return a special ExpansionInfo for the expansion of /// a macro argument into a function-like macro's body. /// /// ExpansionLoc specifies the expansion location (where the macro is @@ -389,13 +401,24 @@ namespace SrcMgr { static ExpansionInfo createForMacroArg(SourceLocation SpellingLoc, SourceLocation ExpansionLoc) { // We store an intentionally invalid source location for the end of the - // expansion range to mark that this is a macro argument ion rather than - // a normal one. + // expansion range to mark that this is a macro argument location rather + // than a normal one. return create(SpellingLoc, ExpansionLoc, SourceLocation()); } + + /// Return a special ExpansionInfo representing a token that ends + /// prematurely. This is used to model a '>>' token that has been split + /// into '>' tokens and similar cases. Unlike for the other forms of + /// expansion, the expansion range in this case is a character range, not + /// a token range. + static ExpansionInfo createForTokenSplit(SourceLocation SpellingLoc, + SourceLocation Start, + SourceLocation End) { + return create(SpellingLoc, Start, End, false); + } }; - /// \brief This is a discriminated union of FileInfo and ExpansionInfo. + /// This is a discriminated union of FileInfo and ExpansionInfo. /// /// SourceManager keeps an array of these objects, and they are uniquely /// identified by the FileID datatype. @@ -446,44 +469,44 @@ namespace SrcMgr { } // namespace SrcMgr -/// \brief External source of source location entries. +/// External source of source location entries. class ExternalSLocEntrySource { public: virtual ~ExternalSLocEntrySource(); - /// \brief Read the source location entry with index ID, which will always be + /// Read the source location entry with index ID, which will always be /// less than -1. /// /// \returns true if an error occurred that prevented the source-location /// entry from being loaded. virtual bool ReadSLocEntry(int ID) = 0; - /// \brief Retrieve the module import location and name for the given ID, if + /// Retrieve the module import location and name for the given ID, if /// in fact it was loaded from a module (rather than, say, a precompiled /// header). virtual std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) = 0; }; -/// \brief Holds the cache used by isBeforeInTranslationUnit. +/// Holds the cache used by isBeforeInTranslationUnit. /// /// The cache structure is complex enough to be worth breaking out of /// SourceManager. class InBeforeInTUCacheEntry { - /// \brief The FileID's of the cached query. + /// The FileID's of the cached query. /// /// If these match up with a subsequent query, the result can be reused. FileID LQueryFID, RQueryFID; - /// \brief True if LQueryFID was created before RQueryFID. + /// True if LQueryFID was created before RQueryFID. /// /// This is used to compare macro expansion locations. bool IsLQFIDBeforeRQFID; - /// \brief The file found in common between the two \#include traces, i.e., + /// The file found in common between the two \#include traces, i.e., /// the nearest common ancestor of the \#include tree. FileID CommonFID; - /// \brief The offset of the previous query in CommonFID. + /// The offset of the previous query in CommonFID. /// /// Usually, this represents the location of the \#include for QueryFID, but /// if LQueryFID is a parent of RQueryFID (or vice versa) then these can be a @@ -491,7 +514,7 @@ class InBeforeInTUCacheEntry { unsigned LCommonOffset, RCommonOffset; public: - /// \brief Return true if the currently cached values match up with + /// Return true if the currently cached values match up with /// the specified LHS/RHS query. /// /// If not, we can't use the cache. @@ -499,7 +522,7 @@ public: return LQueryFID == LHS && RQueryFID == RHS; } - /// \brief If the cache is valid, compute the result given the + /// If the cache is valid, compute the result given the /// specified offsets in the LHS/RHS FileID's. bool getCachedResult(unsigned LOffset, unsigned ROffset) const { // If one of the query files is the common file, use the offset. Otherwise, @@ -518,7 +541,7 @@ public: return LOffset < ROffset; } - /// \brief Set up a new query. + /// Set up a new query. void setQueryFIDs(FileID LHS, FileID RHS, bool isLFIDBeforeRFID) { assert(LHS != RHS); LQueryFID = LHS; @@ -539,12 +562,12 @@ public: } }; -/// \brief The stack used when building modules on demand, which is used +/// The stack used when building modules on demand, which is used /// to provide a link between the source managers of the different compiler /// instances. using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>; -/// \brief This class handles loading and caching of source files into memory. +/// This class handles loading and caching of source files into memory. /// /// This object owns the MemoryBuffer objects for all of the loaded /// files and assigns unique FileID's for each unique \#include chain. @@ -557,14 +580,14 @@ using ModuleBuildStack = ArrayRef<std::pair<std::string, FullSourceLoc>>; /// where the expanded token came from and the expansion location specifies /// where it was expanded. class SourceManager : public RefCountedBase<SourceManager> { - /// \brief DiagnosticsEngine object. + /// DiagnosticsEngine object. DiagnosticsEngine &Diag; FileManager &FileMgr; mutable llvm::BumpPtrAllocator ContentCacheAlloc; - /// \brief Memoized information about all of the files tracked by this + /// Memoized information about all of the files tracked by this /// SourceManager. /// /// This map allows us to merge ContentCache entries based @@ -572,29 +595,29 @@ class SourceManager : public RefCountedBase<SourceManager> { /// non-null, FileEntry pointers. llvm::DenseMap<const FileEntry*, SrcMgr::ContentCache*> FileInfos; - /// \brief True if the ContentCache for files that are overridden by other + /// True if the ContentCache for files that are overridden by other /// files, should report the original file name. Defaults to true. bool OverridenFilesKeepOriginalName = true; - /// \brief True if non-system source files should be treated as volatile + /// True if non-system source files should be treated as volatile /// (likely to change while trying to use them). Defaults to false. bool UserFilesAreVolatile; - /// \brief True if all files read during this compilation should be treated + /// True if all files read during this compilation should be treated /// as transient (may not be present in later compilations using a module /// file created from this compilation). Defaults to false. bool FilesAreTransient = false; struct OverriddenFilesInfoTy { - /// \brief Files that have been overridden with the contents from another + /// Files that have been overridden with the contents from another /// file. llvm::DenseMap<const FileEntry *, const FileEntry *> OverriddenFiles; - /// \brief Files that were overridden with a memory buffer. + /// Files that were overridden with a memory buffer. llvm::DenseSet<const FileEntry *> OverriddenFilesWithBuffer; }; - /// \brief Lazily create the object keeping overridden files info, since + /// Lazily create the object keeping overridden files info, since /// it is uncommonly used. std::unique_ptr<OverriddenFilesInfoTy> OverriddenFilesInfo; @@ -604,77 +627,77 @@ class SourceManager : public RefCountedBase<SourceManager> { return *OverriddenFilesInfo; } - /// \brief Information about various memory buffers that we have read in. + /// Information about various memory buffers that we have read in. /// /// All FileEntry* within the stored ContentCache objects are NULL, /// as they do not refer to a file. std::vector<SrcMgr::ContentCache*> MemBufferInfos; - /// \brief The table of SLocEntries that are local to this module. + /// The table of SLocEntries that are local to this module. /// /// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid /// expansion. SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable; - /// \brief The table of SLocEntries that are loaded from other modules. + /// The table of SLocEntries that are loaded from other modules. /// /// Negative FileIDs are indexes into this table. To get from ID to an index, /// use (-ID - 2). mutable SmallVector<SrcMgr::SLocEntry, 0> LoadedSLocEntryTable; - /// \brief The starting offset of the next local SLocEntry. + /// The starting offset of the next local SLocEntry. /// /// This is LocalSLocEntryTable.back().Offset + the size of that entry. unsigned NextLocalOffset; - /// \brief The starting offset of the latest batch of loaded SLocEntries. + /// The starting offset of the latest batch of loaded SLocEntries. /// /// This is LoadedSLocEntryTable.back().Offset, except that that entry might /// not have been loaded, so that value would be unknown. unsigned CurrentLoadedOffset; - /// \brief The highest possible offset is 2^31-1, so CurrentLoadedOffset + /// The highest possible offset is 2^31-1, so CurrentLoadedOffset /// starts at 2^31. static const unsigned MaxLoadedOffset = 1U << 31U; - /// \brief A bitmap that indicates whether the entries of LoadedSLocEntryTable + /// A bitmap that indicates whether the entries of LoadedSLocEntryTable /// have already been loaded from the external source. /// /// Same indexing as LoadedSLocEntryTable. llvm::BitVector SLocEntryLoaded; - /// \brief An external source for source location entries. + /// An external source for source location entries. ExternalSLocEntrySource *ExternalSLocEntries = nullptr; - /// \brief A one-entry cache to speed up getFileID. + /// A one-entry cache to speed up getFileID. /// /// LastFileIDLookup records the last FileID looked up or created, because it /// is very common to look up many tokens from the same file. mutable FileID LastFileIDLookup; - /// \brief Holds information for \#line directives. + /// Holds information for \#line directives. /// /// This is referenced by indices from SLocEntryTable. LineTableInfo *LineTable = nullptr; - /// \brief These ivars serve as a cache used in the getLineNumber + /// These ivars serve as a cache used in the getLineNumber /// method which is used to speedup getLineNumber calls to nearby locations. mutable FileID LastLineNoFileIDQuery; mutable SrcMgr::ContentCache *LastLineNoContentCache; mutable unsigned LastLineNoFilePos; mutable unsigned LastLineNoResult; - /// \brief The file ID for the main source file of the translation unit. + /// The file ID for the main source file of the translation unit. FileID MainFileID; - /// \brief The file ID for the precompiled preamble there is one. + /// The file ID for the precompiled preamble there is one. FileID PreambleFileID; // Statistics for -print-stats. mutable unsigned NumLinearScans = 0; mutable unsigned NumBinaryProbes = 0; - /// \brief Associates a FileID with its "included/expanded in" decomposed + /// Associates a FileID with its "included/expanded in" decomposed /// location. /// /// Used to cache results from and speed-up \c getDecomposedIncludedLoc @@ -702,14 +725,14 @@ class SourceManager : public RefCountedBase<SourceManager> { mutable std::unique_ptr<SrcMgr::ContentCache> FakeContentCacheForRecovery; - /// \brief Lazily computed map of macro argument chunks to their expanded + /// Lazily computed map of macro argument chunks to their expanded /// source location. using MacroArgsMap = std::map<unsigned, SourceLocation>; mutable llvm::DenseMap<FileID, std::unique_ptr<MacroArgsMap>> MacroArgsCacheMap; - /// \brief The stack of modules being built, which is used to detect + /// The stack of modules being built, which is used to detect /// cycles in the module dependency graph as modules are being built, as /// well as to describe why we're rebuilding a particular module. /// @@ -735,29 +758,29 @@ public: FileManager &getFileManager() const { return FileMgr; } - /// \brief Set true if the SourceManager should report the original file name + /// Set true if the SourceManager should report the original file name /// for contents of files that were overridden by other files. Defaults to /// true. void setOverridenFilesKeepOriginalName(bool value) { OverridenFilesKeepOriginalName = value; } - /// \brief True if non-system source files should be treated as volatile + /// True if non-system source files should be treated as volatile /// (likely to change while trying to use them). bool userFilesAreVolatile() const { return UserFilesAreVolatile; } - /// \brief Retrieve the module build stack. + /// Retrieve the module build stack. ModuleBuildStack getModuleBuildStack() const { return StoredModuleBuildStack; } - /// \brief Set the module build stack. + /// Set the module build stack. void setModuleBuildStack(ModuleBuildStack stack) { StoredModuleBuildStack.clear(); StoredModuleBuildStack.append(stack.begin(), stack.end()); } - /// \brief Push an entry to the module build stack. + /// Push an entry to the module build stack. void pushModuleBuildStack(StringRef moduleName, FullSourceLoc importLoc) { StoredModuleBuildStack.push_back(std::make_pair(moduleName.str(),importLoc)); } @@ -766,28 +789,28 @@ public: // MainFileID creation and querying methods. //===--------------------------------------------------------------------===// - /// \brief Returns the FileID of the main source file. + /// Returns the FileID of the main source file. FileID getMainFileID() const { return MainFileID; } - /// \brief Set the file ID for the main source file. + /// Set the file ID for the main source file. void setMainFileID(FileID FID) { MainFileID = FID; } - /// \brief Set the file ID for the precompiled preamble. + /// Set the file ID for the precompiled preamble. void setPreambleFileID(FileID Preamble) { assert(PreambleFileID.isInvalid() && "PreambleFileID already set!"); PreambleFileID = Preamble; } - /// \brief Get the file ID for the precompiled preamble if there is one. + /// Get the file ID for the precompiled preamble if there is one. FileID getPreambleFileID() const { return PreambleFileID; } //===--------------------------------------------------------------------===// // Methods to create new FileID's and macro expansions. //===--------------------------------------------------------------------===// - /// \brief Create a new FileID that represents the specified file + /// Create a new FileID that represents the specified file /// being \#included from the specified IncludePosition. /// /// This translates NULL into standard input. @@ -800,7 +823,7 @@ public: return createFileID(IR, IncludePos, FileCharacter, LoadedID, LoadedOffset); } - /// \brief Create a new FileID that represents the specified memory buffer. + /// Create a new FileID that represents the specified memory buffer. /// /// This does no caching of the buffer and takes ownership of the /// MemoryBuffer, so only pass a MemoryBuffer to this once. @@ -815,7 +838,7 @@ public: enum UnownedTag { Unowned }; - /// \brief Create a new FileID that represents the specified memory buffer. + /// Create a new FileID that represents the specified memory buffer. /// /// This does no caching of the buffer and takes ownership of the /// MemoryBuffer, so only pass a MemoryBuffer to this once. @@ -827,7 +850,7 @@ public: IncludeLoc, FileCharacter, LoadedID, LoadedOffset); } - /// \brief Get the FileID for \p SourceFile if it exists. Otherwise, create a + /// Get the FileID for \p SourceFile if it exists. Otherwise, create a /// new FileID for the \p SourceFile. FileID getOrCreateFileID(const FileEntry *SourceFile, SrcMgr::CharacteristicKind FileCharacter) { @@ -836,7 +859,7 @@ public: FileCharacter); } - /// \brief Return a new SourceLocation that encodes the + /// Return a new SourceLocation that encodes the /// fact that a token from SpellingLoc should actually be referenced from /// ExpansionLoc, and that it represents the expansion of a macro argument /// into the function-like macro body. @@ -844,24 +867,31 @@ public: SourceLocation ExpansionLoc, unsigned TokLength); - /// \brief Return a new SourceLocation that encodes the fact + /// Return a new SourceLocation that encodes the fact /// that a token from SpellingLoc should actually be referenced from /// ExpansionLoc. SourceLocation createExpansionLoc(SourceLocation Loc, SourceLocation ExpansionLocStart, SourceLocation ExpansionLocEnd, unsigned TokLength, + bool ExpansionIsTokenRange = true, int LoadedID = 0, unsigned LoadedOffset = 0); - /// \brief Retrieve the memory buffer associated with the given file. + /// Return a new SourceLocation that encodes that the token starting + /// at \p TokenStart ends prematurely at \p TokenEnd. + SourceLocation createTokenSplitLoc(SourceLocation SpellingLoc, + SourceLocation TokenStart, + SourceLocation TokenEnd); + + /// Retrieve the memory buffer associated with the given file. /// /// \param Invalid If non-NULL, will be set \c true if an error /// occurs while retrieving the memory buffer. llvm::MemoryBuffer *getMemoryBufferForFile(const FileEntry *File, bool *Invalid = nullptr); - /// \brief Override the contents of the given source file by providing an + /// Override the contents of the given source file by providing an /// already-allocated buffer. /// /// \param SourceFile the source file whose contents will be overridden. @@ -878,7 +908,7 @@ public: overrideFileContents(SourceFile, Buffer.release(), /*DoNotFree*/ false); } - /// \brief Override the given source file with another one. + /// Override the given source file with another one. /// /// \param SourceFile the source file which will be overridden. /// @@ -887,7 +917,7 @@ public: void overrideFileContents(const FileEntry *SourceFile, const FileEntry *NewFile); - /// \brief Returns true if the file contents have been overridden. + /// Returns true if the file contents have been overridden. bool isFileOverridden(const FileEntry *File) const { if (OverriddenFilesInfo) { if (OverriddenFilesInfo->OverriddenFilesWithBuffer.count(File)) @@ -899,16 +929,16 @@ public: return false; } - /// \brief Disable overridding the contents of a file, previously enabled + /// Disable overridding the contents of a file, previously enabled /// with #overrideFileContents. /// /// This should be called before parsing has begun. void disableFileContentsOverride(const FileEntry *File); - /// \brief Specify that a file is transient. + /// Specify that a file is transient. void setFileIsTransient(const FileEntry *SourceFile); - /// \brief Specify that all files that are read during this compilation are + /// Specify that all files that are read during this compilation are /// transient. void setAllFilesAreTransient(bool Transient) { FilesAreTransient = Transient; @@ -918,7 +948,7 @@ public: // FileID manipulation methods. //===--------------------------------------------------------------------===// - /// \brief Return the buffer for the specified FileID. + /// Return the buffer for the specified FileID. /// /// If there is an error opening this buffer the first time, this /// manufactures a temporary buffer and returns a non-empty error string. @@ -952,7 +982,7 @@ public: Invalid); } - /// \brief Returns the FileEntry record for the provided FileID. + /// Returns the FileEntry record for the provided FileID. const FileEntry *getFileEntryForID(FileID FID) const { bool MyInvalid = false; const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &MyInvalid); @@ -965,7 +995,7 @@ public: return Content->OrigEntry; } - /// \brief Returns the FileEntry record for the provided SLocEntry. + /// Returns the FileEntry record for the provided SLocEntry. const FileEntry *getFileEntryForSLocEntry(const SrcMgr::SLocEntry &sloc) const { const SrcMgr::ContentCache *Content = sloc.getFile().getContentCache(); @@ -974,14 +1004,14 @@ public: return Content->OrigEntry; } - /// \brief Return a StringRef to the source buffer data for the + /// Return a StringRef to the source buffer data for the /// specified FileID. /// /// \param FID The file ID whose contents will be returned. /// \param Invalid If non-NULL, will be set true if an error occurred. StringRef getBufferData(FileID FID, bool *Invalid = nullptr) const; - /// \brief Get the number of FileIDs (files and macros) that were created + /// Get the number of FileIDs (files and macros) that were created /// during preprocessing of \p FID, including it. unsigned getNumCreatedFIDsForFileID(FileID FID) const { bool Invalid = false; @@ -992,7 +1022,7 @@ public: return Entry.getFile().NumCreatedFIDs; } - /// \brief Set the number of FileIDs (files and macros) that were created + /// Set the number of FileIDs (files and macros) that were created /// during preprocessing of \p FID, including it. void setNumCreatedFIDsForFileID(FileID FID, unsigned NumFIDs) const { bool Invalid = false; @@ -1008,7 +1038,7 @@ public: // SourceLocation manipulation methods. //===--------------------------------------------------------------------===// - /// \brief Return the FileID for a SourceLocation. + /// Return the FileID for a SourceLocation. /// /// This is a very hot method that is used for all SourceManager queries /// that start with a SourceLocation object. It is responsible for finding @@ -1024,14 +1054,14 @@ public: return getFileIDSlow(SLocOffset); } - /// \brief Return the filename of the file containing a SourceLocation. + /// Return the filename of the file containing a SourceLocation. StringRef getFilename(SourceLocation SpellingLoc) const { if (const FileEntry *F = getFileEntryForID(getFileID(SpellingLoc))) return F->getName(); return StringRef(); } - /// \brief Return the source location corresponding to the first byte of + /// Return the source location corresponding to the first byte of /// the specified file. SourceLocation getLocForStartOfFile(FileID FID) const { bool Invalid = false; @@ -1043,7 +1073,7 @@ public: return SourceLocation::getFileLoc(FileOffset); } - /// \brief Return the source location corresponding to the last byte of the + /// Return the source location corresponding to the last byte of the /// specified file. SourceLocation getLocForEndOfFile(FileID FID) const { bool Invalid = false; @@ -1055,7 +1085,7 @@ public: return SourceLocation::getFileLoc(FileOffset + getFileIDSize(FID)); } - /// \brief Returns the include location if \p FID is a \#include'd file + /// Returns the include location if \p FID is a \#include'd file /// otherwise it returns an invalid location. SourceLocation getIncludeLoc(FileID FID) const { bool Invalid = false; @@ -1066,7 +1096,7 @@ public: return Entry.getFile().getIncludeLoc(); } - // \brief Returns the import location if the given source location is + // Returns the import location if the given source location is // located within a module, or an invalid location if the source location // is within the current translation unit. std::pair<SourceLocation, StringRef> @@ -1081,7 +1111,7 @@ public: return ExternalSLocEntries->getModuleImportLoc(FID.ID); } - /// \brief Given a SourceLocation object \p Loc, return the expansion + /// Given a SourceLocation object \p Loc, return the expansion /// location referenced by the ID. SourceLocation getExpansionLoc(SourceLocation Loc) const { // Handle the non-mapped case inline, defer to out of line code to handle @@ -1090,7 +1120,7 @@ public: return getExpansionLocSlowCase(Loc); } - /// \brief Given \p Loc, if it is a macro location return the expansion + /// Given \p Loc, if it is a macro location return the expansion /// location or the spelling location, depending on if it comes from a /// macro argument or not. SourceLocation getFileLoc(SourceLocation Loc) const { @@ -1098,26 +1128,35 @@ public: return getFileLocSlowCase(Loc); } - /// \brief Return the start/end of the expansion information for an + /// Return the start/end of the expansion information for an /// expansion location. /// /// \pre \p Loc is required to be an expansion location. - std::pair<SourceLocation,SourceLocation> - getImmediateExpansionRange(SourceLocation Loc) const; + CharSourceRange getImmediateExpansionRange(SourceLocation Loc) const; - /// \brief Given a SourceLocation object, return the range of + /// Given a SourceLocation object, return the range of /// tokens covered by the expansion in the ultimate file. - std::pair<SourceLocation,SourceLocation> - getExpansionRange(SourceLocation Loc) const; + CharSourceRange getExpansionRange(SourceLocation Loc) const; - /// \brief Given a SourceRange object, return the range of - /// tokens covered by the expansion in the ultimate file. - SourceRange getExpansionRange(SourceRange Range) const { - return SourceRange(getExpansionRange(Range.getBegin()).first, - getExpansionRange(Range.getEnd()).second); + /// Given a SourceRange object, return the range of + /// tokens or characters covered by the expansion in the ultimate file. + CharSourceRange getExpansionRange(SourceRange Range) const { + SourceLocation Begin = getExpansionRange(Range.getBegin()).getBegin(); + CharSourceRange End = getExpansionRange(Range.getEnd()); + return CharSourceRange(SourceRange(Begin, End.getEnd()), + End.isTokenRange()); + } + + /// Given a CharSourceRange object, return the range of + /// tokens or characters covered by the expansion in the ultimate file. + CharSourceRange getExpansionRange(CharSourceRange Range) const { + CharSourceRange Expansion = getExpansionRange(Range.getAsRange()); + if (Expansion.getEnd() == Range.getEnd()) + Expansion.setTokenRange(Range.isTokenRange()); + return Expansion; } - /// \brief Given a SourceLocation object, return the spelling + /// Given a SourceLocation object, return the spelling /// location referenced by the ID. /// /// This is the place where the characters that make up the lexed token @@ -1129,7 +1168,7 @@ public: return getSpellingLocSlowCase(Loc); } - /// \brief Given a SourceLocation object, return the spelling location + /// Given a SourceLocation object, return the spelling location /// referenced by the ID. /// /// This is the first level down towards the place where the characters @@ -1137,7 +1176,19 @@ public: /// be used by clients. SourceLocation getImmediateSpellingLoc(SourceLocation Loc) const; - /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// Form a SourceLocation from a FileID and Offset pair. + SourceLocation getComposedLoc(FileID FID, unsigned Offset) const { + bool Invalid = false; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID, &Invalid); + if (Invalid) + return SourceLocation(); + + unsigned GlobalOffset = Entry.getOffset() + Offset; + return Entry.isFile() ? SourceLocation::getFileLoc(GlobalOffset) + : SourceLocation::getMacroLoc(GlobalOffset); + } + + /// Decompose the specified location into a raw FileID + Offset pair. /// /// The first element is the FileID, the second is the offset from the /// start of the buffer of the location. @@ -1150,7 +1201,7 @@ public: return std::make_pair(FID, Loc.getOffset()-E.getOffset()); } - /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// Decompose the specified location into a raw FileID + Offset pair. /// /// If the location is an expansion record, walk through it until we find /// the final location expanded. @@ -1169,7 +1220,7 @@ public: return getDecomposedExpansionLocSlowCase(E); } - /// \brief Decompose the specified location into a raw FileID + Offset pair. + /// Decompose the specified location into a raw FileID + Offset pair. /// /// If the location is an expansion record, walk through it until we find /// its spelling record. @@ -1187,11 +1238,11 @@ public: return getDecomposedSpellingLocSlowCase(E, Offset); } - /// \brief Returns the "included/expanded in" decomposed location of the given + /// Returns the "included/expanded in" decomposed location of the given /// FileID. std::pair<FileID, unsigned> getDecomposedIncludedLoc(FileID FID) const; - /// \brief Returns the offset from the start of the file that the + /// Returns the offset from the start of the file that the /// specified SourceLocation represents. /// /// This is not very meaningful for a macro ID. @@ -1199,7 +1250,7 @@ public: return getDecomposedLoc(SpellingLoc).second; } - /// \brief Tests whether the given source location represents a macro + /// Tests whether the given source location represents a macro /// argument's expansion into the function-like macro definition. /// /// \param StartLoc If non-null and function returns true, it is set to the @@ -1211,14 +1262,14 @@ public: bool isMacroArgExpansion(SourceLocation Loc, SourceLocation *StartLoc = nullptr) const; - /// \brief Tests whether the given source location represents the expansion of + /// Tests whether the given source location represents the expansion of /// a macro body. /// /// This is equivalent to testing whether the location is part of a macro /// expansion but not the expansion of an argument to a function-like macro. bool isMacroBodyExpansion(SourceLocation Loc) const; - /// \brief Returns true if the given MacroID location points at the beginning + /// Returns true if the given MacroID location points at the beginning /// of the immediate macro expansion. /// /// \param MacroBegin If non-null and function returns true, it is set to the @@ -1226,7 +1277,7 @@ public: bool isAtStartOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroBegin = nullptr) const; - /// \brief Returns true if the given MacroID location points at the character + /// Returns true if the given MacroID location points at the character /// end of the immediate macro expansion. /// /// \param MacroEnd If non-null and function returns true, it is set to the @@ -1235,7 +1286,7 @@ public: isAtEndOfImmediateMacroExpansion(SourceLocation Loc, SourceLocation *MacroEnd = nullptr) const; - /// \brief Returns true if \p Loc is inside the [\p Start, +\p Length) + /// Returns true if \p Loc is inside the [\p Start, +\p Length) /// chunk of the source location address space. /// /// If it's true and \p RelativeOffset is non-null, it will be set to the @@ -1260,7 +1311,7 @@ public: return false; } - /// \brief Return true if both \p LHS and \p RHS are in the local source + /// Return true if both \p LHS and \p RHS are in the local source /// location address space or the loaded one. /// /// If it's true and \p RelativeOffset is non-null, it will be set to the @@ -1284,14 +1335,14 @@ public: // Queries about the code at a SourceLocation. //===--------------------------------------------------------------------===// - /// \brief Return a pointer to the start of the specified location + /// Return a pointer to the start of the specified location /// in the appropriate spelling MemoryBuffer. /// /// \param Invalid If non-NULL, will be set \c true if an error occurs. const char *getCharacterData(SourceLocation SL, bool *Invalid = nullptr) const; - /// \brief Return the column # for the specified file position. + /// Return the column # for the specified file position. /// /// This is significantly cheaper to compute than the line number. This /// returns zero if the column number isn't known. This may only be called @@ -1306,7 +1357,7 @@ public: unsigned getPresumedColumnNumber(SourceLocation Loc, bool *Invalid = nullptr) const; - /// \brief Given a SourceLocation, return the spelling line number + /// Given a SourceLocation, return the spelling line number /// for the position indicated. /// /// This requires building and caching a table of line offsets for the @@ -1317,14 +1368,14 @@ public: unsigned getExpansionLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; unsigned getPresumedLineNumber(SourceLocation Loc, bool *Invalid = nullptr) const; - /// \brief Return the filename or buffer identifier of the buffer the + /// Return the filename or buffer identifier of the buffer the /// location is in. /// /// Note that this name does not respect \#line directives. Use /// getPresumedLoc for normal clients. StringRef getBufferName(SourceLocation Loc, bool *Invalid = nullptr) const; - /// \brief Return the file characteristic of the specified source + /// Return the file characteristic of the specified source /// location, indicating whether this is a normal file, a system /// header, or an "implicit extern C" system header. /// @@ -1336,7 +1387,7 @@ public: /// considered to be from a system header. SrcMgr::CharacteristicKind getFileCharacteristic(SourceLocation Loc) const; - /// \brief Returns the "presumed" location of a SourceLocation specifies. + /// Returns the "presumed" location of a SourceLocation specifies. /// /// A "presumed location" can be modified by \#line or GNU line marker /// directives. This provides a view on the data that a user should see @@ -1352,7 +1403,7 @@ public: PresumedLoc getPresumedLoc(SourceLocation Loc, bool UseLineDirectives = true) const; - /// \brief Returns whether the PresumedLoc for a given SourceLocation is + /// Returns whether the PresumedLoc for a given SourceLocation is /// in the main file. /// /// This computes the "presumed" location for a SourceLocation, then checks @@ -1361,7 +1412,7 @@ public: /// account. bool isInMainFile(SourceLocation Loc) const; - /// \brief Returns true if the spelling locations for both SourceLocations + /// Returns true if the spelling locations for both SourceLocations /// are part of the same file buffer. /// /// This check ignores line marker directives. @@ -1369,7 +1420,7 @@ public: return getFileID(Loc1) == getFileID(Loc2); } - /// \brief Returns true if the spelling location for the given location + /// Returns true if the spelling location for the given location /// is in the main file buffer. /// /// This check ignores line marker directives. @@ -1377,25 +1428,25 @@ public: return getFileID(Loc) == getMainFileID(); } - /// \brief Returns if a SourceLocation is in a system header. + /// Returns if a SourceLocation is in a system header. bool isInSystemHeader(SourceLocation Loc) const { return isSystem(getFileCharacteristic(Loc)); } - /// \brief Returns if a SourceLocation is in an "extern C" system header. + /// Returns if a SourceLocation is in an "extern C" system header. bool isInExternCSystemHeader(SourceLocation Loc) const { return getFileCharacteristic(Loc) == SrcMgr::C_ExternCSystem; } - /// \brief Returns whether \p Loc is expanded from a macro in a system header. + /// Returns whether \p Loc is expanded from a macro in a system header. bool isInSystemMacro(SourceLocation loc) const { return loc.isMacroID() && isInSystemHeader(getSpellingLoc(loc)); } - /// \brief The size of the SLocEntry that \p FID represents. + /// The size of the SLocEntry that \p FID represents. unsigned getFileIDSize(FileID FID) const; - /// \brief Given a specific FileID, returns true if \p Loc is inside that + /// Given a specific FileID, returns true if \p Loc is inside that /// FileID chunk and sets relative offset (offset of \p Loc from beginning /// of FileID) to \p relativeOffset. bool isInFileID(SourceLocation Loc, FileID FID, @@ -1414,10 +1465,10 @@ public: // Line Table Manipulation Routines //===--------------------------------------------------------------------===// - /// \brief Return the uniqued ID for the specified filename. + /// Return the uniqued ID for the specified filename. unsigned getLineTableFilenameID(StringRef Str); - /// \brief Add a line note to the line table for the FileID and offset + /// Add a line note to the line table for the FileID and offset /// specified by Loc. /// /// If FilenameID is -1, it is considered to be unspecified. @@ -1425,17 +1476,17 @@ public: bool IsFileEntry, bool IsFileExit, SrcMgr::CharacteristicKind FileKind); - /// \brief Determine if the source manager has a line table. + /// Determine if the source manager has a line table. bool hasLineTable() const { return LineTable != nullptr; } - /// \brief Retrieve the stored line table. + /// Retrieve the stored line table. LineTableInfo &getLineTable(); //===--------------------------------------------------------------------===// // Queries for performance analysis. //===--------------------------------------------------------------------===// - /// \brief Return the total amount of physical memory allocated by the + /// Return the total amount of physical memory allocated by the /// ContentCache allocator. size_t getContentCacheSize() const { return ContentCacheAlloc.getTotalMemory(); @@ -1449,11 +1500,11 @@ public: : malloc_bytes(malloc_bytes), mmap_bytes(mmap_bytes) {} }; - /// \brief Return the amount of memory used by memory buffers, breaking down + /// Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. MemoryBufferSizes getMemoryBufferSizes() const; - /// \brief Return the amount of memory used for various side tables and + /// Return the amount of memory used for various side tables and /// data structures in the SourceManager. size_t getDataStructureSizes() const; @@ -1461,25 +1512,25 @@ public: // Other miscellaneous methods. //===--------------------------------------------------------------------===// - /// \brief Get the source location for the given file:line:col triplet. + /// Get the source location for the given file:line:col triplet. /// /// If the source file is included multiple times, the source location will /// be based upon the first inclusion. SourceLocation translateFileLineCol(const FileEntry *SourceFile, unsigned Line, unsigned Col) const; - /// \brief Get the FileID for the given file. + /// Get the FileID for the given file. /// /// If the source file is included multiple times, the FileID will be the /// first inclusion. FileID translateFile(const FileEntry *SourceFile) const; - /// \brief Get the source location in \p FID for the given line:col. + /// Get the source location in \p FID for the given line:col. /// Returns null location if \p FID is not a file SLocEntry. SourceLocation translateLineCol(FileID FID, unsigned Line, unsigned Col) const; - /// \brief If \p Loc points inside a function macro argument, the returned + /// If \p Loc points inside a function macro argument, the returned /// location will be the macro location in which the argument was expanded. /// If a macro argument is used multiple times, the expanded location will /// be at the first expansion of the argument. @@ -1490,12 +1541,12 @@ public: /// where 'foo' was expanded into. SourceLocation getMacroArgExpandedLocation(SourceLocation Loc) const; - /// \brief Determines the order of 2 source locations in the translation unit. + /// Determines the order of 2 source locations in the translation unit. /// /// \returns true if LHS source location comes before RHS, false otherwise. bool isBeforeInTranslationUnit(SourceLocation LHS, SourceLocation RHS) const; - /// \brief Determines whether the two decomposed source location is in the + /// Determines whether the two decomposed source location is in the /// same translation unit. As a byproduct, it also calculates the order /// of the source locations in case they are in the same TU. /// @@ -1506,13 +1557,13 @@ public: isInTheSameTranslationUnit(std::pair<FileID, unsigned> &LOffs, std::pair<FileID, unsigned> &ROffs) const; - /// \brief Determines the order of 2 source locations in the "source location + /// Determines the order of 2 source locations in the "source location /// address space". bool isBeforeInSLocAddrSpace(SourceLocation LHS, SourceLocation RHS) const { return isBeforeInSLocAddrSpace(LHS, RHS.getOffset()); } - /// \brief Determines the order of a source location and a source location + /// Determines the order of a source location and a source location /// offset in the "source location address space". /// /// Note that we always consider source locations loaded from @@ -1544,25 +1595,25 @@ public: return FileInfos.find(File) != FileInfos.end(); } - /// \brief Print statistics to stderr. + /// Print statistics to stderr. void PrintStats() const; void dump() const; - /// \brief Get the number of local SLocEntries we have. + /// Get the number of local SLocEntries we have. unsigned local_sloc_entry_size() const { return LocalSLocEntryTable.size(); } - /// \brief Get a local SLocEntry. This is exposed for indexing. + /// Get a local SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLocalSLocEntry(unsigned Index, bool *Invalid = nullptr) const { assert(Index < LocalSLocEntryTable.size() && "Invalid index"); return LocalSLocEntryTable[Index]; } - /// \brief Get the number of loaded SLocEntries we have. + /// Get the number of loaded SLocEntries we have. unsigned loaded_sloc_entry_size() const { return LoadedSLocEntryTable.size();} - /// \brief Get a loaded SLocEntry. This is exposed for indexing. + /// Get a loaded SLocEntry. This is exposed for indexing. const SrcMgr::SLocEntry &getLoadedSLocEntry(unsigned Index, bool *Invalid = nullptr) const { assert(Index < LoadedSLocEntryTable.size() && "Invalid index"); @@ -1588,7 +1639,7 @@ public: ExternalSLocEntries = Source; } - /// \brief Allocate a number of loaded SLocEntries, which will be actually + /// Allocate a number of loaded SLocEntries, which will be actually /// loaded on demand from the external source. /// /// NumSLocEntries will be allocated, which occupy a total of TotalSize space @@ -1597,23 +1648,23 @@ public: std::pair<int, unsigned> AllocateLoadedSLocEntries(unsigned NumSLocEntries, unsigned TotalSize); - /// \brief Returns true if \p Loc came from a PCH/Module. + /// Returns true if \p Loc came from a PCH/Module. bool isLoadedSourceLocation(SourceLocation Loc) const { return Loc.getOffset() >= CurrentLoadedOffset; } - /// \brief Returns true if \p Loc did not come from a PCH/Module. + /// Returns true if \p Loc did not come from a PCH/Module. bool isLocalSourceLocation(SourceLocation Loc) const { return Loc.getOffset() < NextLocalOffset; } - /// \brief Returns true if \p FID came from a PCH/Module. + /// Returns true if \p FID came from a PCH/Module. bool isLoadedFileID(FileID FID) const { assert(FID.ID != -1 && "Using FileID sentinel value"); return FID.ID < 0; } - /// \brief Returns true if \p FID did not come from a PCH/Module. + /// Returns true if \p FID did not come from a PCH/Module. bool isLocalFileID(FileID FID) const { return !isLoadedFileID(FID); } @@ -1631,9 +1682,12 @@ public: // Otherwise, the caller of the macro is located where this macro is // expanded (while the spelling is part of the macro definition). - return getImmediateExpansionRange(Loc).first; + return getImmediateExpansionRange(Loc).getBegin(); } + /// \return Location of the top-level macro caller. + SourceLocation getTopMacroCallerLoc(SourceLocation Loc) const; + private: friend class ASTReader; friend class ASTWriter; @@ -1643,7 +1697,7 @@ private: const SrcMgr::SLocEntry &loadSLocEntry(unsigned Index, bool *Invalid) const; - /// \brief Get the entry with the given unwrapped FileID. + /// Get the entry with the given unwrapped FileID. const SrcMgr::SLocEntry &getSLocEntryByID(int ID, bool *Invalid = nullptr) const { assert(ID != -1 && "Using FileID sentinel value"); @@ -1664,7 +1718,7 @@ private: int LoadedID = 0, unsigned LoadedOffset = 0); - /// \brief Return true if the specified FileID contains the + /// Return true if the specified FileID contains the /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, unsigned SLocOffset) const { const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); @@ -1684,15 +1738,15 @@ private: return SLocOffset < getSLocEntryByID(FID.ID+1).getOffset(); } - /// \brief Returns the previous in-order FileID or an invalid FileID if there + /// Returns the previous in-order FileID or an invalid FileID if there /// is no previous one. FileID getPreviousFileID(FileID FID) const; - /// \brief Returns the next in-order FileID or an invalid FileID if there is + /// Returns the next in-order FileID or an invalid FileID if there is /// no next one. FileID getNextFileID(FileID FID) const; - /// \brief Create a new fileID for the specified ContentCache and + /// Create a new fileID for the specified ContentCache and /// include position. /// /// This works regardless of whether the ContentCache corresponds to a @@ -1706,7 +1760,7 @@ private: getOrCreateContentCache(const FileEntry *SourceFile, bool isSystemFile = false); - /// \brief Create a new ContentCache for the specified memory buffer. + /// Create a new ContentCache for the specified memory buffer. const SrcMgr::ContentCache * createMemBufferContentCache(llvm::MemoryBuffer *Buf, bool DoNotFree); @@ -1731,11 +1785,11 @@ private: unsigned ExpansionLength) const; }; -/// \brief Comparison function object. +/// Comparison function object. template<typename T> class BeforeThanCompare; -/// \brief Compare two source locations. +/// Compare two source locations. template<> class BeforeThanCompare<SourceLocation> { SourceManager &SM; @@ -1748,7 +1802,7 @@ public: } }; -/// \brief Compare two non-overlapping source ranges. +/// Compare two non-overlapping source ranges. template<> class BeforeThanCompare<SourceRange> { SourceManager &SM; @@ -1761,6 +1815,28 @@ public: } }; +/// SourceManager and necessary depdencies (e.g. VFS, FileManager) for a single +/// in-memorty file. +class SourceManagerForFile { +public: + /// Creates SourceManager and necessary depdencies (e.g. VFS, FileManager). + /// The main file in the SourceManager will be \p FileName with \p Content. + SourceManagerForFile(StringRef FileName, StringRef Content); + + SourceManager &get() { + assert(SourceMgr); + return *SourceMgr; + } + +private: + // The order of these fields are important - they should be in the same order + // as they are created in `createSourceManagerForFile` so that they can be + // deleted in the reverse order as they are created. + std::unique_ptr<FileManager> FileMgr; + std::unique_ptr<DiagnosticsEngine> Diagnostics; + std::unique_ptr<SourceManager> SourceMgr; +}; + } // namespace clang #endif // LLVM_CLANG_BASIC_SOURCEMANAGER_H diff --git a/include/clang/Basic/SourceManagerInternals.h b/include/clang/Basic/SourceManagerInternals.h index edd910e704128..68873be594d4b 100644 --- a/include/clang/Basic/SourceManagerInternals.h +++ b/include/clang/Basic/SourceManagerInternals.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines implementation details of the clang::SourceManager class. +/// Defines implementation details of the clang::SourceManager class. // //===----------------------------------------------------------------------===// @@ -31,20 +31,20 @@ namespace clang { //===----------------------------------------------------------------------===// struct LineEntry { - /// \brief The offset in this file that the line entry occurs at. + /// The offset in this file that the line entry occurs at. unsigned FileOffset; - /// \brief The presumed line number of this line entry: \#line 4. + /// The presumed line number of this line entry: \#line 4. unsigned LineNo; - /// \brief The ID of the filename identified by this line entry: + /// The ID of the filename identified by this line entry: /// \#line 4 "foo.c". This is -1 if not specified. int FilenameID; - /// \brief Set the 0 if no flags, 1 if a system header, + /// Set the 0 if no flags, 1 if a system header, SrcMgr::CharacteristicKind FileKind; - /// \brief The offset of the virtual include stack location, + /// The offset of the virtual include stack location, /// which is manipulated by GNU linemarker directives. /// /// If this is 0 then there is no virtual \#includer. @@ -77,9 +77,9 @@ inline bool operator<(unsigned Offset, const LineEntry &E) { return Offset < E.FileOffset; } -/// \brief Used to hold and unique data used to represent \#line information. +/// Used to hold and unique data used to represent \#line information. class LineTableInfo { - /// \brief Map used to assign unique IDs to filenames in \#line directives. + /// Map used to assign unique IDs to filenames in \#line directives. /// /// This allows us to unique the filenames that /// frequently reoccur and reference them with indices. FilenameIDs holds @@ -88,7 +88,7 @@ class LineTableInfo { llvm::StringMap<unsigned, llvm::BumpPtrAllocator> FilenameIDs; std::vector<llvm::StringMapEntry<unsigned>*> FilenamesByID; - /// \brief Map from FileIDs to a list of line entries (sorted by the offset + /// Map from FileIDs to a list of line entries (sorted by the offset /// at which they occur in the file). std::map<FileID, std::vector<LineEntry>> LineEntries; @@ -113,7 +113,7 @@ public: unsigned EntryExit, SrcMgr::CharacteristicKind FileKind); - /// \brief Find the line entry nearest to FID that is before it. + /// Find the line entry nearest to FID that is before it. /// /// If there is no line entry before \p Offset in \p FID, returns null. const LineEntry *FindNearestLineEntry(FileID FID, unsigned Offset); @@ -124,7 +124,7 @@ public: iterator begin() { return LineEntries.begin(); } iterator end() { return LineEntries.end(); } - /// \brief Add a new line entry that has already been encoded into + /// Add a new line entry that has already been encoded into /// the internal representation of the line table. void AddEntry(FileID FID, const std::vector<LineEntry> &Entries); }; diff --git a/include/clang/Basic/Specifiers.h b/include/clang/Basic/Specifiers.h index 377534baab06b..303b77e448053 100644 --- a/include/clang/Basic/Specifiers.h +++ b/include/clang/Basic/Specifiers.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines various enumerations that describe declaration and +/// Defines various enumerations that describe declaration and /// type specifiers. /// //===----------------------------------------------------------------------===// @@ -21,7 +21,7 @@ #include "llvm/Support/ErrorHandling.h" namespace clang { - /// \brief Specifies the width of a type, e.g., short, long, or long long. + /// Specifies the width of a type, e.g., short, long, or long long. enum TypeSpecifierWidth { TSW_unspecified, TSW_short, @@ -29,7 +29,7 @@ namespace clang { TSW_longlong }; - /// \brief Specifies the signedness of a type, e.g., signed or unsigned. + /// Specifies the signedness of a type, e.g., signed or unsigned. enum TypeSpecifierSign { TSS_unspecified, TSS_signed, @@ -41,18 +41,21 @@ namespace clang { TSP_pipe }; - /// \brief Specifies the kind of type. + /// Specifies the kind of type. enum TypeSpecifierType { TST_unspecified, TST_void, TST_char, TST_wchar, // C++ wchar_t + TST_char8, // C++20 char8_t (proposed) TST_char16, // C++11 char16_t TST_char32, // C++11 char32_t TST_int, TST_int128, TST_half, // OpenCL half, ARM NEON __fp16 TST_Float16, // C11 extension ISO/IEC TS 18661-3 + TST_Accum, // ISO/IEC JTC1 SC22 WG14 N1169 Extension + TST_Fract, TST_float, TST_double, TST_float128, @@ -80,7 +83,7 @@ namespace clang { TST_error // erroneous type }; - /// \brief Structure that packs information about the type specifiers that + /// Structure that packs information about the type specifiers that /// were written in a particular type specifier sequence. struct WrittenBuiltinSpecs { static_assert(TST_error < 1 << 6, "Type bitfield not wide enough for TST"); @@ -90,7 +93,7 @@ namespace clang { unsigned ModeAttr : 1; }; - /// \brief A C++ access specifier (public, private, protected), plus the + /// A C++ access specifier (public, private, protected), plus the /// special value "none" which means different things in different contexts. enum AccessSpecifier { AS_public, @@ -99,24 +102,24 @@ namespace clang { AS_none }; - /// \brief The categorization of expression values, currently following the + /// The categorization of expression values, currently following the /// C++11 scheme. enum ExprValueKind { - /// \brief An r-value expression (a pr-value in the C++11 taxonomy) + /// An r-value expression (a pr-value in the C++11 taxonomy) /// produces a temporary value. VK_RValue, - /// \brief An l-value expression is a reference to an object with + /// An l-value expression is a reference to an object with /// independent storage. VK_LValue, - /// \brief An x-value expression is a reference to an object with + /// An x-value expression is a reference to an object with /// independent storage but which can be "moved", i.e. /// efficiently cannibalized for its resources. VK_XValue }; - /// \brief A further classification of the kind of object referenced by an + /// A further classification of the kind of object referenced by an /// l-value or x-value. enum ExprObjectKind { /// An ordinary object is located at an address in memory. @@ -138,7 +141,7 @@ namespace clang { OK_ObjCSubscript }; - /// \brief Describes the kind of template specialization that a + /// Describes the kind of template specialization that a /// particular template specialization declaration represents. enum TemplateSpecializationKind { /// This template specialization was formed from a template-id but @@ -161,14 +164,14 @@ namespace clang { TSK_ExplicitInstantiationDefinition }; - /// \brief Determine whether this template specialization kind refers + /// Determine whether this template specialization kind refers /// to an instantiation of an entity (as opposed to a non-template or /// an explicit specialization). inline bool isTemplateInstantiation(TemplateSpecializationKind Kind) { return Kind != TSK_Undeclared && Kind != TSK_ExplicitSpecialization; } - /// \brief True if this template specialization kind is an explicit + /// True if this template specialization kind is an explicit /// specialization, explicit instantiation declaration, or explicit /// instantiation definition. inline bool isTemplateExplicitInstantiationOrSpecialization( @@ -186,7 +189,7 @@ namespace clang { llvm_unreachable("bad template specialization kind"); } - /// \brief Thread storage-class-specifier. + /// Thread storage-class-specifier. enum ThreadStorageClassSpecifier { TSCS_unspecified, /// GNU __thread. @@ -199,7 +202,7 @@ namespace clang { TSCS__Thread_local }; - /// \brief Storage classes. + /// Storage classes. enum StorageClass { // These are legal on both functions and variables. SC_None, @@ -212,24 +215,24 @@ namespace clang { SC_Register }; - /// \brief Checks whether the given storage class is legal for functions. + /// Checks whether the given storage class is legal for functions. inline bool isLegalForFunction(StorageClass SC) { return SC <= SC_PrivateExtern; } - /// \brief Checks whether the given storage class is legal for variables. + /// Checks whether the given storage class is legal for variables. inline bool isLegalForVariable(StorageClass SC) { return true; } - /// \brief In-class initialization styles for non-static data members. + /// In-class initialization styles for non-static data members. enum InClassInitStyle { ICIS_NoInit, ///< No in-class initializer. ICIS_CopyInit, ///< Copy initialization. ICIS_ListInit ///< Direct list-initialization. }; - /// \brief CallingConv - Specifies the calling convention that a function uses. + /// CallingConv - Specifies the calling convention that a function uses. enum CallingConv { CC_C, // __attribute__((cdecl)) CC_X86StdCall, // __attribute__((stdcall)) @@ -250,7 +253,7 @@ namespace clang { CC_PreserveAll, // __attribute__((preserve_all)) }; - /// \brief Checks whether the given calling convention supports variadic + /// Checks whether the given calling convention supports variadic /// calls. Unprototyped calls also use the variadic call rules. inline bool supportsVariadicCall(CallingConv CC) { switch (CC) { @@ -269,7 +272,7 @@ namespace clang { } } - /// \brief The storage duration for an object (per C++ [basic.stc]). + /// The storage duration for an object (per C++ [basic.stc]). enum StorageDuration { SD_FullExpression, ///< Full-expression storage duration (for temporaries). SD_Automatic, ///< Automatic storage duration (most local variables). @@ -291,11 +294,17 @@ namespace clang { Unspecified }; + /// Return true if \p L has a weaker nullability annotation than \p R. The + /// ordering is: Unspecified < Nullable < NonNull. + inline bool hasWeakerNullability(NullabilityKind L, NullabilityKind R) { + return uint8_t(L) > uint8_t(R); + } + /// Retrieve the spelling of the given nullability kind. llvm::StringRef getNullabilitySpelling(NullabilityKind kind, bool isContextSensitive = false); - /// \brief Kinds of parameter ABI. + /// Kinds of parameter ABI. enum class ParameterABI { /// This parameter uses ordinary ABI rules for its type. Ordinary, diff --git a/include/clang/Basic/Stack.h b/include/clang/Basic/Stack.h new file mode 100644 index 0000000000000..15a37c6d5949f --- /dev/null +++ b/include/clang/Basic/Stack.h @@ -0,0 +1,27 @@ +//===--- Stack.h - Utilities for dealing with stack space -------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +/// +/// \file +/// Defines utilities for dealing with stack allocation and stack space. +/// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_STACK_H +#define LLVM_CLANG_BASIC_STACK_H + +#include <cstddef> + +namespace clang { + /// The amount of stack space that Clang would like to be provided with. + /// If less than this much is available, we may be unable to reach our + /// template instantiation depth limit and other similar limits. + constexpr size_t DesiredStackSize = 8 << 20; +} // end namespace clang + +#endif // LLVM_CLANG_BASIC_STACK_H diff --git a/include/clang/Basic/StmtNodes.td b/include/clang/Basic/StmtNodes.td index 0d21845fbf8b1..506da07203385 100644 --- a/include/clang/Basic/StmtNodes.td +++ b/include/clang/Basic/StmtNodes.td @@ -57,6 +57,7 @@ def Expr : Stmt<1>; def PredefinedExpr : DStmt<Expr>; def DeclRefExpr : DStmt<Expr>; def IntegerLiteral : DStmt<Expr>; +def FixedPointLiteral : DStmt<Expr>; def FloatingLiteral : DStmt<Expr>; def ImaginaryLiteral : DStmt<Expr>; def StringLiteral : DStmt<Expr>; diff --git a/include/clang/Basic/SyncScope.h b/include/clang/Basic/SyncScope.h index 09ac0052185af..db4461eda0134 100644 --- a/include/clang/Basic/SyncScope.h +++ b/include/clang/Basic/SyncScope.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Provides definitions for the atomic synchronization scopes. +/// Provides definitions for the atomic synchronization scopes. /// //===----------------------------------------------------------------------===// @@ -22,7 +22,7 @@ namespace clang { -/// \brief Defines synch scope values used internally by clang. +/// Defines synch scope values used internally by clang. /// /// The enum values start from 0 and are contiguous. They are mainly used for /// enumerating all supported synch scope values and mapping them to LLVM @@ -62,36 +62,36 @@ inline llvm::StringRef getAsString(SyncScope S) { llvm_unreachable("Invalid synch scope"); } -/// \brief Defines the kind of atomic scope models. +/// Defines the kind of atomic scope models. enum class AtomicScopeModelKind { None, OpenCL }; -/// \brief Defines the interface for synch scope model. +/// Defines the interface for synch scope model. class AtomicScopeModel { public: virtual ~AtomicScopeModel() {} - /// \brief Maps language specific synch scope values to internal + /// Maps language specific synch scope values to internal /// SyncScope enum. virtual SyncScope map(unsigned S) const = 0; - /// \brief Check if the compile-time constant synch scope value + /// Check if the compile-time constant synch scope value /// is valid. virtual bool isValid(unsigned S) const = 0; - /// \brief Get all possible synch scope values that might be + /// Get all possible synch scope values that might be /// encountered at runtime for the current language. virtual ArrayRef<unsigned> getRuntimeValues() const = 0; - /// \brief If atomic builtin function is called with invalid + /// If atomic builtin function is called with invalid /// synch scope value at runtime, it will fall back to a valid /// synch scope value returned by this function. virtual unsigned getFallBackValue() const = 0; - /// \brief Create an atomic scope model by AtomicScopeModelKind. + /// Create an atomic scope model by AtomicScopeModelKind. /// \return an empty std::unique_ptr for AtomicScopeModelKind::None. static std::unique_ptr<AtomicScopeModel> create(AtomicScopeModelKind K); }; -/// \brief Defines the synch scope model for OpenCL. +/// Defines the synch scope model for OpenCL. class AtomicScopeOpenCLModel : public AtomicScopeModel { public: /// The enum values match the pre-defined macros diff --git a/include/clang/Basic/TargetBuiltins.h b/include/clang/Basic/TargetBuiltins.h index 8f4f5e9a74dd8..75a3811007cc5 100644 --- a/include/clang/Basic/TargetBuiltins.h +++ b/include/clang/Basic/TargetBuiltins.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Enumerates target-specific builtins in their own namespaces within +/// Enumerates target-specific builtins in their own namespaces within /// namespace ::clang. /// //===----------------------------------------------------------------------===// @@ -31,7 +31,7 @@ namespace clang { }; } - /// \brief ARM builtins + /// ARM builtins namespace ARM { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -42,7 +42,7 @@ namespace clang { }; } - /// \brief AArch64 builtins + /// AArch64 builtins namespace AArch64 { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, @@ -53,7 +53,7 @@ namespace clang { }; } - /// \brief PPC builtins + /// PPC builtins namespace PPC { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -63,7 +63,7 @@ namespace clang { }; } - /// \brief NVPTX builtins + /// NVPTX builtins namespace NVPTX { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -73,7 +73,7 @@ namespace clang { }; } - /// \brief AMDGPU builtins + /// AMDGPU builtins namespace AMDGPU { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, @@ -83,7 +83,7 @@ namespace clang { }; } - /// \brief X86 builtins + /// X86 builtins namespace X86 { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, @@ -97,7 +97,7 @@ namespace clang { }; } - /// \brief Flags to identify the types for overloaded Neon builtins. + /// Flags to identify the types for overloaded Neon builtins. /// /// These must be kept in sync with the flags in utils/TableGen/NeonEmitter.h. class NeonTypeFlags { @@ -140,7 +140,7 @@ namespace clang { bool isQuad() const { return (Flags & QuadFlag) != 0; } }; - /// \brief Hexagon builtins + /// Hexagon builtins namespace Hexagon { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -150,7 +150,7 @@ namespace clang { }; } - /// \brief Nios2 builtins + /// Nios2 builtins namespace Nios2 { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, @@ -160,7 +160,7 @@ namespace clang { }; } - /// \brief MIPS builtins + /// MIPS builtins namespace Mips { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -170,7 +170,7 @@ namespace clang { }; } - /// \brief XCore builtins + /// XCore builtins namespace XCore { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -180,7 +180,7 @@ namespace clang { }; } - /// \brief Le64 builtins + /// Le64 builtins namespace Le64 { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin - 1, @@ -190,7 +190,7 @@ namespace clang { }; } - /// \brief SystemZ builtins + /// SystemZ builtins namespace SystemZ { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, @@ -200,7 +200,7 @@ namespace clang { }; } - /// \brief WebAssembly builtins + /// WebAssembly builtins namespace WebAssembly { enum { LastTIBuiltin = clang::Builtin::FirstTSBuiltin-1, diff --git a/include/clang/Basic/TargetCXXABI.h b/include/clang/Basic/TargetCXXABI.h index 7fb1f826b0f64..455121a98f338 100644 --- a/include/clang/Basic/TargetCXXABI.h +++ b/include/clang/Basic/TargetCXXABI.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the TargetCXXABI class, which abstracts details of the +/// Defines the TargetCXXABI class, which abstracts details of the /// C++ ABI that we're targeting. /// //===----------------------------------------------------------------------===// @@ -20,10 +20,10 @@ namespace clang { -/// \brief The basic abstraction for the target C++ ABI. +/// The basic abstraction for the target C++ ABI. class TargetCXXABI { public: - /// \brief The basic C++ ABI kind. + /// The basic C++ ABI kind. enum Kind { /// The generic Itanium ABI is the standard ABI of most open-source /// and Unix-like platforms. It is the primary ABI targeted by @@ -131,7 +131,7 @@ public: Kind getKind() const { return TheKind; } - /// \brief Does this ABI generally fall into the Itanium family of ABIs? + /// Does this ABI generally fall into the Itanium family of ABIs? bool isItaniumFamily() const { switch (getKind()) { case GenericAArch64: @@ -150,7 +150,7 @@ public: llvm_unreachable("bad ABI kind"); } - /// \brief Is this ABI an MSVC-compatible ABI? + /// Is this ABI an MSVC-compatible ABI? bool isMicrosoft() const { switch (getKind()) { case GenericAArch64: @@ -169,7 +169,7 @@ public: llvm_unreachable("bad ABI kind"); } - /// \brief Are member functions differently aligned? + /// Are member functions differently aligned? /// /// Many Itanium-style C++ ABIs require member functions to be aligned, so /// that a pointer to such a function is guaranteed to have a zero in the @@ -199,13 +199,6 @@ public: llvm_unreachable("bad ABI kind"); } - /// \brief Is the default C++ member function calling convention - /// the same as the default calling convention? - bool isMemberFunctionCCDefault() const { - // Right now, this is always false for Microsoft. - return !isMicrosoft(); - } - /// Are arguments to a call destroyed left to right in the callee? /// This is a fundamental language change, since it implies that objects /// passed by value do *not* live to the end of the full expression. @@ -217,25 +210,25 @@ public: return isMicrosoft(); } - /// \brief Does this ABI have different entrypoints for complete-object + /// Does this ABI have different entrypoints for complete-object /// and base-subobject constructors? bool hasConstructorVariants() const { return isItaniumFamily(); } - /// \brief Does this ABI allow virtual bases to be primary base classes? + /// Does this ABI allow virtual bases to be primary base classes? bool hasPrimaryVBases() const { return isItaniumFamily(); } - /// \brief Does this ABI use key functions? If so, class data such as the + /// Does this ABI use key functions? If so, class data such as the /// vtable is emitted with strong linkage by the TU containing the key /// function. bool hasKeyFunctions() const { return isItaniumFamily(); } - /// \brief Can an out-of-line inline function serve as a key function? + /// Can an out-of-line inline function serve as a key function? /// /// This flag is only useful in ABIs where type data (for example, /// vtables and type_info objects) are emitted only after processing diff --git a/include/clang/Basic/TargetInfo.h b/include/clang/Basic/TargetInfo.h index 6ba58779114f5..ec5c59b239069 100644 --- a/include/clang/Basic/TargetInfo.h +++ b/include/clang/Basic/TargetInfo.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::TargetInfo interface. +/// Defines the clang::TargetInfo interface. /// //===----------------------------------------------------------------------===// @@ -20,7 +20,6 @@ #include "clang/Basic/Specifiers.h" #include "clang/Basic/TargetCXXABI.h" #include "clang/Basic/TargetOptions.h" -#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" @@ -30,6 +29,7 @@ #include "llvm/ADT/Triple.h" #include "llvm/IR/DataLayout.h" #include "llvm/Support/DataTypes.h" +#include "llvm/Support/VersionTuple.h" #include <cassert> #include <string> #include <vector> @@ -49,7 +49,7 @@ class SourceManager; namespace Builtin { struct Info; } -/// \brief Exposes information about the current target. +/// Exposes information about the current target. /// class TargetInfo : public RefCountedBase<TargetInfo> { std::shared_ptr<TargetOptions> TargetOpts; @@ -61,6 +61,8 @@ protected: bool TLSSupported; bool VLASupported; bool NoAsmVariants; // True if {|} are normal characters. + bool HasLegalHalfType; // True if the backend supports operations on the half + // LLVM IR type. bool HasFloat128; unsigned char PointerWidth, PointerAlign; unsigned char BoolWidth, BoolAlign; @@ -72,6 +74,33 @@ protected: unsigned char LargeArrayMinWidth, LargeArrayAlign; unsigned char LongWidth, LongAlign; unsigned char LongLongWidth, LongLongAlign; + + // Fixed point bit widths + unsigned char ShortAccumWidth, ShortAccumAlign; + unsigned char AccumWidth, AccumAlign; + unsigned char LongAccumWidth, LongAccumAlign; + unsigned char ShortFractWidth, ShortFractAlign; + unsigned char FractWidth, FractAlign; + unsigned char LongFractWidth, LongFractAlign; + + // If true, unsigned fixed point types have the same number of fractional bits + // as their signed counterparts, forcing the unsigned types to have one extra + // bit of padding. Otherwise, unsigned fixed point types have + // one more fractional bit than its corresponding signed type. This is false + // by default. + bool PaddingOnUnsignedFixedPoint; + + // Fixed point integral and fractional bit sizes + // Saturated types share the same integral/fractional bits as their + // corresponding unsaturated types. + // For simplicity, the fractional bits in a _Fract type will be one less the + // width of that _Fract type. This leaves all signed _Fract types having no + // padding and unsigned _Fract types will only have 1 bit of padding after the + // sign if PaddingOnUnsignedFixedPoint is set. + unsigned char ShortAccumScale; + unsigned char AccumScale; + unsigned char LongAccumScale; + unsigned char SuitableAlign; unsigned char DefaultAlignForAttributeAligned; unsigned char MinGlobalAlign; @@ -107,7 +136,7 @@ protected: } public: - /// \brief Construct a target for the given options. + /// Construct a target for the given options. /// /// \param Opts - The options to use to initialize the target. The target may /// modify the options to canonicalize the target feature information to match @@ -118,7 +147,7 @@ public: virtual ~TargetInfo(); - /// \brief Retrieve the target options. + /// Retrieve the target options. TargetOptions &getTargetOpts() const { assert(TargetOpts && "Missing target options"); return *TargetOpts; @@ -147,7 +176,7 @@ public: Float128 }; - /// \brief The different kinds of __builtin_va_list types defined by + /// The different kinds of __builtin_va_list types defined by /// the target implementation. enum BuiltinVaListKind { /// typedef char* __builtin_va_list; @@ -193,7 +222,7 @@ protected: WIntType, Char16Type, Char32Type, Int64Type, SigAtomicType, ProcessIDType; - /// \brief Whether Objective-C's built-in boolean type should be signed char. + /// Whether Objective-C's built-in boolean type should be signed char. /// /// Otherwise, when this flag is not set, the normal built-in boolean type is /// used. @@ -206,7 +235,7 @@ protected: /// boundary. unsigned UseBitFieldTypeAlignment : 1; - /// \brief Whether zero length bitfields (e.g., int : 0;) force alignment of + /// Whether zero length bitfields (e.g., int : 0;) force alignment of /// the next bitfield. /// /// If the alignment of the zero length bitfield is greater than the member @@ -214,14 +243,14 @@ protected: /// zero-length bitfield. unsigned UseZeroLengthBitfieldAlignment : 1; - /// \brief Whether explicit bit field alignment attributes are honored. + /// Whether explicit bit field alignment attributes are honored. unsigned UseExplicitBitFieldAlignment : 1; /// If non-zero, specifies a fixed alignment value for bitfields that follow /// zero length bitfield, regardless of the zero length bitfield type. unsigned ZeroLengthBitfieldBoundary; - /// \brief Specify if mangling based on address space map should be used or + /// Specify if mangling based on address space map should be used or /// not for language specific address spaces bool UseAddrSpaceMapMangling; @@ -283,30 +312,30 @@ public: } } - /// \brief Return the width (in bits) of the specified integer type enum. + /// Return the width (in bits) of the specified integer type enum. /// /// For example, SignedInt -> getIntWidth(). unsigned getTypeWidth(IntType T) const; - /// \brief Return integer type with specified width. + /// Return integer type with specified width. virtual IntType getIntTypeByWidth(unsigned BitWidth, bool IsSigned) const; - /// \brief Return the smallest integer type with at least the specified width. + /// Return the smallest integer type with at least the specified width. virtual IntType getLeastIntTypeByWidth(unsigned BitWidth, bool IsSigned) const; - /// \brief Return floating point type with specified width. + /// Return floating point type with specified width. RealType getRealTypeByWidth(unsigned BitWidth) const; - /// \brief Return the alignment (in bits) of the specified integer type enum. + /// Return the alignment (in bits) of the specified integer type enum. /// /// For example, SignedInt -> getIntAlign(). unsigned getTypeAlign(IntType T) const; - /// \brief Returns true if the type is signed; false otherwise. + /// Returns true if the type is signed; false otherwise. static bool isTypeSigned(IntType T); - /// \brief Return the width of pointers on this target, for the + /// Return the width of pointers on this target, for the /// specified address space. uint64_t getPointerWidth(unsigned AddrSpace) const { return AddrSpace == 0 ? PointerWidth : getPointerWidthV(AddrSpace); @@ -315,29 +344,29 @@ public: return AddrSpace == 0 ? PointerAlign : getPointerAlignV(AddrSpace); } - /// \brief Return the maximum width of pointers on this target. + /// Return the maximum width of pointers on this target. virtual uint64_t getMaxPointerWidth() const { return PointerWidth; } - /// \brief Get integer value for null pointer. + /// Get integer value for null pointer. /// \param AddrSpace address space of pointee in source language. virtual uint64_t getNullPointerValue(LangAS AddrSpace) const { return 0; } - /// \brief Return the size of '_Bool' and C++ 'bool' for this target, in bits. + /// Return the size of '_Bool' and C++ 'bool' for this target, in bits. unsigned getBoolWidth() const { return BoolWidth; } - /// \brief Return the alignment of '_Bool' and C++ 'bool' for this target. + /// Return the alignment of '_Bool' and C++ 'bool' for this target. unsigned getBoolAlign() const { return BoolAlign; } unsigned getCharWidth() const { return 8; } // FIXME unsigned getCharAlign() const { return 8; } // FIXME - /// \brief Return the size of 'signed short' and 'unsigned short' for this + /// Return the size of 'signed short' and 'unsigned short' for this /// target, in bits. unsigned getShortWidth() const { return 16; } // FIXME - /// \brief Return the alignment of 'signed short' and 'unsigned short' for + /// Return the alignment of 'signed short' and 'unsigned short' for /// this target. unsigned getShortAlign() const { return 16; } // FIXME @@ -356,19 +385,135 @@ public: unsigned getLongLongWidth() const { return LongLongWidth; } unsigned getLongLongAlign() const { return LongLongAlign; } - /// \brief Determine whether the __int128 type is supported on this target. + /// getShortAccumWidth/Align - Return the size of 'signed short _Accum' and + /// 'unsigned short _Accum' for this target, in bits. + unsigned getShortAccumWidth() const { return ShortAccumWidth; } + unsigned getShortAccumAlign() const { return ShortAccumAlign; } + + /// getAccumWidth/Align - Return the size of 'signed _Accum' and + /// 'unsigned _Accum' for this target, in bits. + unsigned getAccumWidth() const { return AccumWidth; } + unsigned getAccumAlign() const { return AccumAlign; } + + /// getLongAccumWidth/Align - Return the size of 'signed long _Accum' and + /// 'unsigned long _Accum' for this target, in bits. + unsigned getLongAccumWidth() const { return LongAccumWidth; } + unsigned getLongAccumAlign() const { return LongAccumAlign; } + + /// getShortFractWidth/Align - Return the size of 'signed short _Fract' and + /// 'unsigned short _Fract' for this target, in bits. + unsigned getShortFractWidth() const { return ShortFractWidth; } + unsigned getShortFractAlign() const { return ShortFractAlign; } + + /// getFractWidth/Align - Return the size of 'signed _Fract' and + /// 'unsigned _Fract' for this target, in bits. + unsigned getFractWidth() const { return FractWidth; } + unsigned getFractAlign() const { return FractAlign; } + + /// getLongFractWidth/Align - Return the size of 'signed long _Fract' and + /// 'unsigned long _Fract' for this target, in bits. + unsigned getLongFractWidth() const { return LongFractWidth; } + unsigned getLongFractAlign() const { return LongFractAlign; } + + /// getShortAccumScale/IBits - Return the number of fractional/integral bits + /// in a 'signed short _Accum' type. + unsigned getShortAccumScale() const { return ShortAccumScale; } + unsigned getShortAccumIBits() const { + return ShortAccumWidth - ShortAccumScale - 1; + } + + /// getAccumScale/IBits - Return the number of fractional/integral bits + /// in a 'signed _Accum' type. + unsigned getAccumScale() const { return AccumScale; } + unsigned getAccumIBits() const { return AccumWidth - AccumScale - 1; } + + /// getLongAccumScale/IBits - Return the number of fractional/integral bits + /// in a 'signed long _Accum' type. + unsigned getLongAccumScale() const { return LongAccumScale; } + unsigned getLongAccumIBits() const { + return LongAccumWidth - LongAccumScale - 1; + } + + /// getUnsignedShortAccumScale/IBits - Return the number of + /// fractional/integral bits in a 'unsigned short _Accum' type. + unsigned getUnsignedShortAccumScale() const { + return PaddingOnUnsignedFixedPoint ? ShortAccumScale : ShortAccumScale + 1; + } + unsigned getUnsignedShortAccumIBits() const { + return PaddingOnUnsignedFixedPoint + ? getShortAccumIBits() + : ShortAccumWidth - getUnsignedShortAccumScale(); + } + + /// getUnsignedAccumScale/IBits - Return the number of fractional/integral + /// bits in a 'unsigned _Accum' type. + unsigned getUnsignedAccumScale() const { + return PaddingOnUnsignedFixedPoint ? AccumScale : AccumScale + 1; + } + unsigned getUnsignedAccumIBits() const { + return PaddingOnUnsignedFixedPoint ? getAccumIBits() + : AccumWidth - getUnsignedAccumScale(); + } + + /// getUnsignedLongAccumScale/IBits - Return the number of fractional/integral + /// bits in a 'unsigned long _Accum' type. + unsigned getUnsignedLongAccumScale() const { + return PaddingOnUnsignedFixedPoint ? LongAccumScale : LongAccumScale + 1; + } + unsigned getUnsignedLongAccumIBits() const { + return PaddingOnUnsignedFixedPoint + ? getLongAccumIBits() + : LongAccumWidth - getUnsignedLongAccumScale(); + } + + /// getShortFractScale - Return the number of fractional bits + /// in a 'signed short _Fract' type. + unsigned getShortFractScale() const { return ShortFractWidth - 1; } + + /// getFractScale - Return the number of fractional bits + /// in a 'signed _Fract' type. + unsigned getFractScale() const { return FractWidth - 1; } + + /// getLongFractScale - Return the number of fractional bits + /// in a 'signed long _Fract' type. + unsigned getLongFractScale() const { return LongFractWidth - 1; } + + /// getUnsignedShortFractScale - Return the number of fractional bits + /// in a 'unsigned short _Fract' type. + unsigned getUnsignedShortFractScale() const { + return PaddingOnUnsignedFixedPoint ? getShortFractScale() + : getShortFractScale() + 1; + } + + /// getUnsignedFractScale - Return the number of fractional bits + /// in a 'unsigned _Fract' type. + unsigned getUnsignedFractScale() const { + return PaddingOnUnsignedFixedPoint ? getFractScale() : getFractScale() + 1; + } + + /// getUnsignedLongFractScale - Return the number of fractional bits + /// in a 'unsigned long _Fract' type. + unsigned getUnsignedLongFractScale() const { + return PaddingOnUnsignedFixedPoint ? getLongFractScale() + : getLongFractScale() + 1; + } + + /// Determine whether the __int128 type is supported on this target. virtual bool hasInt128Type() const { - return getPointerWidth(0) >= 64; + return (getPointerWidth(0) >= 64) || getTargetOpts().ForceEnableInt128; } // FIXME - /// \brief Determine whether the __float128 type is supported on this target. + /// Determine whether _Float16 is supported on this target. + virtual bool hasLegalHalfType() const { return HasLegalHalfType; } + + /// Determine whether the __float128 type is supported on this target. virtual bool hasFloat128Type() const { return HasFloat128; } - /// \brief Return the alignment that is suitable for storing any + /// Return the alignment that is suitable for storing any /// object with a fundamental alignment requirement. unsigned getSuitableAlign() const { return SuitableAlign; } - /// \brief Return the default alignment for __attribute__((aligned)) on + /// Return the default alignment for __attribute__((aligned)) on /// this target, to be used if no alignment value is specified. unsigned getDefaultAlignForAttributeAligned() const { return DefaultAlignForAttributeAligned; @@ -431,11 +576,11 @@ public: return *Float128Format; } - /// \brief Return true if the 'long double' type should be mangled like + /// Return true if the 'long double' type should be mangled like /// __float128. virtual bool useFloat128ManglingForLongDouble() const { return false; } - /// \brief Return the value for the C99 FLT_EVAL_METHOD macro. + /// Return the value for the C99 FLT_EVAL_METHOD macro. virtual unsigned getFloatEvalMethod() const { return 0; } // getLargeArrayMinWidth/Align - Return the minimum array size that is @@ -443,16 +588,16 @@ public: unsigned getLargeArrayMinWidth() const { return LargeArrayMinWidth; } unsigned getLargeArrayAlign() const { return LargeArrayAlign; } - /// \brief Return the maximum width lock-free atomic operation which will + /// Return the maximum width lock-free atomic operation which will /// ever be supported for the given target unsigned getMaxAtomicPromoteWidth() const { return MaxAtomicPromoteWidth; } - /// \brief Return the maximum width lock-free atomic operation which can be + /// 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 Set the maximum inline or promote width lock-free atomic operation + /// Set the maximum inline or promote width lock-free atomic operation /// for the given target. virtual void setMaxAtomicWidth() {} - /// \brief Returns true if the given target supports lock-free atomic + /// 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 { @@ -462,14 +607,14 @@ public: llvm::isPowerOf2_64(AtomicSizeInBits / getCharWidth())); } - /// \brief Return the maximum vector alignment supported for the given target. + /// Return the maximum vector alignment supported for the given target. unsigned getMaxVectorAlign() const { return MaxVectorAlign; } - /// \brief Return default simd alignment for the given target. Generally, this + /// Return default simd alignment for the given target. Generally, this /// value is type-specific, but this alignment can be used for most of the /// types for the given target. unsigned getSimdDefaultAlign() const { return SimdDefaultAlign; } - /// \brief Return the size of intmax_t and uintmax_t for this target, in bits. + /// Return the size of intmax_t and uintmax_t for this target, in bits. unsigned getIntMaxTWidth() const { return getTypeWidth(IntMaxType); } @@ -477,7 +622,7 @@ public: // Return the size of unwind_word for this target. virtual unsigned getUnwindWordWidth() const { return getPointerWidth(0); } - /// \brief Return the "preferred" register width on this target. + /// Return the "preferred" register width on this target. virtual unsigned getRegisterWidth() const { // Currently we assume the register width on the target matches the pointer // width, we can introduce a new variable for this if/when some target wants @@ -485,12 +630,12 @@ public: return PointerWidth; } - /// \brief Returns the name of the mcount instrumentation function. + /// Returns the name of the mcount instrumentation function. const char *getMCountName() const { return MCountName; } - /// \brief Check if the Objective-C built-in boolean type should be signed + /// Check if the Objective-C built-in boolean type should be signed /// char. /// /// Otherwise, if this returns false, the normal built-in boolean type @@ -502,58 +647,58 @@ public: UseSignedCharForObjCBool = false; } - /// \brief Check whether the alignment of bit-field types is respected + /// Check whether the alignment of bit-field types is respected /// when laying out structures. bool useBitFieldTypeAlignment() const { return UseBitFieldTypeAlignment; } - /// \brief Check whether zero length bitfields should force alignment of + /// Check whether zero length bitfields should force alignment of /// the next member. bool useZeroLengthBitfieldAlignment() const { return UseZeroLengthBitfieldAlignment; } - /// \brief Get the fixed alignment value in bits for a member that follows + /// Get the fixed alignment value in bits for a member that follows /// a zero length bitfield. unsigned getZeroLengthBitfieldBoundary() const { return ZeroLengthBitfieldBoundary; } - /// \brief Check whether explicit bitfield alignment attributes should be + /// Check whether explicit bitfield alignment attributes should be // honored, as in "__attribute__((aligned(2))) int b : 1;". bool useExplicitBitFieldAlignment() const { return UseExplicitBitFieldAlignment; } - /// \brief Check whether this target support '\#pragma options align=mac68k'. + /// Check whether this target support '\#pragma options align=mac68k'. bool hasAlignMac68kSupport() const { return HasAlignMac68kSupport; } - /// \brief Return the user string for the specified integer type enum. + /// Return the user string for the specified integer type enum. /// /// For example, SignedShort -> "short". static const char *getTypeName(IntType T); - /// \brief Return the constant suffix for the specified integer type enum. + /// Return the constant suffix for the specified integer type enum. /// /// For example, SignedLong -> "L". const char *getTypeConstantSuffix(IntType T) const; - /// \brief Return the printf format modifier for the specified + /// Return the printf format modifier for the specified /// integer type enum. /// /// For example, SignedLong -> "l". static const char *getTypeFormatModifier(IntType T); - /// \brief Check whether the given real type should use the "fpret" flavor of + /// Check whether the given real type should use the "fpret" flavor of /// Objective-C message passing on this target. bool useObjCFPRetForRealType(RealType T) const { return RealTypeUsesObjCFPRet & (1 << T); } - /// \brief Check whether _Complex long double should use the "fp2ret" flavor + /// Check whether _Complex long double should use the "fp2ret" flavor /// of Objective-C message passing on this target. bool useObjCFP2RetForComplexLongDouble() const { return ComplexLongDoubleUsesFP2Ret; @@ -567,7 +712,7 @@ public: return true; } - /// \brief Specify if mangling based on address space map should be used or + /// Specify if mangling based on address space map should be used or /// not for language specific address spaces bool useAddressSpaceMapMangling() const { return UseAddrSpaceMapMangling; @@ -575,7 +720,7 @@ public: ///===---- Other target property query methods --------------------------===// - /// \brief Appends the target-specific \#define values for this + /// Appends the target-specific \#define values for this /// target set to the specified buffer. virtual void getTargetDefines(const LangOptions &Opts, MacroBuilder &Builder) const = 0; @@ -593,7 +738,7 @@ public: /// idea to avoid optimizing based on that undef behavior. virtual bool isCLZForZeroUndef() const { return true; } - /// \brief Returns the kind of __builtin_va_list type that should be used + /// Returns the kind of __builtin_va_list type that should be used /// with this target. virtual BuiltinVaListKind getBuiltinVaListKind() const = 0; @@ -604,28 +749,34 @@ public: /// Returns true for RenderScript. bool isRenderScriptTarget() const { return IsRenderScriptTarget; } - /// \brief Returns whether the passed in string is a valid clobber in an + /// Returns whether the passed in string is a valid clobber in an /// inline asm statement. /// /// This is used by Sema. bool isValidClobber(StringRef Name) const; - /// \brief Returns whether the passed in string is a valid register name + /// Returns whether the passed in string is a valid register name /// according to GCC. /// /// This is used by Sema for inline asm statements. - bool isValidGCCRegisterName(StringRef Name) const; + virtual bool isValidGCCRegisterName(StringRef Name) const; - /// \brief Returns the "normalized" GCC register name. + /// Returns the "normalized" GCC register name. /// /// ReturnCannonical true will return the register name without any additions /// such as "{}" or "%" in it's canonical form, for example: /// ReturnCanonical = true and Name = "rax", will return "ax". StringRef getNormalizedGCCRegisterName(StringRef Name, bool ReturnCanonical = false) const; - - virtual StringRef getConstraintRegister(const StringRef &Constraint, - const StringRef &Expression) const { + + /// Extracts a register from the passed constraint (if it is a + /// single-register constraint) and the asm label expression related to a + /// variable in the input or output list of an inline asm statement. + /// + /// This function is used by Sema in order to diagnose conflicts between + /// the clobber list and the input/output lists. + virtual StringRef getConstraintRegister(StringRef Constraint, + StringRef Expression) const { return ""; } @@ -663,11 +814,11 @@ public: bool allowsRegister() const { return (Flags & CI_AllowsRegister) != 0; } bool allowsMemory() const { return (Flags & CI_AllowsMemory) != 0; } - /// \brief Return true if this output operand has a matching + /// Return true if this output operand has a matching /// (tied) input operand. bool hasMatchingInput() const { return (Flags & CI_HasMatchingInput) != 0; } - /// \brief Return true if this input operand is a matching + /// Return true if this input operand is a matching /// constraint that ties it to an output operand. /// /// If this returns true then getTiedOperand will indicate which output @@ -711,7 +862,7 @@ public: ImmRange.Max = INT_MAX; } - /// \brief Indicate that this is an input operand that is tied to + /// Indicate that this is an input operand that is tied to /// the specified output operand. /// /// Copy over the various constraint information from the output. @@ -723,7 +874,7 @@ public: } }; - /// \brief Validate register name used for global register variables. + /// Validate register name used for global register variables. /// /// This function returns true if the register passed in RegName can be used /// for global register variables on this target. In addition, it returns @@ -777,16 +928,16 @@ public: return std::string(1, *Constraint); } - /// \brief Returns a string of target-specific clobbers, in LLVM format. + /// Returns a string of target-specific clobbers, in LLVM format. virtual const char *getClobbers() const = 0; - /// \brief Returns true if NaN encoding is IEEE 754-2008. + /// Returns true if NaN encoding is IEEE 754-2008. /// Only MIPS allows a different encoding. virtual bool isNan2008() const { return true; } - /// \brief Returns the target triple of the primary target. + /// Returns the target triple of the primary target. const llvm::Triple &getTriple() const { return Triple; } @@ -806,7 +957,7 @@ public: const unsigned RegNum; }; - /// \brief Does this target support "protected" visibility? + /// Does this target support "protected" visibility? /// /// Any target which dynamic libraries will naturally support /// something like "default" (meaning that the symbol is visible @@ -818,7 +969,7 @@ public: /// either; the entire thing is pretty badly mangled. virtual bool hasProtectedVisibility() const { return true; } - /// \brief An optional hook that targets can implement to perform semantic + /// An optional hook that targets can implement to perform semantic /// checking on attribute((section("foo"))) specifiers. /// /// In this case, "foo" is passed in to be checked. If the section @@ -833,18 +984,18 @@ public: return ""; } - /// \brief Set forced language options. + /// Set forced language options. /// /// Apply changes to the target information with respect to certain /// language options which change the target configuration and adjust /// the language based on the target options where applicable. virtual void adjust(LangOptions &Opts); - /// \brief Adjust target options based on codegen options. + /// Adjust target options based on codegen options. virtual void adjustTargetOptions(const CodeGenOptions &CGOpts, TargetOptions &TargetOpts) const {} - /// \brief Initialize the map with the default set of target features for the + /// Initialize the map with the default set of target features for the /// CPU this should include all legal feature strings on the target. /// /// \return False on error (invalid features). @@ -852,41 +1003,44 @@ public: DiagnosticsEngine &Diags, StringRef CPU, const std::vector<std::string> &FeatureVec) const; - /// \brief Get the ABI currently in use. + /// Get the ABI currently in use. virtual StringRef getABI() const { return StringRef(); } - /// \brief Get the C++ ABI currently in use. + /// Get the C++ ABI currently in use. TargetCXXABI getCXXABI() const { return TheCXXABI; } - /// \brief Target the specified CPU. + /// Target the specified CPU. /// /// \return False on error (invalid CPU name). virtual bool setCPU(const std::string &Name) { return false; } + /// Fill a SmallVectorImpl with the valid values to setCPU. + virtual void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const {} + /// brief Determine whether this TargetInfo supports the given CPU name. virtual bool isValidCPUName(StringRef Name) const { return true; } - /// \brief Use the specified ABI. + /// Use the specified ABI. /// /// \return False on error (invalid ABI name). virtual bool setABI(const std::string &Name) { return false; } - /// \brief Use the specified unit for FP math. + /// Use the specified unit for FP math. /// /// \return False on error (invalid unit name). virtual bool setFPMath(StringRef Name) { return false; } - /// \brief Enable or disable a specific target feature; + /// Enable or disable a specific target feature; /// the feature name must be valid. virtual void setFeatureEnabled(llvm::StringMap<bool> &Features, StringRef Name, @@ -894,12 +1048,12 @@ public: Features[Name] = Enabled; } - /// \brief Determine whether this TargetInfo supports the given feature. + /// Determine whether this TargetInfo supports the given feature. virtual bool isValidFeatureName(StringRef Feature) const { return true; } - /// \brief Perform initialization based on the user configured + /// Perform initialization based on the user configured /// set of features (e.g., +sse4). /// /// The list is guaranteed to have at most one entry per feature. @@ -915,31 +1069,62 @@ public: return true; } - /// \brief Determine whether the given target has the given feature. + /// Determine whether the given target has the given feature. virtual bool hasFeature(StringRef Feature) const { return false; } - // \brief Validate the contents of the __builtin_cpu_supports(const char*) + /// Identify whether this taret supports multiversioning of functions, + /// which requires support for cpu_supports and cpu_is functionality. + virtual bool supportsMultiVersioning() const { return false; } + + // Validate the contents of the __builtin_cpu_supports(const char*) // argument. virtual bool validateCpuSupports(StringRef Name) const { return false; } - // \brief Validate the contents of the __builtin_cpu_is(const char*) + // Return the target-specific priority for features/cpus/vendors so + // that they can be properly sorted for checking. + virtual unsigned multiVersionSortPriority(StringRef Name) const { + return 0; + } + + // Validate the contents of the __builtin_cpu_is(const char*) // argument. virtual bool validateCpuIs(StringRef Name) const { return false; } - // \brief Returns maximal number of args passed in registers. + // Validate a cpu_dispatch/cpu_specific CPU option, which is a different list + // from cpu_is, since it checks via features rather than CPUs directly. + virtual bool validateCPUSpecificCPUDispatch(StringRef Name) const { + return false; + } + + // Get the character to be added for mangling purposes for cpu_specific. + virtual char CPUSpecificManglingCharacter(StringRef Name) const { + llvm_unreachable( + "cpu_specific Multiversioning not implemented on this target"); + } + + // Get a list of the features that make up the CPU option for + // cpu_specific/cpu_dispatch so that it can be passed to llvm as optimization + // options. + virtual void getCPUSpecificCPUDispatchFeatures( + StringRef Name, llvm::SmallVectorImpl<StringRef> &Features) const { + llvm_unreachable( + "cpu_specific Multiversioning not implemented on this target"); + } + + // Returns maximal number of args passed in registers. unsigned getRegParmMax() const { assert(RegParmMax < 7 && "RegParmMax value is larger than AST can handle"); return RegParmMax; } - /// \brief Whether the target supports thread-local storage. + /// Whether the target supports thread-local storage. bool isTLSSupported() const { return TLSSupported; } - /// \brief Return the maximum alignment (in bits) of a TLS variable + /// Return the maximum alignment (in bits) of a TLS variable /// /// Gets the maximum alignment (in bits) of a TLS variable on this target. /// Returns zero if there is no such constraint. @@ -947,17 +1132,17 @@ public: return MaxTLSAlign; } - /// \brief Whether target supports variable-length arrays. + /// Whether target supports variable-length arrays. bool isVLASupported() const { return VLASupported; } - /// \brief Whether the target supports SEH __try. + /// Whether the target supports SEH __try. bool isSEHTrySupported() const { return getTriple().isOSWindows() && (getTriple().getArch() == llvm::Triple::x86 || getTriple().getArch() == llvm::Triple::x86_64); } - /// \brief Return true if {|} are normal characters in the asm string. + /// Return true if {|} are normal characters in the asm string. /// /// If this returns false (the default), then {abc|xyz} is syntax /// that says that when compiling for asm variant #0, "abc" should be @@ -967,7 +1152,7 @@ public: return NoAsmVariants; } - /// \brief Return the register number that __builtin_eh_return_regno would + /// Return the register number that __builtin_eh_return_regno would /// return with the specified argument. /// This corresponds with TargetLowering's getExceptionPointerRegister /// and getExceptionSelectorRegister in the backend. @@ -975,14 +1160,14 @@ public: return -1; } - /// \brief Return the section to use for C++ static initialization functions. + /// Return the section to use for C++ static initialization functions. virtual const char *getStaticInitSectionSpecifier() const { return nullptr; } const LangASMap &getAddressSpaceMap() const { return *AddrSpaceMap; } - /// \brief Return an AST address space which can be used opportunistically + /// Return an AST address space which can be used opportunistically /// for constant global memory. It must be possible to convert pointers into /// this address space to LangAS::Default. If no such address space exists, /// this may return None, and such optimizations will be disabled. @@ -990,11 +1175,11 @@ public: return LangAS::Default; } - /// \brief Retrieve the name of the platform as it is used in the + /// Retrieve the name of the platform as it is used in the /// availability attribute. StringRef getPlatformName() const { return PlatformName; } - /// \brief Retrieve the minimum desired version of the platform, to + /// Retrieve the minimum desired version of the platform, to /// which the program should be compiled. VersionTuple getPlatformMinVersion() const { return PlatformMinVersion; } @@ -1007,7 +1192,7 @@ public: CCMT_NonMember }; - /// \brief Gets the default calling convention for the given target and + /// Gets the default calling convention for the given target and /// declaration context. virtual CallingConv getDefaultCallingConv(CallingConvMethodType MT) const { // Not all targets will specify an explicit calling convention that we can @@ -1022,7 +1207,7 @@ public: CCCR_Ignore, }; - /// \brief Determines whether a given calling convention is valid for the + /// Determines whether a given calling convention is valid for the /// target. A calling convention can either be accepted, produce a warning /// and be substituted with the default calling convention, or (someday) /// produce an error (such as using thiscall on a non-instance function). @@ -1035,31 +1220,47 @@ public: } } + enum CallingConvKind { + CCK_Default, + CCK_ClangABI4OrPS4, + CCK_MicrosoftWin64 + }; + + virtual CallingConvKind getCallingConvKind(bool ClangABICompat4) const; + /// Controls if __builtin_longjmp / __builtin_setjmp can be lowered to /// llvm.eh.sjlj.longjmp / llvm.eh.sjlj.setjmp. virtual bool hasSjLjLowering() const { return false; } - /// \brief Whether target allows to overalign ABI-specified preferred alignment + /// Check if the target supports CFProtection branch. + virtual bool + checkCFProtectionBranchSupported(DiagnosticsEngine &Diags) const; + + /// Check if the target supports CFProtection branch. + virtual bool + checkCFProtectionReturnSupported(DiagnosticsEngine &Diags) const; + + /// Whether target allows to overalign ABI-specified preferred alignment virtual bool allowsLargerPreferedTypeAlignment() const { return true; } - /// \brief Set supported OpenCL extensions and optional core features. + /// Set supported OpenCL extensions and optional core features. virtual void setSupportedOpenCLOpts() {} - /// \brief Set supported OpenCL extensions as written on command line + /// Set supported OpenCL extensions as written on command line virtual void setOpenCLExtensionOpts() { for (const auto &Ext : getTargetOpts().OpenCLExtensionsAsWritten) { getTargetOpts().SupportedOpenCLOptions.support(Ext); } } - /// \brief Get supported OpenCL extensions and optional core features. + /// Get supported OpenCL extensions and optional core features. OpenCLOptions &getSupportedOpenCLOpts() { return getTargetOpts().SupportedOpenCLOptions; } - /// \brief Get const supported OpenCL extensions and optional core features. + /// Get const supported OpenCL extensions and optional core features. const OpenCLOptions &getSupportedOpenCLOpts() const { return getTargetOpts().SupportedOpenCLOptions; } @@ -1075,7 +1276,7 @@ public: OCLTK_Sampler, }; - /// \brief Get address space for OpenCL type. + /// Get address space for OpenCL type. virtual LangAS getOpenCLTypeAddrSpace(OpenCLTypeKind TK) const; /// \returns Target specific vtbl ptr address space. @@ -1093,7 +1294,7 @@ public: return None; } - /// \brief Check the target is valid after it is fully initialized. + /// Check the target is valid after it is fully initialized. virtual bool validateTarget(DiagnosticsEngine &Diags) const { return true; } @@ -1113,6 +1314,11 @@ protected: virtual ArrayRef<AddlRegName> getGCCAddlRegNames() const { return None; } + + private: + // Assert the values for the fractional and integral bits for each fixed point + // type follow the restrictions given in clause 6.2.6.3 of N1169. + void CheckFixedPointBits() const; }; } // end namespace clang diff --git a/include/clang/Basic/TargetOptions.h b/include/clang/Basic/TargetOptions.h index 60becfb8ee76e..31a6742879154 100644 --- a/include/clang/Basic/TargetOptions.h +++ b/include/clang/Basic/TargetOptions.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::TargetOptions class. +/// Defines the clang::TargetOptions class. /// //===----------------------------------------------------------------------===// @@ -22,7 +22,7 @@ namespace clang { -/// \brief Options for controlling the target. +/// Options for controlling the target. class TargetOptions { public: /// The name of the target triple to compile for. @@ -47,7 +47,7 @@ public: /// If given, the version string of the linker in use. std::string LinkerVersion; - /// \brief The list of target specific features to enable or disable, as written on the command line. + /// The list of target specific features to enable or disable, as written on the command line. std::vector<std::string> FeaturesAsWritten; /// The list of target specific features to enable or disable -- this should @@ -57,9 +57,16 @@ public: /// Supported OpenCL extensions and optional core features. OpenCLOptions SupportedOpenCLOptions; - /// \brief The list of OpenCL extensions to enable or disable, as written on + /// The list of OpenCL extensions to enable or disable, as written on /// the command line. std::vector<std::string> OpenCLExtensionsAsWritten; + + /// If given, enables support for __int128_t and __uint128_t types. + bool ForceEnableInt128 = false; + + /// \brief If enabled, use 32-bit pointers for accessing const/local/shared + /// address space. + bool NVPTXUseShortPointers = false; }; } // end namespace clang diff --git a/include/clang/Basic/TemplateKinds.h b/include/clang/Basic/TemplateKinds.h index ac99ad185f330..3b68cba73655b 100644 --- a/include/clang/Basic/TemplateKinds.h +++ b/include/clang/Basic/TemplateKinds.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::TemplateNameKind enum. +/// Defines the clang::TemplateNameKind enum. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_TEMPLATEKINDS_H @@ -16,7 +16,7 @@ namespace clang { -/// \brief Specifies the kind of template name that an identifier refers to. +/// Specifies the kind of template name that an identifier refers to. /// Be careful when changing this: this enumeration is used in diagnostics. enum TemplateNameKind { /// The name does not refer to a template. diff --git a/include/clang/Basic/TokenKinds.def b/include/clang/Basic/TokenKinds.def index 6ae8821a834d0..30cb022f1cba5 100644 --- a/include/clang/Basic/TokenKinds.def +++ b/include/clang/Basic/TokenKinds.def @@ -249,8 +249,10 @@ PUNCTUATOR(caretcaret, "^^") // KEYMS - This is a keyword if Microsoft extensions are enabled // KEYNOMS18 - This is a keyword that must never be enabled under // MSVC <= v18. -// KEYOPENCL - This is a keyword in OpenCL -// KEYNOOPENCL - This is a keyword that is not supported in OpenCL +// KEYOPENCLC - This is a keyword in OpenCL C +// KEYOPENCLCXX - This is a keyword in OpenCL C++ +// KEYNOOPENCL - This is a keyword that is not supported in OpenCL C +// nor in OpenCL C++. // KEYALTIVEC - This is a keyword in AltiVec // KEYZVECTOR - This is a keyword for the System z vector extensions, // which are heavily based on AltiVec @@ -260,6 +262,7 @@ PUNCTUATOR(caretcaret, "^^") // BOOLSUPPORT - This is a keyword if 'bool' is a built-in type // HALFSUPPORT - This is a keyword if 'half' is a built-in type // WCHARSUPPORT - This is a keyword if 'wchar_t' is a built-in type +// CHAR8SUPPORT - This is a keyword if 'char8_t' is a built-in type // KEYWORD(auto , KEYALL) KEYWORD(break , KEYALL) @@ -380,9 +383,17 @@ KEYWORD(co_yield , KEYCOROUTINES) MODULES_KEYWORD(module) MODULES_KEYWORD(import) +// C++ char8_t proposal +KEYWORD(char8_t , CHAR8SUPPORT) + // C11 Extension KEYWORD(_Float16 , KEYALL) +// ISO/IEC JTC1 SC22 WG14 N1169 Extension +KEYWORD(_Accum , KEYNOCXX) +KEYWORD(_Fract , KEYNOCXX) +KEYWORD(_Sat , KEYNOCXX) + // GNU Extensions (in impl-reserved namespace) KEYWORD(_Decimal32 , KEYALL) KEYWORD(_Decimal64 , KEYALL) @@ -398,7 +409,6 @@ TYPE_TRAIT_2(__builtin_types_compatible_p, TypeCompatible, KEYNOCXX) KEYWORD(__builtin_va_arg , KEYALL) KEYWORD(__extension__ , KEYALL) KEYWORD(__float128 , KEYALL) -ALIAS("_Float128", __float128 , KEYNOCXX) KEYWORD(__imag , KEYALL) KEYWORD(__int128 , KEYALL) KEYWORD(__label__ , KEYALL) @@ -415,6 +425,7 @@ KEYWORD(typeof , KEYGNU) KEYWORD(__FUNCDNAME__ , KEYMS) KEYWORD(__FUNCSIG__ , KEYMS) KEYWORD(L__FUNCTION__ , KEYMS) +KEYWORD(L__FUNCSIG__ , KEYMS) TYPE_TRAIT_1(__is_interface_class, IsInterfaceClass, KEYMS) TYPE_TRAIT_1(__is_sealed, IsSealed, KEYMS) @@ -464,6 +475,7 @@ TYPE_TRAIT_1(__has_unique_object_representations, TYPE_TRAIT_N(__is_trivially_constructible, IsTriviallyConstructible, KEYCXX) TYPE_TRAIT_1(__is_trivially_copyable, IsTriviallyCopyable, KEYCXX) TYPE_TRAIT_2(__is_trivially_assignable, IsTriviallyAssignable, KEYCXX) +TYPE_TRAIT_2(__reference_binds_to_temporary, ReferenceBindsToTemporary, KEYCXX) KEYWORD(__underlying_type , KEYCXX) // Embarcadero Expression Traits @@ -521,36 +533,36 @@ 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) +KEYWORD(__global , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__local , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__constant , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__private , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__generic , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("global", __global , KEYOPENCLC) +ALIAS("local", __local , KEYOPENCLC) +ALIAS("constant", __constant , KEYOPENCLC) +ALIAS("private", __private , KEYOPENCLC) +ALIAS("generic", __generic , KEYOPENCLC) // OpenCL function qualifiers -KEYWORD(__kernel , KEYOPENCL) -ALIAS("kernel", __kernel , KEYOPENCL) +KEYWORD(__kernel , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("kernel", __kernel , KEYOPENCLC | KEYOPENCLCXX) // OpenCL access qualifiers -KEYWORD(__read_only , KEYOPENCL) -KEYWORD(__write_only , KEYOPENCL) -KEYWORD(__read_write , KEYOPENCL) -ALIAS("read_only", __read_only , KEYOPENCL) -ALIAS("write_only", __write_only , KEYOPENCL) -ALIAS("read_write", __read_write , KEYOPENCL) +KEYWORD(__read_only , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__write_only , KEYOPENCLC | KEYOPENCLCXX) +KEYWORD(__read_write , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("read_only", __read_only , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("write_only", __write_only , KEYOPENCLC | KEYOPENCLCXX) +ALIAS("read_write", __read_write , KEYOPENCLC | KEYOPENCLCXX) // OpenCL builtins -KEYWORD(__builtin_astype , KEYOPENCL) -KEYWORD(vec_step , KEYOPENCL|KEYALTIVEC|KEYZVECTOR) -#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCL) +KEYWORD(__builtin_astype , KEYOPENCLC) +KEYWORD(vec_step , KEYOPENCLC | KEYALTIVEC | KEYZVECTOR) +#define GENERIC_IMAGE_TYPE(ImgType, Id) KEYWORD(ImgType##_t, KEYOPENCLC) #include "clang/Basic/OpenCLImageTypes.def" // OpenMP Type Traits KEYWORD(__builtin_omp_required_simd_align, KEYALL) -KEYWORD(pipe , KEYOPENCL) +KEYWORD(pipe , KEYOPENCLC) // Borland Extensions. KEYWORD(__pascal , KEYALL) diff --git a/include/clang/Basic/TokenKinds.h b/include/clang/Basic/TokenKinds.h index f4ecb3eb306f1..fb4b5252b70bc 100644 --- a/include/clang/Basic/TokenKinds.h +++ b/include/clang/Basic/TokenKinds.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::TokenKind enum and support functions. +/// Defines the clang::TokenKind enum and support functions. /// //===----------------------------------------------------------------------===// @@ -21,14 +21,14 @@ namespace clang { namespace tok { -/// \brief Provides a simple uniform namespace for tokens from all C languages. +/// Provides a simple uniform namespace for tokens from all C languages. enum TokenKind : unsigned short { #define TOK(X) X, #include "clang/Basic/TokenKinds.def" NUM_TOKENS }; -/// \brief Provides a namespace for preprocessor keywords which start with a +/// Provides a namespace for preprocessor keywords which start with a /// '#' at the beginning of the line. enum PPKeywordKind { #define PPKEYWORD(X) pp_##X, @@ -36,7 +36,7 @@ enum PPKeywordKind { NUM_PP_KEYWORDS }; -/// \brief Provides a namespace for Objective-C keywords which start with +/// Provides a namespace for Objective-C keywords which start with /// an '@'. enum ObjCKeywordKind { #define OBJC1_AT_KEYWORD(X) objc_##X, @@ -45,18 +45,18 @@ enum ObjCKeywordKind { NUM_OBJC_KEYWORDS }; -/// \brief Defines the possible values of an on-off-switch (C99 6.10.6p2). +/// Defines the possible values of an on-off-switch (C99 6.10.6p2). enum OnOffSwitch { OOS_ON, OOS_OFF, OOS_DEFAULT }; -/// \brief Determines the name of a token as used within the front end. +/// Determines the name of a token as used within the front end. /// /// The name of a token will be an internal name (such as "l_square") /// and should not be used as part of diagnostic messages. const char *getTokenName(TokenKind Kind) LLVM_READNONE; -/// \brief Determines the spelling of simple punctuation tokens like +/// Determines the spelling of simple punctuation tokens like /// '!' or '%', and returns NULL for literal and annotation tokens. /// /// This routine only retrieves the "simple" spelling of the token, @@ -65,16 +65,16 @@ const char *getTokenName(TokenKind Kind) LLVM_READNONE; /// Preprocessor::getSpelling(). const char *getPunctuatorSpelling(TokenKind Kind) LLVM_READNONE; -/// \brief Determines the spelling of simple keyword and contextual keyword +/// Determines the spelling of simple keyword and contextual keyword /// tokens like 'int' and 'dynamic_cast'. Returns NULL for other token kinds. const char *getKeywordSpelling(TokenKind Kind) LLVM_READNONE; -/// \brief Return true if this is a raw identifier or an identifier kind. +/// Return true if this is a raw identifier or an identifier kind. inline bool isAnyIdentifier(TokenKind K) { return (K == tok::identifier) || (K == tok::raw_identifier); } -/// \brief Return true if this is a C or C++ string-literal (or +/// Return true if this is a C or C++ string-literal (or /// C++11 user-defined-string-literal) token. inline bool isStringLiteral(TokenKind K) { return K == tok::string_literal || K == tok::wide_string_literal || @@ -82,7 +82,7 @@ inline bool isStringLiteral(TokenKind K) { K == tok::utf32_string_literal; } -/// \brief Return true if this is a "literal" kind, like a numeric +/// Return true if this is a "literal" kind, like a numeric /// constant, string, etc. inline bool isLiteral(TokenKind K) { return K == tok::numeric_constant || K == tok::char_constant || @@ -91,7 +91,7 @@ inline bool isLiteral(TokenKind K) { isStringLiteral(K) || K == tok::angle_string_literal; } -/// \brief Return true if this is any of tok::annot_* kinds. +/// Return true if this is any of tok::annot_* kinds. inline bool isAnnotation(TokenKind K) { #define ANNOTATION(NAME) \ if (K == tok::annot_##NAME) \ diff --git a/include/clang/Basic/TypeTraits.h b/include/clang/Basic/TypeTraits.h index 8ecd63f9c3cbb..bdb426834a8cc 100644 --- a/include/clang/Basic/TypeTraits.h +++ b/include/clang/Basic/TypeTraits.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines enumerations for the type traits support. +/// Defines enumerations for the type traits support. /// //===----------------------------------------------------------------------===// @@ -17,7 +17,7 @@ namespace clang { - /// \brief Names for traits that operate specifically on types. + /// Names for traits that operate specifically on types. enum TypeTrait { UTT_HasNothrowAssign, UTT_HasNothrowMoveAssign, @@ -80,19 +80,20 @@ namespace clang { BTT_IsAssignable, BTT_IsNothrowAssignable, BTT_IsTriviallyAssignable, - BTT_Last = BTT_IsTriviallyAssignable, + BTT_ReferenceBindsToTemporary, + BTT_Last = BTT_ReferenceBindsToTemporary, TT_IsConstructible, TT_IsNothrowConstructible, TT_IsTriviallyConstructible }; - /// \brief Names for the array type traits. + /// Names for the array type traits. enum ArrayTypeTrait { ATT_ArrayRank, ATT_ArrayExtent }; - /// \brief Names for the "expression or type" traits. + /// Names for the "expression or type" traits. enum UnaryExprOrTypeTrait { UETT_SizeOf, UETT_AlignOf, diff --git a/include/clang/Basic/Version.h b/include/clang/Basic/Version.h index 57dcf92c3b280..6d625c6ddb80e 100644 --- a/include/clang/Basic/Version.h +++ b/include/clang/Basic/Version.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines version macros and version-related utility functions +/// Defines version macros and version-related utility functions /// for Clang. /// //===----------------------------------------------------------------------===// @@ -20,40 +20,40 @@ #include "llvm/ADT/StringRef.h" namespace clang { - /// \brief Retrieves the repository path (e.g., Subversion path) that + /// Retrieves the repository path (e.g., Subversion path) that /// identifies the particular Clang branch, tag, or trunk from which this /// Clang was built. std::string getClangRepositoryPath(); - /// \brief Retrieves the repository path from which LLVM was built. + /// Retrieves the repository path from which LLVM was built. /// /// This supports LLVM residing in a separate repository from clang. std::string getLLVMRepositoryPath(); - /// \brief Retrieves the repository revision number (or identifer) from which + /// Retrieves the repository revision number (or identifier) from which /// this Clang was built. std::string getClangRevision(); - /// \brief Retrieves the repository revision number (or identifer) from which + /// Retrieves the repository revision number (or identifier) from which /// LLVM was built. /// /// If Clang and LLVM are in the same repository, this returns the same /// string as getClangRevision. std::string getLLVMRevision(); - /// \brief Retrieves the full repository version that is an amalgamation of + /// Retrieves the full repository version that is an amalgamation of /// the information in getClangRepositoryPath() and getClangRevision(). std::string getClangFullRepositoryVersion(); - /// \brief Retrieves a string representing the complete clang version, + /// Retrieves a string representing the complete clang version, /// which includes the clang version number, the repository version, /// and the vendor tag. std::string getClangFullVersion(); - /// \brief Like getClangFullVersion(), but with a custom tool name. + /// Like getClangFullVersion(), but with a custom tool name. std::string getClangToolFullVersion(llvm::StringRef ToolName); - /// \brief Retrieves a string representing the complete clang version suitable + /// Retrieves a string representing the complete clang version suitable /// for use in the CPP __VERSION__ macro, which includes the clang version /// number, the repository version, and the vendor tag. std::string getClangFullCPPVersion(); diff --git a/include/clang/Basic/VersionTuple.h b/include/clang/Basic/VersionTuple.h deleted file mode 100644 index da3b01903ed93..0000000000000 --- a/include/clang/Basic/VersionTuple.h +++ /dev/null @@ -1,168 +0,0 @@ -//===- VersionTuple.h - Version Number Handling -----------------*- 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::VersionTuple class, which represents a version in -/// the form major[.minor[.subminor]]. -/// -//===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_BASIC_VERSIONTUPLE_H -#define LLVM_CLANG_BASIC_VERSIONTUPLE_H - -#include "clang/Basic/LLVM.h" -#include "llvm/ADT/Optional.h" -#include <string> -#include <tuple> - -namespace clang { - -/// \brief Represents a version number in the form major[.minor[.subminor[.build]]]. -class VersionTuple { - unsigned Major : 31; - - unsigned UsesUnderscores : 1; - - unsigned Minor : 31; - unsigned HasMinor : 1; - - unsigned Subminor : 31; - unsigned HasSubminor : 1; - - unsigned Build : 31; - unsigned HasBuild : 1; - -public: - VersionTuple() - : Major(0), UsesUnderscores(false), Minor(0), HasMinor(false), - Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} - - explicit VersionTuple(unsigned Major) - : Major(Major), UsesUnderscores(false), Minor(0), HasMinor(false), - Subminor(0), HasSubminor(false), Build(0), HasBuild(false) {} - - explicit VersionTuple(unsigned Major, unsigned Minor, - bool UsesUnderscores = false) - : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor), - HasMinor(true), Subminor(0), HasSubminor(false), Build(0), - HasBuild(false) {} - - explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, - bool UsesUnderscores = false) - : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor), - HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(0), - HasBuild(false) {} - - explicit VersionTuple(unsigned Major, unsigned Minor, unsigned Subminor, - unsigned Build, bool UsesUnderscores = false) - : Major(Major), UsesUnderscores(UsesUnderscores), Minor(Minor), - HasMinor(true), Subminor(Subminor), HasSubminor(true), Build(Build), - HasBuild(true) {} - - /// \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 && Build == 0; - } - - /// \brief Retrieve the major version number. - unsigned getMajor() const { return Major; } - - /// \brief Retrieve the minor version number, if provided. - Optional<unsigned> getMinor() const { - if (!HasMinor) - return None; - return Minor; - } - - /// \brief Retrieve the subminor version number, if provided. - Optional<unsigned> getSubminor() const { - if (!HasSubminor) - return None; - return Subminor; - } - - /// \brief Retrieve the build version number, if provided. - Optional<unsigned> getBuild() const { - if (!HasBuild) - return None; - return Build; - } - - 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) { - return X.Major == Y.Major && X.Minor == Y.Minor && - X.Subminor == Y.Subminor && X.Build == Y.Build; - } - - /// \brief Determine if two version numbers are not equivalent. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator!=(const VersionTuple &X, const VersionTuple &Y) { - return !(X == Y); - } - - /// \brief Determine whether one version number precedes another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator<(const VersionTuple &X, const VersionTuple &Y) { - return std::tie(X.Major, X.Minor, X.Subminor, X.Build) < - std::tie(Y.Major, Y.Minor, Y.Subminor, Y.Build); - } - - /// \brief Determine whether one version number follows another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator>(const VersionTuple &X, const VersionTuple &Y) { - return Y < X; - } - - /// \brief Determine whether one version number precedes or is - /// equivalent to another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator<=(const VersionTuple &X, const VersionTuple &Y) { - return !(Y < X); - } - - /// \brief Determine whether one version number follows or is - /// equivalent to another. - /// - /// If not provided, minor and subminor version numbers are considered to be - /// zero. - friend bool operator>=(const VersionTuple &X, const VersionTuple &Y) { - return !(X < Y); - } - - /// \brief Retrieve a string representation of the version number. - std::string getAsString() const; - - /// \brief Try to parse the given string as a version number. - /// \returns \c true if the string does not match the regular expression - /// [0-9]+(\.[0-9]+){0,3} - bool tryParse(StringRef string); -}; - -/// \brief Print a version number. -raw_ostream& operator<<(raw_ostream &Out, const VersionTuple &V); - -} // end namespace clang -#endif // LLVM_CLANG_BASIC_VERSIONTUPLE_H diff --git a/include/clang/Basic/VirtualFileSystem.h b/include/clang/Basic/VirtualFileSystem.h index 245452dd12b57..2480b91123c15 100644 --- a/include/clang/Basic/VirtualFileSystem.h +++ b/include/clang/Basic/VirtualFileSystem.h @@ -6,8 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// /// \file -/// \brief Defines the virtual file system interface vfs::FileSystem. +/// Defines the virtual file system interface vfs::FileSystem. +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H @@ -15,6 +17,7 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" @@ -23,8 +26,6 @@ #include "llvm/Support/ErrorOr.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/SourceMgr.h" -#include "llvm/Support/raw_ostream.h" -#include <algorithm> #include <cassert> #include <cstdint> #include <ctime> @@ -39,12 +40,12 @@ namespace llvm { class MemoryBuffer; -} // end namespace llvm +} // namespace llvm namespace clang { namespace vfs { -/// \brief The result of a \p status operation. +/// The result of a \p status operation. class Status { std::string Name; llvm::sys::fs::UniqueID UID; @@ -52,14 +53,14 @@ class Status { uint32_t User; uint32_t Group; uint64_t Size; - llvm::sys::fs::file_type Type; + llvm::sys::fs::file_type Type = llvm::sys::fs::file_type::status_error; llvm::sys::fs::perms Perms; public: - bool IsVFSMapped; // FIXME: remove when files support multiple names + // FIXME: remove when files support multiple names + bool IsVFSMapped = false; -public: - Status() : Type(llvm::sys::fs::file_type::status_error) {} + Status() = default; Status(const llvm::sys::fs::file_status &Status); Status(StringRef Name, llvm::sys::fs::UniqueID UID, llvm::sys::TimePoint<> MTime, uint32_t User, uint32_t Group, @@ -71,7 +72,7 @@ public: static Status copyWithNewName(const llvm::sys::fs::file_status &In, StringRef NewName); - /// \brief Returns the name that should be used for this file or directory. + /// Returns the name that should be used for this file or directory. StringRef getName() const { return Name; } /// @name Status interface from llvm::sys::fs @@ -97,18 +98,18 @@ public: /// @} }; -/// \brief Represents an open file. +/// Represents an open file. class File { public: - /// \brief Destroy the file after closing it (if open). + /// Destroy the file after closing it (if open). /// Sub-classes should generally call close() inside their destructors. We /// cannot do that from the base class, since close is virtual. virtual ~File(); - /// \brief Get the status of the file. + /// Get the status of the file. virtual llvm::ErrorOr<Status> status() = 0; - /// \brief Get the name of the file + /// Get the name of the file virtual llvm::ErrorOr<std::string> getName() { if (auto Status = status()) return Status->getName().str(); @@ -116,32 +117,32 @@ public: return Status.getError(); } - /// \brief Get the contents of the file as a \p MemoryBuffer. + /// Get the contents of the file as a \p MemoryBuffer. 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. + /// Closes the file. virtual std::error_code close() = 0; }; namespace detail { -/// \brief An interface for virtual file systems to provide an iterator over the +/// An interface for virtual file systems to provide an iterator over the /// (non-recursive) contents of a directory. struct DirIterImpl { virtual ~DirIterImpl(); - /// \brief Sets \c CurrentEntry to the next entry in the directory on success, + /// Sets \c CurrentEntry to the next entry in the directory on success, /// or returns a system-defined \c error_code. virtual std::error_code increment() = 0; Status CurrentEntry; }; -} // end namespace detail +} // namespace detail -/// \brief An input iterator over the entries in a virtual path, similar to +/// An input iterator over the entries in a virtual path, similar to /// llvm::sys::fs::directory_iterator. class directory_iterator { std::shared_ptr<detail::DirIterImpl> Impl; // Input iterator semantics on copy @@ -154,10 +155,10 @@ public: Impl.reset(); // Normalize the end iterator to Impl == nullptr. } - /// \brief Construct an 'end' iterator. + /// Construct an 'end' iterator. directory_iterator() = default; - /// \brief Equivalent to operator++, with an error code. + /// Equivalent to operator++, with an error code. directory_iterator &increment(std::error_code &EC) { assert(Impl && "attempting to increment past end"); EC = Impl->increment(); @@ -181,11 +182,11 @@ public: class FileSystem; -/// \brief An input iterator over the recursive contents of a virtual path, +/// An input iterator over the recursive contents of a virtual path, /// similar to llvm::sys::fs::recursive_directory_iterator. class recursive_directory_iterator { - typedef std::stack<directory_iterator, std::vector<directory_iterator>> - IterState; + using IterState = + std::stack<directory_iterator, std::vector<directory_iterator>>; FileSystem *FS; std::shared_ptr<IterState> State; // Input iterator semantics on copy. @@ -193,10 +194,11 @@ class recursive_directory_iterator { public: recursive_directory_iterator(FileSystem &FS, const Twine &Path, std::error_code &EC); - /// \brief Construct an 'end' iterator. + + /// Construct an 'end' iterator. recursive_directory_iterator() = default; - /// \brief Equivalent to operator++, with an error code. + /// Equivalent to operator++, with an error code. recursive_directory_iterator &increment(std::error_code &EC); const Status &operator*() const { return *State->top(); } @@ -209,21 +211,22 @@ public: return !(*this == RHS); } - /// \brief Gets the current level. Starting path is at level 0. + /// Gets the current level. Starting path is at level 0. int level() const { - assert(State->size() && "Cannot get level without any iteration state"); + assert(!State->empty() && "Cannot get level without any iteration state"); return State->size()-1; } }; -/// \brief The virtual file system interface. +/// The virtual file system interface. class FileSystem : public llvm::ThreadSafeRefCountedBase<FileSystem> { public: virtual ~FileSystem(); - /// \brief Get the status of the entry at \p Path, if one exists. + /// 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. + + /// Get a \p File object for the file at \p Path, if one exists. virtual llvm::ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) = 0; @@ -233,7 +236,7 @@ public: getBufferForFile(const Twine &Name, int64_t FileSize = -1, bool RequiresNullTerminator = true, bool IsVolatile = false); - /// \brief Get a directory_iterator for \p Dir. + /// Get a directory_iterator for \p Dir. /// \note The 'end' iterator is directory_iterator(). virtual directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) = 0; @@ -241,9 +244,16 @@ public: /// Set the working directory. This will affect all following operations on /// this file system and may propagate down for nested file systems. virtual std::error_code setCurrentWorkingDirectory(const Twine &Path) = 0; + /// Get the working directory of this file system. virtual llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const = 0; + /// Gets real path of \p Path e.g. collapse all . and .. patterns, resolve + /// symlinks. For real file system, this uses `llvm::sys::fs::real_path`. + /// This returns errc::operation_not_permitted if not implemented by subclass. + virtual std::error_code getRealPath(const Twine &Path, + SmallVectorImpl<char> &Output) const; + /// Check whether a file exists. Provided for convenience. bool exists(const Twine &Path); @@ -261,11 +271,11 @@ public: std::error_code makeAbsolute(SmallVectorImpl<char> &Path) const; }; -/// \brief Gets an \p vfs::FileSystem for the 'real' file system, as seen by +/// Gets an \p vfs::FileSystem for the 'real' file system, as seen by /// the operating system. IntrusiveRefCntPtr<FileSystem> getRealFileSystem(); -/// \brief A file system that allows overlaying one \p AbstractFileSystem on top +/// A file system that allows overlaying one \p AbstractFileSystem on top /// of another. /// /// Consists of a stack of >=1 \p FileSystem objects, which are treated as being @@ -276,14 +286,16 @@ IntrusiveRefCntPtr<FileSystem> getRealFileSystem(); /// that exists in more than one file system, the file in the top-most file /// system overrides the other(s). class OverlayFileSystem : public FileSystem { - typedef SmallVector<IntrusiveRefCntPtr<FileSystem>, 1> FileSystemList; - /// \brief The stack of file systems, implemented as a list in order of + using FileSystemList = SmallVector<IntrusiveRefCntPtr<FileSystem>, 1>; + + /// The stack of file systems, implemented as a list in order of /// their addition. FileSystemList FSList; public: OverlayFileSystem(IntrusiveRefCntPtr<FileSystem> Base); - /// \brief Pushes a file system on top of the stack. + + /// Pushes a file system on top of the stack. void pushOverlay(IntrusiveRefCntPtr<FileSystem> FS); llvm::ErrorOr<Status> status(const Twine &Path) override; @@ -292,22 +304,27 @@ public: directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override; std::error_code setCurrentWorkingDirectory(const Twine &Path) override; + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl<char> &Output) const override; + + using iterator = FileSystemList::reverse_iterator; + using const_iterator = FileSystemList::const_reverse_iterator; - typedef FileSystemList::reverse_iterator iterator; - - /// \brief Get an iterator pointing to the most recently added file system. + /// Get an iterator pointing to the most recently added file system. iterator overlays_begin() { return FSList.rbegin(); } + const_iterator overlays_begin() const { return FSList.rbegin(); } - /// \brief Get an iterator pointing one-past the least recently added file + /// Get an iterator pointing one-past the least recently added file /// system. iterator overlays_end() { return FSList.rend(); } + const_iterator overlays_end() const { return FSList.rend(); } }; namespace detail { class InMemoryDirectory; -} // end namespace detail +} // namespace detail /// An in-memory file system. class InMemoryFileSystem : public FileSystem { @@ -330,6 +347,7 @@ public: Optional<uint32_t> User = None, Optional<uint32_t> Group = None, Optional<llvm::sys::fs::file_type> Type = None, Optional<llvm::sys::fs::perms> Perms = None); + /// Add a buffer to the VFS with a path. The VFS does not own the buffer. /// If present, User, Group, Type and Perms apply to the newly-created file /// or directory. @@ -344,6 +362,7 @@ public: Optional<llvm::sys::fs::perms> Perms = None); std::string toString() const; + /// Return true if this file system normalizes . and .. in paths. bool useNormalizedPaths() const { return UseNormalizedPaths; } @@ -351,16 +370,26 @@ public: llvm::ErrorOr<std::unique_ptr<File>> openFileForRead(const Twine &Path) override; directory_iterator dir_begin(const Twine &Dir, std::error_code &EC) override; + llvm::ErrorOr<std::string> getCurrentWorkingDirectory() const override { return WorkingDirectory; } + /// Canonicalizes \p Path by combining with the current working + /// directory and normalizing the path (e.g. remove dots). If the current + /// working directory is not set, this returns errc::operation_not_permitted. + /// + /// This doesn't resolve symlinks as they are not supported in in-memory file + /// system. + std::error_code getRealPath(const Twine &Path, + SmallVectorImpl<char> &Output) const override; + std::error_code setCurrentWorkingDirectory(const Twine &Path) override; }; -/// \brief Get a globally unique ID for a virtual file or directory. +/// Get a globally unique ID for a virtual file or directory. llvm::sys::fs::UniqueID getNextVirtualUniqueID(); -/// \brief Gets a \p FileSystem for a virtual file system described in YAML +/// Gets a \p FileSystem for a virtual file system described in YAML /// format. IntrusiveRefCntPtr<FileSystem> getVFSFromYAML(std::unique_ptr<llvm::MemoryBuffer> Buffer, @@ -376,7 +405,7 @@ struct YAMLVFSEntry { std::string RPath; }; -/// \brief Collect all pairs of <virtual path, real path> entries from the +/// Collect all pairs of <virtual path, real path> entries from the /// \p YAMLFilePath. This is used by the module dependency collector to forward /// the entries into the reproducer output VFS YAML file. void collectVFSFromYAML( @@ -419,7 +448,7 @@ public: void write(llvm::raw_ostream &OS); }; -} // end namespace vfs -} // end namespace clang +} // namespace vfs +} // namespace clang #endif // LLVM_CLANG_BASIC_VIRTUALFILESYSTEM_H diff --git a/include/clang/Basic/Visibility.h b/include/clang/Basic/Visibility.h index cc839d789e7fd..c5ab62436fe0e 100644 --- a/include/clang/Basic/Visibility.h +++ b/include/clang/Basic/Visibility.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::Visibility enumeration and various utility +/// Defines the clang::Visibility enumeration and various utility /// functions. /// //===----------------------------------------------------------------------===// @@ -16,10 +16,12 @@ #define LLVM_CLANG_BASIC_VISIBILITY_H #include "clang/Basic/Linkage.h" +#include <cassert> +#include <cstdint> namespace clang { -/// \brief Describes the different kinds of visibility that a declaration +/// Describes the different kinds of visibility that a declaration /// may have. /// /// Visibility determines how a declaration interacts with the dynamic diff --git a/include/clang/Basic/X86Target.def b/include/clang/Basic/X86Target.def index 21550fe2dd55f..d2d2540e50054 100644 --- a/include/clang/Basic/X86Target.def +++ b/include/clang/Basic/X86Target.def @@ -12,6 +12,10 @@ // //===----------------------------------------------------------------------===// +#ifndef PROC_WITH_FEAT +#define PROC_WITH_FEAT(ENUM, STRING, IS64BIT, KEYFEATURE) \ + PROC(ENUM, STRING, IS64BIT) +#endif #ifndef PROC #define PROC(ENUM, STRING, IS64BIT) @@ -21,6 +25,18 @@ #define PROC_ALIAS(ENUM, ALIAS) #endif +#ifndef FEATURE +#define FEATURE(ENUM) +#endif + +#ifndef CPU_SPECIFIC +#define CPU_SPECIFIC(NAME, MANGLING, FEATURES) +#endif + +#ifndef CPU_SPECIFIC_ALIAS +#define CPU_SPECIFIC_ALIAS(NEW_NAME, NAME) +#endif + #define PROC_64_BIT true #define PROC_32_BIT false @@ -77,7 +93,7 @@ PROC(Nocona, "nocona", PROC_64_BIT) /// \name Core /// Core microarchitecture based processors. //@{ -PROC(Core2, "core2", PROC_64_BIT) +PROC_WITH_FEAT(Core2, "core2", PROC_64_BIT, FEATURE_SSSE3) /// This enumerator, like Yonah, is a bit odd. It is another /// codename which GCC no longer accepts as an option to -march, but Clang @@ -89,67 +105,74 @@ PROC(Penryn, "penryn", PROC_64_BIT) /// \name Atom /// Atom processors //@{ -PROC(Bonnell, "bonnell", PROC_64_BIT) +PROC_WITH_FEAT(Bonnell, "bonnell", PROC_64_BIT, FEATURE_SSSE3) PROC_ALIAS(Bonnell, "atom") -PROC(Silvermont, "silvermont", PROC_64_BIT) +PROC_WITH_FEAT(Silvermont, "silvermont", PROC_64_BIT, FEATURE_SSE4_2) PROC_ALIAS(Silvermont, "slm") PROC(Goldmont, "goldmont", PROC_64_BIT) +PROC(GoldmontPlus, "goldmont-plus", PROC_64_BIT) + +PROC(Tremont, "tremont", PROC_64_BIT) //@} /// \name Nehalem /// Nehalem microarchitecture based processors. -PROC(Nehalem, "nehalem", PROC_64_BIT) +PROC_WITH_FEAT(Nehalem, "nehalem", PROC_64_BIT, FEATURE_SSE4_2) PROC_ALIAS(Nehalem, "corei7") /// \name Westmere /// Westmere microarchitecture based processors. -PROC(Westmere, "westmere", PROC_64_BIT) +PROC_WITH_FEAT(Westmere, "westmere", PROC_64_BIT, FEATURE_PCLMUL) /// \name Sandy Bridge /// Sandy Bridge microarchitecture based processors. -PROC(SandyBridge, "sandybridge", PROC_64_BIT) +PROC_WITH_FEAT(SandyBridge, "sandybridge", PROC_64_BIT, FEATURE_AVX) PROC_ALIAS(SandyBridge, "corei7-avx") /// \name Ivy Bridge /// Ivy Bridge microarchitecture based processors. -PROC(IvyBridge, "ivybridge", PROC_64_BIT) +PROC_WITH_FEAT(IvyBridge, "ivybridge", PROC_64_BIT, FEATURE_AVX) PROC_ALIAS(IvyBridge, "core-avx-i") /// \name Haswell /// Haswell microarchitecture based processors. -PROC(Haswell, "haswell", PROC_64_BIT) +PROC_WITH_FEAT(Haswell, "haswell", PROC_64_BIT, FEATURE_AVX2) PROC_ALIAS(Haswell, "core-avx2") /// \name Broadwell /// Broadwell microarchitecture based processors. -PROC(Broadwell, "broadwell", PROC_64_BIT) +PROC_WITH_FEAT(Broadwell, "broadwell", PROC_64_BIT, FEATURE_AVX2) /// \name Skylake Client /// Skylake client microarchitecture based processors. -PROC(SkylakeClient, "skylake", PROC_64_BIT) +PROC_WITH_FEAT(SkylakeClient, "skylake", PROC_64_BIT, FEATURE_AVX2) /// \name Skylake Server /// Skylake server microarchitecture based processors. -PROC(SkylakeServer, "skylake-avx512", PROC_64_BIT) +PROC_WITH_FEAT(SkylakeServer, "skylake-avx512", PROC_64_BIT, FEATURE_AVX512F) PROC_ALIAS(SkylakeServer, "skx") /// \name Cannonlake Client /// Cannonlake client microarchitecture based processors. -PROC(Cannonlake, "cannonlake", PROC_64_BIT) +PROC_WITH_FEAT(Cannonlake, "cannonlake", PROC_64_BIT, FEATURE_AVX512VBMI) /// \name Icelake Client /// Icelake client microarchitecture based processors. -PROC(Icelake, "icelake", PROC_64_BIT) +PROC(IcelakeClient, "icelake-client", PROC_64_BIT) + +/// \name Icelake Server +/// Icelake server microarchitecture based processors. +PROC(IcelakeServer, "icelake-server", PROC_64_BIT) /// \name Knights Landing /// Knights Landing processor. -PROC(KNL, "knl", PROC_64_BIT) +PROC_WITH_FEAT(KNL, "knl", PROC_64_BIT, FEATURE_AVX512F) /// \name Knights Mill /// Knights Mill processor. -PROC(KNM, "knm", PROC_64_BIT) +PROC_WITH_FEAT(KNM, "knm", PROC_64_BIT, FEATURE_AVX5124FMAPS) /// \name Lakemont /// Lakemont microarchitecture based processors. @@ -186,30 +209,30 @@ PROC(K8SSE3, "k8-sse3", PROC_64_BIT) PROC_ALIAS(K8SSE3, "athlon64-sse3") PROC_ALIAS(K8SSE3, "opteron-sse3") -PROC(AMDFAM10, "amdfam10", PROC_64_BIT) +PROC_WITH_FEAT(AMDFAM10, "amdfam10", PROC_64_BIT, FEATURE_SSE4_A) PROC_ALIAS(AMDFAM10, "barcelona") //@} /// \name Bobcat /// Bobcat architecture processors. //@{ -PROC(BTVER1, "btver1", PROC_64_BIT) -PROC(BTVER2, "btver2", PROC_64_BIT) +PROC_WITH_FEAT(BTVER1, "btver1", PROC_64_BIT, FEATURE_SSE4_A) +PROC_WITH_FEAT(BTVER2, "btver2", PROC_64_BIT, FEATURE_BMI) //@} /// \name Bulldozer /// Bulldozer architecture processors. //@{ -PROC(BDVER1, "bdver1", PROC_64_BIT) -PROC(BDVER2, "bdver2", PROC_64_BIT) -PROC(BDVER3, "bdver3", PROC_64_BIT) -PROC(BDVER4, "bdver4", PROC_64_BIT) +PROC_WITH_FEAT(BDVER1, "bdver1", PROC_64_BIT, FEATURE_XOP) +PROC_WITH_FEAT(BDVER2, "bdver2", PROC_64_BIT, FEATURE_FMA) +PROC_WITH_FEAT(BDVER3, "bdver3", PROC_64_BIT, FEATURE_FMA) +PROC_WITH_FEAT(BDVER4, "bdver4", PROC_64_BIT, FEATURE_AVX2) //@} /// \name zen /// Zen architecture processors. //@{ -PROC(ZNVER1, "znver1", PROC_64_BIT) +PROC_WITH_FEAT(ZNVER1, "znver1", PROC_64_BIT, FEATURE_AVX2) //@} /// This specification is deprecated and will be removed in the future. @@ -225,8 +248,84 @@ PROC(x86_64, "x86-64", PROC_64_BIT) PROC(Geode, "geode", PROC_32_BIT) //@} - +// List of CPU Supports features in order. These need to remain in the order +// required by attribute 'target' checking. Note that not all are supported/ +// prioritized by GCC, so synchronization with GCC's implementation may require +// changing some existing values. +FEATURE(FEATURE_CMOV) +FEATURE(FEATURE_MMX) +FEATURE(FEATURE_SSE) +FEATURE(FEATURE_SSE2) +FEATURE(FEATURE_SSE3) +FEATURE(FEATURE_SSSE3) +FEATURE(FEATURE_SSE4_A) +FEATURE(FEATURE_SSE4_1) +FEATURE(FEATURE_SSE4_2) +FEATURE(FEATURE_POPCNT) +FEATURE(FEATURE_AES) +FEATURE(FEATURE_PCLMUL) +FEATURE(FEATURE_AVX) +FEATURE(FEATURE_BMI) +FEATURE(FEATURE_FMA4) +FEATURE(FEATURE_XOP) +FEATURE(FEATURE_FMA) +FEATURE(FEATURE_BMI2) +FEATURE(FEATURE_AVX2) +FEATURE(FEATURE_AVX512F) +FEATURE(FEATURE_AVX512VL) +FEATURE(FEATURE_AVX512BW) +FEATURE(FEATURE_AVX512DQ) +FEATURE(FEATURE_AVX512CD) +FEATURE(FEATURE_AVX512ER) +FEATURE(FEATURE_AVX512PF) +FEATURE(FEATURE_AVX512VBMI) +FEATURE(FEATURE_AVX512IFMA) +FEATURE(FEATURE_AVX5124VNNIW) +FEATURE(FEATURE_AVX5124FMAPS) +FEATURE(FEATURE_AVX512VPOPCNTDQ) + + +// FIXME: When commented out features are supported in LLVM, enable them here. +CPU_SPECIFIC("generic", 'A', "") +CPU_SPECIFIC("pentium", 'B', "") +CPU_SPECIFIC("pentium_pro", 'C', "+cmov") +CPU_SPECIFIC("pentium_mmx", 'D', "+mmx") +CPU_SPECIFIC("pentium_ii", 'E', "+cmov,+mmx") +CPU_SPECIFIC("pentium_iii", 'H', "+cmov,+mmx,+sse") +CPU_SPECIFIC("pentium_iii_no_xmm_regs", 'H',"+cmov,+sse") +CPU_SPECIFIC("pentium_4", 'J', "+cmov,+mmx,+sse,+sse2") +CPU_SPECIFIC("pentium_m", 'K', "+cmov,+mmx,+sse,+sse2") +CPU_SPECIFIC("pentium_4_sse3", 'L', "+cmov,+mmx,+sse,+sse2,+sse3") +CPU_SPECIFIC("core_2_duo_ssse3", 'M', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3") +CPU_SPECIFIC("core_2_duo_sse4_1", 'N', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1") +CPU_SPECIFIC("atom", 'O', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+movbe") +CPU_SPECIFIC("atom_sse4_2", 'c', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt") +CPU_SPECIFIC("core_i7_sse4_2", 'P', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt") +CPU_SPECIFIC("core_aes_pclmulqdq", 'Q', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt") +CPU_SPECIFIC("atom_sse4_2_movbe", 'd', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt") +CPU_SPECIFIC("goldmont", 'i', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt") +CPU_SPECIFIC("sandybridge", 'R', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+avx") +CPU_SPECIFIC_ALIAS("core_2nd_gen_avx", "sandybridge") +CPU_SPECIFIC("ivybridge", 'S', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+popcnt,+f16c,+avx") +CPU_SPECIFIC_ALIAS("core_3rd_gen_avx", "ivybridge") +CPU_SPECIFIC("haswell", 'V', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2") +CPU_SPECIFIC_ALIAS("core_4th_gen_avx", "haswell") +CPU_SPECIFIC("core_4th_gen_avx_tsx", 'W', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2") +CPU_SPECIFIC("broadwell", 'X', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx") +CPU_SPECIFIC_ALIAS("core_5th_gen_avx", "broadwell") +CPU_SPECIFIC("core_5th_gen_avx_tsx", 'Y', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx") +CPU_SPECIFIC("knl", 'Z', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512f,+adx,+avx512er,+avx512pf,+avx512cd") +CPU_SPECIFIC_ALIAS("mic_avx512", "knl") +CPU_SPECIFIC("skylake", 'b', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+adx,+mpx") +CPU_SPECIFIC( "skylake_avx512", 'a', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512dq,+avx512f,+adx,+avx512cd,+avx512bw,+avx512vl,+clwb") +CPU_SPECIFIC("cannonlake", 'e', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512dq,+avx512f,+adx,+avx512ifma,+avx512cd,+avx512bw,+avx512vl,+avx512vbmi") +CPU_SPECIFIC("knm", 'j', "+cmov,+mmx,+sse,+sse2,+sse3,+ssse3,+sse4.1,+sse4.2,+movbe,+popcnt,+f16c,+avx,+fma,+bmi,+lzcnt,+avx2,+avx512f,+adx,+avx512er,+avx512pf,+avx512cd,+avx5124fmaps,+avx5124vnniw,+avx512vpopcntdq") + +#undef CPU_SPECIFIC_ALIAS +#undef CPU_SPECIFIC #undef PROC_64_BIT #undef PROC_32_BIT +#undef FEATURE #undef PROC #undef PROC_ALIAS +#undef PROC_WITH_FEAT diff --git a/include/clang/Basic/XRayInstr.h b/include/clang/Basic/XRayInstr.h new file mode 100644 index 0000000000000..13c3032a5ccab --- /dev/null +++ b/include/clang/Basic/XRayInstr.h @@ -0,0 +1,70 @@ +//===--- XRayInstr.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +/// \file +/// Defines the clang::XRayInstrKind enum. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_BASIC_XRAYINSTR_H +#define LLVM_CLANG_BASIC_XRAYINSTR_H + +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstdint> + +namespace clang { + +using XRayInstrMask = uint32_t; + +namespace XRayInstrKind { + +// TODO: Auto-generate these as we add more instrumentation kinds. +enum XRayInstrOrdinal : XRayInstrMask { + XRIO_Function, + XRIO_Custom, + XRIO_Typed, + XRIO_Count +}; + +constexpr XRayInstrMask None = 0; +constexpr XRayInstrMask Function = 1U << XRIO_Function; +constexpr XRayInstrMask Custom = 1U << XRIO_Custom; +constexpr XRayInstrMask Typed = 1U << XRIO_Typed; +constexpr XRayInstrMask All = Function | Custom | Typed; + +} // namespace XRayInstrKind + +struct XRayInstrSet { + bool has(XRayInstrMask K) const { + assert(llvm::isPowerOf2_32(K)); + return Mask & K; + } + + bool hasOneOf(XRayInstrMask K) const { return Mask & K; } + + void set(XRayInstrMask K, bool Value) { + assert(llvm::isPowerOf2_32(K)); + Mask = Value ? (Mask | K) : (Mask & ~K); + } + + void clear(XRayInstrMask K = XRayInstrKind::All) { Mask &= ~K; } + + bool empty() const { return Mask == 0; } + + XRayInstrMask Mask = 0; +}; + +XRayInstrMask parseXRayInstrValue(StringRef Value); + +} // namespace clang + +#endif // LLVM_CLANG_BASIC_XRAYINSTR_H diff --git a/include/clang/Basic/XRayLists.h b/include/clang/Basic/XRayLists.h index 8cfea70e280a9..244b1d533b7ca 100644 --- a/include/clang/Basic/XRayLists.h +++ b/include/clang/Basic/XRayLists.h @@ -26,12 +26,13 @@ namespace clang { class XRayFunctionFilter { std::unique_ptr<llvm::SpecialCaseList> AlwaysInstrument; std::unique_ptr<llvm::SpecialCaseList> NeverInstrument; + std::unique_ptr<llvm::SpecialCaseList> AttrList; SourceManager &SM; public: XRayFunctionFilter(ArrayRef<std::string> AlwaysInstrumentPaths, ArrayRef<std::string> NeverInstrumentPaths, - SourceManager &SM); + ArrayRef<std::string> AttrListPaths, SourceManager &SM); enum class ImbueAttribute { NONE, diff --git a/include/clang/Basic/arm_fp16.td b/include/clang/Basic/arm_fp16.td new file mode 100644 index 0000000000000..bc15a22d84a63 --- /dev/null +++ b/include/clang/Basic/arm_fp16.td @@ -0,0 +1,131 @@ +//===--- arm_fp16.td - ARM FP16 compiler interface ------------------------===// +// +// 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 TableGen definitions from which the ARM FP16 header +// file will be generated. +// +//===----------------------------------------------------------------------===// + +include "arm_neon_incl.td" + +// ARMv8.2-A FP16 intrinsics. +let ArchGuard = "defined(__ARM_FEATURE_FP16_SCALAR_ARITHMETIC) && defined(__aarch64__)" in { + + // Negate + def VNEGSH : SInst<"vneg", "ss", "Sh">; + + // Reciprocal/Sqrt + def SCALAR_FRECPSH : IInst<"vrecps", "sss", "Sh">; + def FSQRTSH : SInst<"vsqrt", "ss", "Sh">; + def SCALAR_FRSQRTSH : IInst<"vrsqrts", "sss", "Sh">; + + // Reciprocal Estimate + def SCALAR_FRECPEH : IInst<"vrecpe", "ss", "Sh">; + + // Reciprocal Exponent + def SCALAR_FRECPXH : IInst<"vrecpx", "ss", "Sh">; + + // Reciprocal Square Root Estimate + def SCALAR_FRSQRTEH : IInst<"vrsqrte", "ss", "Sh">; + + // Rounding + def FRINTZ_S64H : SInst<"vrnd", "ss", "Sh">; + def FRINTA_S64H : SInst<"vrnda", "ss", "Sh">; + def FRINTI_S64H : SInst<"vrndi", "ss", "Sh">; + def FRINTM_S64H : SInst<"vrndm", "ss", "Sh">; + def FRINTN_S64H : SInst<"vrndn", "ss", "Sh">; + def FRINTP_S64H : SInst<"vrndp", "ss", "Sh">; + def FRINTX_S64H : SInst<"vrndx", "ss", "Sh">; + + // Conversion + def SCALAR_SCVTFSH : SInst<"vcvth_f16", "Ys", "silUsUiUl">; + def SCALAR_FCVTZSH : SInst<"vcvt_s16", "$s", "Sh">; + def SCALAR_FCVTZSH1 : SInst<"vcvt_s32", "Is", "Sh">; + def SCALAR_FCVTZSH2 : SInst<"vcvt_s64", "Ls", "Sh">; + def SCALAR_FCVTZUH : SInst<"vcvt_u16", "bs", "Sh">; + def SCALAR_FCVTZUH1 : SInst<"vcvt_u32", "Us", "Sh">; + def SCALAR_FCVTZUH2 : SInst<"vcvt_u64", "Os", "Sh">; + def SCALAR_FCVTASH : SInst<"vcvta_s16", "$s", "Sh">; + def SCALAR_FCVTASH1 : SInst<"vcvta_s32", "Is", "Sh">; + def SCALAR_FCVTASH2 : SInst<"vcvta_s64", "Ls", "Sh">; + def SCALAR_FCVTAUH : SInst<"vcvta_u16", "bs", "Sh">; + def SCALAR_FCVTAUH1 : SInst<"vcvta_u32", "Us", "Sh">; + def SCALAR_FCVTAUH2 : SInst<"vcvta_u64", "Os", "Sh">; + def SCALAR_FCVTMSH : SInst<"vcvtm_s16", "$s", "Sh">; + def SCALAR_FCVTMSH1 : SInst<"vcvtm_s32", "Is", "Sh">; + def SCALAR_FCVTMSH2 : SInst<"vcvtm_s64", "Ls", "Sh">; + def SCALAR_FCVTMUH : SInst<"vcvtm_u16", "bs", "Sh">; + def SCALAR_FCVTMUH1 : SInst<"vcvtm_u32", "Us", "Sh">; + def SCALAR_FCVTMUH2 : SInst<"vcvtm_u64", "Os", "Sh">; + def SCALAR_FCVTNSH : SInst<"vcvtn_s16", "$s", "Sh">; + def SCALAR_FCVTNSH1 : SInst<"vcvtn_s32", "Is", "Sh">; + def SCALAR_FCVTNSH2 : SInst<"vcvtn_s64", "Ls", "Sh">; + def SCALAR_FCVTNUH : SInst<"vcvtn_u16", "bs", "Sh">; + def SCALAR_FCVTNUH1 : SInst<"vcvtn_u32", "Us", "Sh">; + def SCALAR_FCVTNUH2 : SInst<"vcvtn_u64", "Os", "Sh">; + def SCALAR_FCVTPSH : SInst<"vcvtp_s16", "$s", "Sh">; + def SCALAR_FCVTPSH1 : SInst<"vcvtp_s32", "Is", "Sh">; + def SCALAR_FCVTPSH2 : SInst<"vcvtp_s64", "Ls", "Sh">; + def SCALAR_FCVTPUH : SInst<"vcvtp_u16", "bs", "Sh">; + def SCALAR_FCVTPUH1 : SInst<"vcvtp_u32", "Us", "Sh">; + def SCALAR_FCVTPUH2 : SInst<"vcvtp_u64", "Os", "Sh">; + let isVCVT_N = 1 in { + def SCALAR_SCVTFSHO : SInst<"vcvth_n_f16", "Ysi", "silUsUiUl">; + def SCALAR_FCVTZSHO : SInst<"vcvt_n_s16", "$si", "Sh">; + def SCALAR_FCVTZSH1O: SInst<"vcvt_n_s32", "Isi", "Sh">; + def SCALAR_FCVTZSH2O: SInst<"vcvt_n_s64", "Lsi", "Sh">; + def SCALAR_FCVTZUHO : SInst<"vcvt_n_u16", "bsi", "Sh">; + def SCALAR_FCVTZUH1O: SInst<"vcvt_n_u32", "Usi", "Sh">; + def SCALAR_FCVTZUH2O: SInst<"vcvt_n_u64", "Osi", "Sh">; + } + // Comparison + def SCALAR_CMEQRH : SInst<"vceq", "bss", "Sh">; + def SCALAR_CMEQZH : SInst<"vceqz", "bs", "Sh">; + def SCALAR_CMGERH : SInst<"vcge", "bss", "Sh">; + def SCALAR_CMGEZH : SInst<"vcgez", "bs", "Sh">; + def SCALAR_CMGTRH : SInst<"vcgt", "bss", "Sh">; + def SCALAR_CMGTZH : SInst<"vcgtz", "bs", "Sh">; + def SCALAR_CMLERH : SInst<"vcle", "bss", "Sh">; + def SCALAR_CMLEZH : SInst<"vclez", "bs", "Sh">; + def SCALAR_CMLTH : SInst<"vclt", "bss", "Sh">; + def SCALAR_CMLTZH : SInst<"vcltz", "bs", "Sh">; + + // Absolute Compare Mask Greater Than Or Equal + def SCALAR_FACGEH : IInst<"vcage", "bss", "Sh">; + def SCALAR_FACLEH : IInst<"vcale", "bss", "Sh">; + + // Absolute Compare Mask Greater Than + def SCALAR_FACGT : IInst<"vcagt", "bss", "Sh">; + def SCALAR_FACLT : IInst<"vcalt", "bss", "Sh">; + + // Scalar Absolute Value + def SCALAR_ABSH : SInst<"vabs", "ss", "Sh">; + + // Scalar Absolute Difference + def SCALAR_ABDH: IInst<"vabd", "sss", "Sh">; + + // Add/Sub + def VADDSH : SInst<"vadd", "sss", "Sh">; + def VSUBHS : SInst<"vsub", "sss", "Sh">; + + // Max/Min + def VMAXHS : SInst<"vmax", "sss", "Sh">; + def VMINHS : SInst<"vmin", "sss", "Sh">; + def FMAXNMHS : SInst<"vmaxnm", "sss", "Sh">; + def FMINNMHS : SInst<"vminnm", "sss", "Sh">; + + // Multiplication/Division + def VMULHS : SInst<"vmul", "sss", "Sh">; + def MULXHS : SInst<"vmulx", "sss", "Sh">; + def FDIVHS : SInst<"vdiv", "sss", "Sh">; + + // Vector fused multiply-add operations + def VFMAHS : SInst<"vfma", "ssss", "Sh">; + def VFMSHS : SInst<"vfms", "ssss", "Sh">; +} diff --git a/include/clang/Basic/arm_neon.td b/include/clang/Basic/arm_neon.td index d5c16a91a34f2..d405aac106504 100644 --- a/include/clang/Basic/arm_neon.td +++ b/include/clang/Basic/arm_neon.td @@ -11,309 +11,8 @@ // file will be generated. See ARM document DUI0348B. // //===----------------------------------------------------------------------===// -// -// Each intrinsic is a subclass of the Inst class. An intrinsic can either -// generate a __builtin_* call or it can expand to a set of generic operations. -// -// The operations are subclasses of Operation providing a list of DAGs, the -// last of which is the return value. The available DAG nodes are documented -// below. -// -//===----------------------------------------------------------------------===// - -// The base Operation class. All operations must subclass this. -class Operation<list<dag> ops=[]> { - list<dag> Ops = ops; - bit Unavailable = 0; -} -// An operation that only contains a single DAG. -class Op<dag op> : Operation<[op]>; -// A shorter version of Operation - takes a list of DAGs. The last of these will -// be the return value. -class LOp<list<dag> ops> : Operation<ops>; - -// These defs and classes are used internally to implement the SetTheory -// expansion and should be ignored. -foreach Index = 0-63 in - def sv##Index; -class MaskExpand; - -//===----------------------------------------------------------------------===// -// Available operations -//===----------------------------------------------------------------------===// - -// DAG arguments can either be operations (documented below) or variables. -// Variables are prefixed with '$'. There are variables for each input argument, -// with the name $pN, where N starts at zero. So the zero'th argument will be -// $p0, the first $p1 etc. - -// op - Binary or unary operator, depending on the number of arguments. The -// operator itself is just treated as a raw string and is not checked. -// example: (op "+", $p0, $p1) -> "__p0 + __p1". -// (op "-", $p0) -> "-__p0" -def op; -// call - Invoke another intrinsic. The input types are type checked and -// disambiguated. If there is no intrinsic defined that takes -// the given types (or if there is a type ambiguity) an error is -// generated at tblgen time. The name of the intrinsic is the raw -// name as given to the Inst class (not mangled). -// example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)" -// (assuming $p0 has type int16x8_t). -def call; -// cast - Perform a cast to a different type. This gets emitted as a static -// C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use -// "bitcast". -// -// The syntax is (cast MOD* VAL). The last argument is the value to -// cast, preceded by a sequence of type modifiers. The target type -// starts off as the type of VAL, and is modified by MOD in sequence. -// The available modifiers are: -// - $X - Take the type of parameter/variable X. For example: -// (cast $p0, $p1) would cast $p1 to the type of $p0. -// - "R" - The type of the return type. -// - A typedef string - A NEON or stdint.h type that is then parsed. -// for example: (cast "uint32x4_t", $p0). -// - "U" - Make the type unsigned. -// - "S" - Make the type signed. -// - "H" - Halve the number of lanes in the type. -// - "D" - Double the number of lanes in the type. -// - "8" - Convert type to an equivalent vector of 8-bit signed -// integers. -// example: (cast "R", "U", $p0) -> "(uint32x4_t)__p0" (assuming the return -// value is of type "int32x4_t". -// (cast $p0, "D", "8", $p1) -> "(int8x16_t)__p1" (assuming __p0 -// has type float64x1_t or any other vector type of 64 bits). -// (cast "int32_t", $p2) -> "(int32_t)__p2" -def cast; -// bitcast - Same as "cast", except a reinterpret-cast is produced: -// (bitcast "T", $p0) -> "*(T*)&__p0". -// The VAL argument is saved to a temporary so it can be used -// as an l-value. -def bitcast; -// dup - Take a scalar argument and create a vector by duplicating it into -// all lanes. The type of the vector is the base type of the intrinsic. -// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type -// is uint32x2_t). -def dup; -// splat - Take a vector and a lane index, and return a vector of the same type -// containing repeated instances of the source vector at the lane index. -// example: (splat $p0, $p1) -> -// "__builtin_shufflevector(__p0, __p0, __p1, __p1, __p1, __p1)" -// (assuming __p0 has four elements). -def splat; -// save_temp - Create a temporary (local) variable. The variable takes a name -// based on the zero'th parameter and can be referenced using -// using that name in subsequent DAGs in the same -// operation. The scope of a temp is the operation. If a variable -// with the given name already exists, an error will be given at -// tblgen time. -// example: [(save_temp $var, (call "foo", $p0)), -// (op "+", $var, $p1)] -> -// "int32x2_t __var = foo(__p0); return __var + __p1;" -def save_temp; -// name_replace - Return the name of the current intrinsic with the first -// argument replaced by the second argument. Raises an error if -// the first argument does not exist in the intrinsic name. -// example: (call (name_replace "_high_", "_"), $p0) (to call the non-high -// version of this intrinsic). -def name_replace; -// literal - Create a literal piece of code. The code is treated as a raw -// string, and must be given a type. The type is a stdint.h or -// NEON intrinsic type as given to (cast). -// example: (literal "int32_t", "0") -def literal; -// shuffle - Create a vector shuffle. The syntax is (shuffle ARG0, ARG1, MASK). -// The MASK argument is a set of elements. The elements are generated -// from the two special defs "mask0" and "mask1". "mask0" expands to -// the lane indices in sequence for ARG0, and "mask1" expands to -// the lane indices in sequence for ARG1. They can be used as-is, e.g. -// -// (shuffle $p0, $p1, mask0) -> $p0 -// (shuffle $p0, $p1, mask1) -> $p1 -// -// or, more usefully, they can be manipulated using the SetTheory -// operators plus some extra operators defined in the NEON emitter. -// The operators are described below. -// example: (shuffle $p0, $p1, (add (highhalf mask0), (highhalf mask1))) -> -// A concatenation of the high halves of the input vectors. -def shuffle; - -// add, interleave, decimate: These set operators are vanilla SetTheory -// operators and take their normal definition. -def add; -def interleave; -def decimate; -// rotl - Rotate set left by a number of elements. -// example: (rotl mask0, 3) -> [3, 4, 5, 6, 0, 1, 2] -def rotl; -// rotl - Rotate set right by a number of elements. -// example: (rotr mask0, 3) -> [4, 5, 6, 0, 1, 2, 3] -def rotr; -// highhalf - Take only the high half of the input. -// example: (highhalf mask0) -> [4, 5, 6, 7] (assuming mask0 had 8 elements) -def highhalf; -// highhalf - Take only the low half of the input. -// example: (lowhalf mask0) -> [0, 1, 2, 3] (assuming mask0 had 8 elements) -def lowhalf; -// rev - Perform a variable-width reversal of the elements. The zero'th argument -// is a width in bits to reverse. The lanes this maps to is determined -// based on the element width of the underlying type. -// example: (rev 32, mask0) -> [3, 2, 1, 0, 7, 6, 5, 4] (if 8-bit elements) -// example: (rev 32, mask0) -> [1, 0, 3, 2] (if 16-bit elements) -def rev; -// mask0 - The initial sequence of lanes for shuffle ARG0 -def mask0 : MaskExpand; -// mask0 - The initial sequence of lanes for shuffle ARG1 -def mask1 : MaskExpand; - -def OP_NONE : Operation; -def OP_UNAVAILABLE : Operation { - let Unavailable = 1; -} - -//===----------------------------------------------------------------------===// -// Instruction definitions -//===----------------------------------------------------------------------===// - -// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and -// a sequence of typespecs. -// -// The name is the base name of the intrinsic, for example "vget_lane". This is -// then mangled by the tblgen backend to add type information ("vget_lane_s16"). -// -// A typespec is a sequence of uppercase characters (modifiers) followed by one -// lowercase character. A typespec encodes a particular "base type" of the -// intrinsic. -// -// An example typespec is "Qs" - quad-size short - uint16x8_t. The available -// typespec codes are given below. -// -// The string given to an Inst class is a sequence of typespecs. The intrinsic -// is instantiated for every typespec in the sequence. For example "sdQsQd". -// -// The prototype is a string that defines the return type of the intrinsic -// and the type of each argument. The return type and every argument gets a -// "modifier" that can change in some way the "base type" of the intrinsic. -// -// The modifier 'd' means "default" and does not modify the base type in any -// way. The available modifiers are given below. -// -// Typespecs -// --------- -// c: char -// s: short -// i: int -// l: long -// k: 128-bit long -// f: float -// h: half-float -// d: double -// -// Typespec modifiers -// ------------------ -// S: scalar, only used for function mangling. -// U: unsigned -// Q: 128b -// H: 128b without mangling 'q' -// P: polynomial -// -// Prototype modifiers -// ------------------- -// prototype: return (arg, arg, ...) -// -// v: void -// t: best-fit integer (int/poly args) -// x: signed integer (int/float args) -// u: unsigned integer (int/float args) -// f: float (int args) -// F: double (int args) -// H: half (int args) -// d: default -// g: default, ignore 'Q' size modifier. -// j: default, force 'Q' size modifier. -// w: double width elements, same num elts -// n: double width elements, half num elts -// h: half width elements, double num elts -// q: half width elements, quad num elts -// e: half width elements, double num elts, unsigned -// m: half width elements, same num elts -// i: constant int -// l: constant uint64 -// s: scalar of element type -// z: scalar of half width element type, signed -// r: scalar of double width element type, signed -// a: scalar of element type (splat to vector type) -// b: scalar of unsigned integer/long type (int/float args) -// $: scalar of signed integer/long type (int/float args) -// y: scalar of float -// o: scalar of double -// k: default elt width, double num elts -// 2,3,4: array of default vectors -// B,C,D: array of default elts, force 'Q' size modifier. -// p: pointer type -// c: const pointer type - -// Every intrinsic subclasses Inst. -class Inst <string n, string p, string t, Operation o> { - string Name = n; - string Prototype = p; - string Types = t; - string ArchGuard = ""; - - Operation Operation = o; - bit CartesianProductOfTypes = 0; - bit BigEndianSafe = 0; - bit isShift = 0; - bit isScalarShift = 0; - bit isScalarNarrowShift = 0; - bit isVCVT_N = 0; - // For immediate checks: the immediate will be assumed to specify the lane of - // a Q register. Only used for intrinsics which end up calling polymorphic - // builtins. - bit isLaneQ = 0; - - // Certain intrinsics have different names than their representative - // instructions. This field allows us to handle this correctly when we - // are generating tests. - string InstName = ""; - - // Certain intrinsics even though they are not a WOpInst or LOpInst, - // generate a WOpInst/LOpInst instruction (see below for definition - // of a WOpInst/LOpInst). For testing purposes we need to know - // this. Ex: vset_lane which outputs vmov instructions. - bit isHiddenWInst = 0; - bit isHiddenLInst = 0; -} - -// The following instruction classes are implemented via builtins. -// These declarations are used to generate Builtins.def: -// -// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8", "p8") -// IInst: Instruction with generic integer suffix (e.g., "i8") -// WInst: Instruction with only bit size suffix (e.g., "8") -class SInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} -class IInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} -class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} - -// The following instruction classes are implemented via operators -// instead of builtins. As such these declarations are only used for -// the purpose of generating tests. -// -// SOpInst: Instruction with signed/unsigned suffix (e.g., "s8", -// "u8", "p8"). -// IOpInst: Instruction with generic integer suffix (e.g., "i8"). -// WOpInst: Instruction with bit size only suffix (e.g., "8"). -// LOpInst: Logical instruction with no bit size suffix. -// NoTestOpInst: Intrinsic that has no corresponding instruction. -class SOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} -class IOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} -class WOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} -class LOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} -class NoTestOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} -//===----------------------------------------------------------------------===// -// Operations -//===----------------------------------------------------------------------===// +include "arm_neon_incl.td" def OP_ADD : Op<(op "+", $p0, $p1)>; def OP_ADDL : Op<(op "+", (call "vmovl", $p0), (call "vmovl", $p1))>; @@ -500,6 +199,13 @@ def OP_SCALAR_HALF_SET_LNQ : Op<(bitcast "float16x8_t", (bitcast "int16_t", $p0), (bitcast "int16x8_t", $p1), $p2))>; +def OP_DOT_LN + : Op<(call "vdot", $p0, $p1, + (bitcast $p1, (splat(bitcast "uint32x2_t", $p2), $p3)))>; +def OP_DOT_LNQ + : Op<(call "vdot", $p0, $p1, + (bitcast $p1, (splat(bitcast "uint32x4_t", $p2), $p3)))>; + //===----------------------------------------------------------------------===// // Instructions //===----------------------------------------------------------------------===// @@ -632,12 +338,24 @@ def VSLI_N : WInst<"vsli_n", "dddi", // E.3.14 Loads and stores of a single vector def VLD1 : WInst<"vld1", "dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VLD1_X2 : WInst<"vld1_x2", "2c", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; +def VLD1_X3 : WInst<"vld1_x3", "3c", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; +def VLD1_X4 : WInst<"vld1_x4", "4c", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; def VLD1_LANE : WInst<"vld1_lane", "dcdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VLD1_DUP : WInst<"vld1_dup", "dc", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VST1 : WInst<"vst1", "vpd", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; +def VST1_X2 : WInst<"vst1_x2", "vp2", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; +def VST1_X3 : WInst<"vst1_x3", "vp3", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; +def VST1_X4 : WInst<"vst1_x4", "vp4", + "cfhilsUcUiUlUsQcQfQhQiQlQsQUcQUiQUlQUsPcPsQPcQPs">; def VST1_LANE : WInst<"vst1_lane", "vpdi", "QUcQUsQUiQUlQcQsQiQlQhQfQPcQPsUcUsUiUlcsilhfPcPs">; @@ -646,9 +364,12 @@ def VST1_LANE : WInst<"vst1_lane", "vpdi", def VLD2 : WInst<"vld2", "2c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VLD3 : WInst<"vld3", "3c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; def VLD4 : WInst<"vld4", "4c", "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPs">; -def VLD2_DUP : WInst<"vld2_dup", "2c", "UcUsUiUlcsilhfPcPs">; -def VLD3_DUP : WInst<"vld3_dup", "3c", "UcUsUiUlcsilhfPcPs">; -def VLD4_DUP : WInst<"vld4_dup", "4c", "UcUsUiUlcsilhfPcPs">; +def VLD2_DUP : WInst<"vld2_dup", "2c", + "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">; +def VLD3_DUP : WInst<"vld3_dup", "3c", + "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">; +def VLD4_DUP : WInst<"vld4_dup", "4c", + "UcUsUiUlcsilhfPcPsQcQfQhQiQlQsQPcQPsQUcQUiQUlQUs">; def VLD2_LANE : WInst<"vld2_lane", "2c2i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; def VLD3_LANE : WInst<"vld3_lane", "3c3i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; def VLD4_LANE : WInst<"vld4_lane", "4c4i", "QUsQUiQsQiQhQfQPsUcUsUicsihfPcPs">; @@ -698,6 +419,10 @@ def VCOMBINE : NoTestOpInst<"vcombine", "kdd", "csilhfUcUsUiUlPcPs", OP_CONC>; //////////////////////////////////////////////////////////////////////////////// // E.3.21 Splitting vectors +// Note that the ARM NEON Reference 2.0 mistakenly document the vget_high_f16() +// and vget_low_f16() intrinsics as AArch64-only. We (and GCC) support all +// versions of these intrinsics in both AArch32 and AArch64 architectures. See +// D45668 for more details. let InstName = "vmov" in { def VGET_HIGH : NoTestOpInst<"vget_high", "dk", "csilhfUcUsUiUlPcPs", OP_HI>; def VGET_LOW : NoTestOpInst<"vget_low", "dk", "csilhfUcUsUiUlPcPs", OP_LO>; @@ -832,6 +557,7 @@ def VREINTERPRET let ArchGuard = "defined(__ARM_FEATURE_FMA)" in { def VFMA : SInst<"vfma", "dddd", "fQf">; def VFMS : SOpInst<"vfms", "dddd", "fQf", OP_FMLS>; + def FMLA_N_F32 : SOpInst<"vfma_n", "ddds", "fQf", OP_FMLA_N>; } //////////////////////////////////////////////////////////////////////////////// @@ -858,18 +584,15 @@ def ST3 : WInst<"vst3", "vp3", "QUlQldQdPlQPl">; def ST4 : WInst<"vst4", "vp4", "QUlQldQdPlQPl">; def LD1_X2 : WInst<"vld1_x2", "2c", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; -def LD3_x3 : WInst<"vld1_x3", "3c", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; -def LD4_x4 : WInst<"vld1_x4", "4c", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; - -def ST1_X2 : WInst<"vst1_x2", "vp2", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; -def ST1_X3 : WInst<"vst1_x3", "vp3", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; -def ST1_X4 : WInst<"vst1_x4", "vp4", - "QUcQUsQUiQcQsQiQhQfQPcQPsUcUsUiUlcsilhfPcPsQUlQldQdPlQPl">; + "dQdPlQPl">; +def LD1_X3 : WInst<"vld1_x3", "3c", + "dQdPlQPl">; +def LD1_X4 : WInst<"vld1_x4", "4c", + "dQdPlQPl">; + +def ST1_X2 : WInst<"vst1_x2", "vp2", "dQdPlQPl">; +def ST1_X3 : WInst<"vst1_x3", "vp3", "dQdPlQPl">; +def ST1_X4 : WInst<"vst1_x4", "vp4", "dQdPlQPl">; def LD1_LANE : WInst<"vld1_lane", "dcdi", "dQdPlQPl">; def LD2_LANE : WInst<"vld2_lane", "2c2i", "lUlQcQUcQPcQlQUldQdPlQPl">; @@ -881,12 +604,9 @@ def ST3_LANE : WInst<"vst3_lane", "vp3i", "lUlQcQUcQPcQlQUldQdPlQPl">; def ST4_LANE : WInst<"vst4_lane", "vp4i", "lUlQcQUcQPcQlQUldQdPlQPl">; def LD1_DUP : WInst<"vld1_dup", "dc", "dQdPlQPl">; -def LD2_DUP : WInst<"vld2_dup", "2c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; -def LD3_DUP : WInst<"vld3_dup", "3c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; -def LD4_DUP : WInst<"vld4_dup", "4c", - "QUcQUsQUiQUlQcQsQiQlQhQfQdQPcQPsQPldPl">; +def LD2_DUP : WInst<"vld2_dup", "2c", "dQdPlQPl">; +def LD3_DUP : WInst<"vld3_dup", "3c", "dQdPlQPl">; +def LD4_DUP : WInst<"vld4_dup", "4c", "dQdPlQPl">; def VLDRQ : WInst<"vldrq", "sc", "Pk">; def VSTRQ : WInst<"vstrq", "vps", "Pk">; @@ -922,8 +642,8 @@ def FMLS : SOpInst<"vfms", "dddd", "dQd", OP_FMLS>; // MUL, MLA, MLS, FMA, FMS definitions with scalar argument def VMUL_N_A64 : IOpInst<"vmul_n", "dds", "Qd", OP_MUL_N>; -def FMLA_N : SOpInst<"vfma_n", "ddds", "fQfQd", OP_FMLA_N>; -def FMLS_N : SOpInst<"vfms_n", "ddds", "fQfQd", OP_FMLS_N>; +def FMLA_N : SOpInst<"vfma_n", "ddds", "dQd", OP_FMLA_N>; +def FMLS_N : SOpInst<"vfms_n", "ddds", "fdQfQd", OP_FMLS_N>; def MLA_N : SOpInst<"vmla_n", "ddds", "Qd", OP_MLA_N>; def MLS_N : SOpInst<"vmls_n", "ddds", "Qd", OP_MLS_N>; @@ -1214,7 +934,7 @@ def VEXT_A64 : WInst<"vext", "dddi", "dQdPlQPl">; //////////////////////////////////////////////////////////////////////////////// // Crypto -let ArchGuard = "__ARM_FEATURE_CRYPTO" in { +let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_CRYPTO)" in { def AESE : SInst<"vaese", "ddd", "QUc">; def AESD : SInst<"vaesd", "ddd", "QUc">; def AESMC : SInst<"vaesmc", "dd", "QUc">; @@ -1268,6 +988,7 @@ 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">; +def FRINTI_S32 : SInst<"vrndi", "dd", "fQf">; } let ArchGuard = "__ARM_ARCH >= 8 && defined(__aarch64__) && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in { @@ -1277,7 +998,7 @@ 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">; +def FRINTI_S64 : SInst<"vrndi", "dd", "dQd">; } //////////////////////////////////////////////////////////////////////////////// @@ -1417,6 +1138,12 @@ def SCALAR_FCVTZU_N_U64 : SInst<"vcvt_n_u64", "bsi", "Sd">; } //////////////////////////////////////////////////////////////////////////////// +// Scalar Floating-point Round to Integral +let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING)" in { +def SCALAR_FRINTN_S32 : SInst<"vrndn", "ss", "Sf">; +} + +//////////////////////////////////////////////////////////////////////////////// // Scalar Reduce Pairwise Addition (Scalar and Floating Point) def SCALAR_ADDP : SInst<"vpadd", "sd", "SfSHlSHdSHUl">; @@ -1664,8 +1391,8 @@ def SCALAR_VDUP_LANE : IInst<"vdup_lane", "sdi", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs def SCALAR_VDUP_LANEQ : IInst<"vdup_laneq", "sji", "ScSsSiSlSfSdSUcSUsSUiSUlSPcSPs">; } -// ARMv8.2-A FP16 intrinsics. -let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in { +// ARMv8.2-A FP16 vector intrinsics for A32/A64. +let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { // ARMv8.2-A FP16 one-operand vector intrinsics. @@ -1690,20 +1417,20 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc def VCVTP_U16 : SInst<"vcvtp_u16", "ud", "hQh">; // Vector rounding - def FRINTZH : SInst<"vrnd", "dd", "hQh">; - def FRINTNH : SInst<"vrndn", "dd", "hQh">; - def FRINTAH : SInst<"vrnda", "dd", "hQh">; - def FRINTPH : SInst<"vrndp", "dd", "hQh">; - def FRINTMH : SInst<"vrndm", "dd", "hQh">; - def FRINTXH : SInst<"vrndx", "dd", "hQh">; - def FRINTIH : SInst<"vrndi", "dd", "hQh">; + let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_DIRECTED_ROUNDING) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { + def FRINTZH : SInst<"vrnd", "dd", "hQh">; + def FRINTNH : SInst<"vrndn", "dd", "hQh">; + def FRINTAH : SInst<"vrnda", "dd", "hQh">; + def FRINTPH : SInst<"vrndp", "dd", "hQh">; + def FRINTMH : SInst<"vrndm", "dd", "hQh">; + def FRINTXH : SInst<"vrndx", "dd", "hQh">; + } // Misc. def VABSH : SInst<"vabs", "dd", "hQh">; def VNEGH : SOpInst<"vneg", "dd", "hQh", OP_NEG>; def VRECPEH : SInst<"vrecpe", "dd", "hQh">; def FRSQRTEH : SInst<"vrsqrte", "dd", "hQh">; - def FSQRTH : SInst<"vsqrt", "dd", "hQh">; // ARMv8.2-A FP16 two-operands vector intrinsics. @@ -1714,12 +1441,12 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc // Comparison let InstName = "vacge" in { - def VCAGEH : SInst<"vcage", "udd", "hQh">; - def VCALEH : SInst<"vcale", "udd", "hQh">; + def VCAGEH : SInst<"vcage", "udd", "hQh">; + def VCALEH : SInst<"vcale", "udd", "hQh">; } let InstName = "vacgt" in { def VCAGTH : SInst<"vcagt", "udd", "hQh">; - def VCALTH : SInst<"vcalt", "udd", "hQh">; + def VCALTH : SInst<"vcalt", "udd", "hQh">; } def VCEQH : SOpInst<"vceq", "udd", "hQh", OP_EQ>; def VCGEH : SOpInst<"vcge", "udd", "hQh", OP_GE>; @@ -1739,23 +1466,20 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc // Max/Min def VMAXH : SInst<"vmax", "ddd", "hQh">; def VMINH : SInst<"vmin", "ddd", "hQh">; - def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">; - def FMINNMH : SInst<"vminnm", "ddd", "hQh">; + let ArchGuard = "__ARM_ARCH >= 8 && defined(__ARM_FEATURE_NUMERIC_MAXMIN) && defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC)" in { + def FMAXNMH : SInst<"vmaxnm", "ddd", "hQh">; + def FMINNMH : SInst<"vminnm", "ddd", "hQh">; + } // Multiplication/Division def VMULH : SOpInst<"vmul", "ddd", "hQh", OP_MUL>; - def MULXH : SInst<"vmulx", "ddd", "hQh">; - def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>; // Pairwise addition - def VPADDH : SInst<"vpadd", "ddd", "hQh">; + def VPADDH : SInst<"vpadd", "ddd", "h">; // Pairwise Max/Min - def VPMAXH : SInst<"vpmax", "ddd", "hQh">; - def VPMINH : SInst<"vpmin", "ddd", "hQh">; - // Pairwise MaxNum/MinNum - def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">; - def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">; + def VPMAXH : SInst<"vpmax", "ddd", "h">; + def VPMINH : SInst<"vpmin", "ddd", "h">; // Reciprocal/Sqrt def VRECPSH : SInst<"vrecps", "ddd", "hQh">; @@ -1769,6 +1493,63 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc // ARMv8.2-A FP16 lane vector intrinsics. + // Mul lane + def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>; + def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>; + + // Data processing intrinsics - section 5 + + // Logical operations + let isHiddenLInst = 1 in + def VBSLH : SInst<"vbsl", "dudd", "hQh">; + + // Transposition operations + def VZIPH : WInst<"vzip", "2dd", "hQh">; + def VUZPH : WInst<"vuzp", "2dd", "hQh">; + def VTRNH : WInst<"vtrn", "2dd", "hQh">; + + + let ArchGuard = "!defined(__aarch64__)" in { + // Set all lanes to same value. + // Already implemented prior to ARMv8.2-A. + def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>; + def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>; + def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>; + } + + // Vector Extract + def VEXTH : WInst<"vext", "dddi", "hQh">; + + // Reverse vector elements + def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>; +} + +// ARMv8.2-A FP16 vector intrinsics for A64 only. +let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarch64__)" in { + + // Vector rounding + def FRINTIH : SInst<"vrndi", "dd", "hQh">; + + // Misc. + def FSQRTH : SInst<"vsqrt", "dd", "hQh">; + + // Multiplication/Division + def MULXH : SInst<"vmulx", "ddd", "hQh">; + def FDIVH : IOpInst<"vdiv", "ddd", "hQh", OP_DIV>; + + // Pairwise addition + def VPADDH1 : SInst<"vpadd", "ddd", "Qh">; + + // Pairwise Max/Min + def VPMAXH1 : SInst<"vpmax", "ddd", "Qh">; + def VPMINH1 : SInst<"vpmin", "ddd", "Qh">; + + // Pairwise MaxNum/MinNum + def FMAXNMPH : SInst<"vpmaxnm", "ddd", "hQh">; + def FMINNMPH : SInst<"vpminnm", "ddd", "hQh">; + + // ARMv8.2-A FP16 lane vector intrinsics. + // FMA lane def VFMA_LANEH : IInst<"vfma_lane", "dddgi", "hQh">; def VFMA_LANEQH : IInst<"vfma_laneq", "dddji", "hQh">; @@ -1789,9 +1570,7 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc def SCALAR_FMLS_LANEQH : IOpInst<"vfms_laneq", "sssji", "Sh", OP_FMS_LNQ>; // Mul lane - def VMUL_LANEH : IOpInst<"vmul_lane", "ddgi", "hQh", OP_MUL_LN>; def VMUL_LANEQH : IOpInst<"vmul_laneq", "ddji", "hQh", OP_MUL_LN>; - def VMUL_NH : IOpInst<"vmul_n", "dds", "hQh", OP_MUL_N>; // Scalar floating point multiply (scalar, by element) def SCALAR_FMUL_LANEH : IOpInst<"vmul_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>; def SCALAR_FMUL_LANEQH : IOpInst<"vmul_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>; @@ -1800,11 +1579,9 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc def VMULX_LANEH : IOpInst<"vmulx_lane", "ddgi", "hQh", OP_MULX_LN>; def VMULX_LANEQH : IOpInst<"vmulx_laneq", "ddji", "hQh", OP_MULX_LN>; def VMULX_NH : IOpInst<"vmulx_n", "dds", "hQh", OP_MULX_N>; - // TODO: Scalar floating point multiply extended (scalar, by element) - // Below ones are commented out because they need vmulx_f16(float16_t, float16_t) - // which will be implemented later with fp16 scalar intrinsic (arm_fp16.h) - //def SCALAR_FMULX_LANEH : IOpInst<"vmulx_lane", "ssdi", "Sh", OP_SCALAR_MUL_LN>; - //def SCALAR_FMULX_LANEQH : IOpInst<"vmulx_laneq", "ssji", "Sh", OP_SCALAR_MUL_LN>; + // Scalar floating point mulx (scalar, by element) + def SCALAR_FMULX_LANEH : IInst<"vmulx_lane", "ssdi", "Sh">; + def SCALAR_FMULX_LANEQH : IInst<"vmulx_laneq", "ssji", "Sh">; // ARMv8.2-A FP16 reduction vector intrinsics. def VMAXVH : SInst<"vmaxv", "sd", "hQh">; @@ -1812,29 +1589,6 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc def FMAXNMVH : SInst<"vmaxnmv", "sd", "hQh">; def FMINNMVH : SInst<"vminnmv", "sd", "hQh">; - // Data processing intrinsics - section 5 - - // Logical operations - let isHiddenLInst = 1 in - def VBSLH : SInst<"vbsl", "dudd", "hQh">; - - // Transposition operations - def VZIPH : WInst<"vzip", "2dd", "hQh">; - def VUZPH : WInst<"vuzp", "2dd", "hQh">; - def VTRNH : WInst<"vtrn", "2dd", "hQh">; - - // Set all lanes to same value. - /* Already implemented prior to ARMv8.2-A. - def VMOV_NH : WOpInst<"vmov_n", "ds", "hQh", OP_DUP>; - def VDUP_NH : WOpInst<"vdup_n", "ds", "hQh", OP_DUP>; - def VDUP_LANE1H : WOpInst<"vdup_lane", "dgi", "hQh", OP_DUP_LN>;*/ - - // Vector Extract - def VEXTH : WInst<"vext", "dddi", "hQh">; - - // Reverse vector elements - def VREV64H : WOpInst<"vrev64", "dd", "hQh", OP_REV64>; - // Permutation def VTRN1H : SOpInst<"vtrn1", "ddd", "hQh", OP_TRN1>; def VZIP1H : SOpInst<"vzip1", "ddd", "hQh", OP_ZIP1>; @@ -1846,3 +1600,13 @@ let ArchGuard = "defined(__ARM_FEATURE_FP16_VECTOR_ARITHMETIC) && defined(__aarc def SCALAR_VDUP_LANEH : IInst<"vdup_lane", "sdi", "Sh">; def SCALAR_VDUP_LANEQH : IInst<"vdup_laneq", "sji", "Sh">; } + +// v8.2-A dot product instructions. +let ArchGuard = "defined(__ARM_FEATURE_DOTPROD)" in { + def DOT : SInst<"vdot", "dd88", "iQiUiQUi">; + def DOT_LANE : SOpInst<"vdot_lane", "dd87i", "iUiQiQUi", OP_DOT_LN>; +} +let ArchGuard = "defined(__ARM_FEATURE_DOTPROD) && defined(__aarch64__)" in { + // Variants indexing into a 128-bit vector are A64 only. + def UDOT_LANEQ : SOpInst<"vdot_laneq", "dd89i", "iUiQiQUi", OP_DOT_LNQ>; +} diff --git a/include/clang/Basic/arm_neon_incl.td b/include/clang/Basic/arm_neon_incl.td new file mode 100644 index 0000000000000..46708a52aa3a6 --- /dev/null +++ b/include/clang/Basic/arm_neon_incl.td @@ -0,0 +1,316 @@ +//===--- arm_neon_incl.td - ARM NEON compiler interface ------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines data structures shared by arm_neon.td and arm_fp16.td. +// It constains base operation classes, operations, instructions, instruction +// modifiers, etc. +// +//===----------------------------------------------------------------------===// +// +// Each intrinsic is a subclass of the Inst class. An intrinsic can either +// generate a __builtin_* call or it can expand to a set of generic operations. +// +// The operations are subclasses of Operation providing a list of DAGs, the +// last of which is the return value. The available DAG nodes are documented +// below. +// +//===----------------------------------------------------------------------===// + +// The base Operation class. All operations must subclass this. +class Operation<list<dag> ops=[]> { + list<dag> Ops = ops; + bit Unavailable = 0; +} +// An operation that only contains a single DAG. +class Op<dag op> : Operation<[op]>; +// A shorter version of Operation - takes a list of DAGs. The last of these will +// be the return value. +class LOp<list<dag> ops> : Operation<ops>; + +// These defs and classes are used internally to implement the SetTheory +// expansion and should be ignored. +foreach Index = 0-63 in + def sv##Index; +class MaskExpand; + +//===----------------------------------------------------------------------===// +// Available operations +//===----------------------------------------------------------------------===// + +// DAG arguments can either be operations (documented below) or variables. +// Variables are prefixed with '$'. There are variables for each input argument, +// with the name $pN, where N starts at zero. So the zero'th argument will be +// $p0, the first $p1 etc. + +// op - Binary or unary operator, depending on the number of arguments. The +// operator itself is just treated as a raw string and is not checked. +// example: (op "+", $p0, $p1) -> "__p0 + __p1". +// (op "-", $p0) -> "-__p0" +def op; +// call - Invoke another intrinsic. The input types are type checked and +// disambiguated. If there is no intrinsic defined that takes +// the given types (or if there is a type ambiguity) an error is +// generated at tblgen time. The name of the intrinsic is the raw +// name as given to the Inst class (not mangled). +// example: (call "vget_high", $p0) -> "vgetq_high_s16(__p0)" +// (assuming $p0 has type int16x8_t). +def call; +// cast - Perform a cast to a different type. This gets emitted as a static +// C-style cast. For a pure reinterpret cast (T x = *(T*)&y), use +// "bitcast". +// +// The syntax is (cast MOD* VAL). The last argument is the value to +// cast, preceded by a sequence of type modifiers. The target type +// starts off as the type of VAL, and is modified by MOD in sequence. +// The available modifiers are: +// - $X - Take the type of parameter/variable X. For example: +// (cast $p0, $p1) would cast $p1 to the type of $p0. +// - "R" - The type of the return type. +// - A typedef string - A NEON or stdint.h type that is then parsed. +// for example: (cast "uint32x4_t", $p0). +// - "U" - Make the type unsigned. +// - "S" - Make the type signed. +// - "H" - Halve the number of lanes in the type. +// - "D" - Double the number of lanes in the type. +// - "8" - Convert type to an equivalent vector of 8-bit signed +// integers. +// example: (cast "R", "U", $p0) -> "(uint32x4_t)__p0" (assuming the return +// value is of type "int32x4_t". +// (cast $p0, "D", "8", $p1) -> "(int8x16_t)__p1" (assuming __p0 +// has type float64x1_t or any other vector type of 64 bits). +// (cast "int32_t", $p2) -> "(int32_t)__p2" +def cast; +// bitcast - Same as "cast", except a reinterpret-cast is produced: +// (bitcast "T", $p0) -> "*(T*)&__p0". +// The VAL argument is saved to a temporary so it can be used +// as an l-value. +def bitcast; +// dup - Take a scalar argument and create a vector by duplicating it into +// all lanes. The type of the vector is the base type of the intrinsic. +// example: (dup $p1) -> "(uint32x2_t) {__p1, __p1}" (assuming the base type +// is uint32x2_t). +def dup; +// splat - Take a vector and a lane index, and return a vector of the same type +// containing repeated instances of the source vector at the lane index. +// example: (splat $p0, $p1) -> +// "__builtin_shufflevector(__p0, __p0, __p1, __p1, __p1, __p1)" +// (assuming __p0 has four elements). +def splat; +// save_temp - Create a temporary (local) variable. The variable takes a name +// based on the zero'th parameter and can be referenced using +// using that name in subsequent DAGs in the same +// operation. The scope of a temp is the operation. If a variable +// with the given name already exists, an error will be given at +// tblgen time. +// example: [(save_temp $var, (call "foo", $p0)), +// (op "+", $var, $p1)] -> +// "int32x2_t __var = foo(__p0); return __var + __p1;" +def save_temp; +// name_replace - Return the name of the current intrinsic with the first +// argument replaced by the second argument. Raises an error if +// the first argument does not exist in the intrinsic name. +// example: (call (name_replace "_high_", "_"), $p0) (to call the non-high +// version of this intrinsic). +def name_replace; +// literal - Create a literal piece of code. The code is treated as a raw +// string, and must be given a type. The type is a stdint.h or +// NEON intrinsic type as given to (cast). +// example: (literal "int32_t", "0") +def literal; +// shuffle - Create a vector shuffle. The syntax is (shuffle ARG0, ARG1, MASK). +// The MASK argument is a set of elements. The elements are generated +// from the two special defs "mask0" and "mask1". "mask0" expands to +// the lane indices in sequence for ARG0, and "mask1" expands to +// the lane indices in sequence for ARG1. They can be used as-is, e.g. +// +// (shuffle $p0, $p1, mask0) -> $p0 +// (shuffle $p0, $p1, mask1) -> $p1 +// +// or, more usefully, they can be manipulated using the SetTheory +// operators plus some extra operators defined in the NEON emitter. +// The operators are described below. +// example: (shuffle $p0, $p1, (add (highhalf mask0), (highhalf mask1))) -> +// A concatenation of the high halves of the input vectors. +def shuffle; + +// add, interleave, decimate: These set operators are vanilla SetTheory +// operators and take their normal definition. +def add; +def interleave; +def decimate; +// rotl - Rotate set left by a number of elements. +// example: (rotl mask0, 3) -> [3, 4, 5, 6, 0, 1, 2] +def rotl; +// rotl - Rotate set right by a number of elements. +// example: (rotr mask0, 3) -> [4, 5, 6, 0, 1, 2, 3] +def rotr; +// highhalf - Take only the high half of the input. +// example: (highhalf mask0) -> [4, 5, 6, 7] (assuming mask0 had 8 elements) +def highhalf; +// highhalf - Take only the low half of the input. +// example: (lowhalf mask0) -> [0, 1, 2, 3] (assuming mask0 had 8 elements) +def lowhalf; +// rev - Perform a variable-width reversal of the elements. The zero'th argument +// is a width in bits to reverse. The lanes this maps to is determined +// based on the element width of the underlying type. +// example: (rev 32, mask0) -> [3, 2, 1, 0, 7, 6, 5, 4] (if 8-bit elements) +// example: (rev 32, mask0) -> [1, 0, 3, 2] (if 16-bit elements) +def rev; +// mask0 - The initial sequence of lanes for shuffle ARG0 +def mask0 : MaskExpand; +// mask0 - The initial sequence of lanes for shuffle ARG1 +def mask1 : MaskExpand; + +def OP_NONE : Operation; +def OP_UNAVAILABLE : Operation { + let Unavailable = 1; +} + +//===----------------------------------------------------------------------===// +// Instruction definitions +//===----------------------------------------------------------------------===// + +// Every intrinsic subclasses "Inst". An intrinsic has a name, a prototype and +// a sequence of typespecs. +// +// The name is the base name of the intrinsic, for example "vget_lane". This is +// then mangled by the tblgen backend to add type information ("vget_lane_s16"). +// +// A typespec is a sequence of uppercase characters (modifiers) followed by one +// lowercase character. A typespec encodes a particular "base type" of the +// intrinsic. +// +// An example typespec is "Qs" - quad-size short - uint16x8_t. The available +// typespec codes are given below. +// +// The string given to an Inst class is a sequence of typespecs. The intrinsic +// is instantiated for every typespec in the sequence. For example "sdQsQd". +// +// The prototype is a string that defines the return type of the intrinsic +// and the type of each argument. The return type and every argument gets a +// "modifier" that can change in some way the "base type" of the intrinsic. +// +// The modifier 'd' means "default" and does not modify the base type in any +// way. The available modifiers are given below. +// +// Typespecs +// --------- +// c: char +// s: short +// i: int +// l: long +// k: 128-bit long +// f: float +// h: half-float +// d: double +// +// Typespec modifiers +// ------------------ +// S: scalar, only used for function mangling. +// U: unsigned +// Q: 128b +// H: 128b without mangling 'q' +// P: polynomial +// +// Prototype modifiers +// ------------------- +// prototype: return (arg, arg, ...) +// +// v: void +// t: best-fit integer (int/poly args) +// x: signed integer (int/float args) +// u: unsigned integer (int/float args) +// f: float (int args) +// F: double (int args) +// H: half (int args) +// d: default +// g: default, ignore 'Q' size modifier. +// j: default, force 'Q' size modifier. +// w: double width elements, same num elts +// n: double width elements, half num elts +// h: half width elements, double num elts +// q: half width elements, quad num elts +// e: half width elements, double num elts, unsigned +// m: half width elements, same num elts +// i: constant int +// l: constant uint64 +// s: scalar of element type +// z: scalar of half width element type, signed +// r: scalar of double width element type, signed +// a: scalar of element type (splat to vector type) +// b: scalar of unsigned integer/long type (int/float args) +// $: scalar of signed integer/long type (int/float args) +// y: scalar of float +// o: scalar of double +// k: default elt width, double num elts +// 2,3,4: array of default vectors +// B,C,D: array of default elts, force 'Q' size modifier. +// p: pointer type +// c: const pointer type +// 7: vector of 8-bit elements, ignore 'Q' size modifier +// 8: vector of 8-bit elements, same width as default type +// 9: vector of 8-bit elements, force 'Q' size modifier + +// Every intrinsic subclasses Inst. +class Inst <string n, string p, string t, Operation o> { + string Name = n; + string Prototype = p; + string Types = t; + string ArchGuard = ""; + + Operation Operation = o; + bit CartesianProductOfTypes = 0; + bit BigEndianSafe = 0; + bit isShift = 0; + bit isScalarShift = 0; + bit isScalarNarrowShift = 0; + bit isVCVT_N = 0; + // For immediate checks: the immediate will be assumed to specify the lane of + // a Q register. Only used for intrinsics which end up calling polymorphic + // builtins. + bit isLaneQ = 0; + + // Certain intrinsics have different names than their representative + // instructions. This field allows us to handle this correctly when we + // are generating tests. + string InstName = ""; + + // Certain intrinsics even though they are not a WOpInst or LOpInst, + // generate a WOpInst/LOpInst instruction (see below for definition + // of a WOpInst/LOpInst). For testing purposes we need to know + // this. Ex: vset_lane which outputs vmov instructions. + bit isHiddenWInst = 0; + bit isHiddenLInst = 0; +} + +// The following instruction classes are implemented via builtins. +// These declarations are used to generate Builtins.def: +// +// SInst: Instruction with signed/unsigned suffix (e.g., "s8", "u8", "p8") +// IInst: Instruction with generic integer suffix (e.g., "i8") +// WInst: Instruction with only bit size suffix (e.g., "8") +class SInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} +class IInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} +class WInst<string n, string p, string t> : Inst<n, p, t, OP_NONE> {} + +// The following instruction classes are implemented via operators +// instead of builtins. As such these declarations are only used for +// the purpose of generating tests. +// +// SOpInst: Instruction with signed/unsigned suffix (e.g., "s8", +// "u8", "p8"). +// IOpInst: Instruction with generic integer suffix (e.g., "i8"). +// WOpInst: Instruction with bit size only suffix (e.g., "8"). +// LOpInst: Logical instruction with no bit size suffix. +// NoTestOpInst: Intrinsic that has no corresponding instruction. +class SOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class IOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class WOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class LOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} +class NoTestOpInst<string n, string p, string t, Operation o> : Inst<n, p, t, o> {} diff --git a/include/clang/CodeGen/BackendUtil.h b/include/clang/CodeGen/BackendUtil.h index bb105cb533a41..3d1221a43b146 100644 --- a/include/clang/CodeGen/BackendUtil.h +++ b/include/clang/CodeGen/BackendUtil.h @@ -49,6 +49,8 @@ namespace clang { llvm::Expected<llvm::BitcodeModule> FindThinLTOModule(llvm::MemoryBufferRef MBRef); + llvm::BitcodeModule * + FindThinLTOModule(llvm::MutableArrayRef<llvm::BitcodeModule> BMs); } #endif diff --git a/include/clang/CodeGen/CGFunctionInfo.h b/include/clang/CodeGen/CGFunctionInfo.h index d1f05124d5e5e..cf64e9f3eeff8 100644 --- a/include/clang/CodeGen/CGFunctionInfo.h +++ b/include/clang/CodeGen/CGFunctionInfo.h @@ -95,6 +95,8 @@ private: bool SRetAfterThis : 1; // isIndirect() bool InReg : 1; // isDirect() || isExtend() || isIndirect() bool CanBeFlattened: 1; // isDirect() + bool SignExt : 1; // isExtend() + bool SuppressSRet : 1; // isIndirect() bool canHavePaddingType() const { return isDirect() || isExtend() || isIndirect() || isExpand(); @@ -110,13 +112,14 @@ private: } ABIArgInfo(Kind K) - : TheKind(K), PaddingInReg(false), InReg(false) { + : TheKind(K), PaddingInReg(false), InReg(false), SuppressSRet(false) { } public: ABIArgInfo() : TypeData(nullptr), PaddingType(nullptr), DirectOffset(0), - TheKind(Direct), PaddingInReg(false), InReg(false) {} + TheKind(Direct), PaddingInReg(false), InReg(false), + SuppressSRet(false) {} static ABIArgInfo getDirect(llvm::Type *T = nullptr, unsigned Offset = 0, llvm::Type *Padding = nullptr, @@ -133,15 +136,38 @@ public: AI.setInReg(true); return AI; } - static ABIArgInfo getExtend(llvm::Type *T = nullptr) { + + static ABIArgInfo getSignExtend(QualType Ty, llvm::Type *T = nullptr) { + assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType"); auto AI = ABIArgInfo(Extend); AI.setCoerceToType(T); AI.setPaddingType(nullptr); AI.setDirectOffset(0); + AI.setSignExt(true); return AI; } - static ABIArgInfo getExtendInReg(llvm::Type *T = nullptr) { - auto AI = getExtend(T); + + static ABIArgInfo getZeroExtend(QualType Ty, llvm::Type *T = nullptr) { + assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType"); + auto AI = ABIArgInfo(Extend); + AI.setCoerceToType(T); + AI.setPaddingType(nullptr); + AI.setDirectOffset(0); + AI.setSignExt(false); + return AI; + } + + // ABIArgInfo will record the argument as being extended based on the sign + // of its type. + static ABIArgInfo getExtend(QualType Ty, llvm::Type *T = nullptr) { + assert(Ty->isIntegralOrEnumerationType() && "Unexpected QualType"); + if (Ty->hasSignedIntegerRepresentation()) + return getSignExtend(Ty, T); + return getZeroExtend(Ty, T); + } + + static ABIArgInfo getExtendInReg(QualType Ty, llvm::Type *T = nullptr) { + auto AI = getExtend(Ty, T); AI.setInReg(true); return AI; } @@ -254,6 +280,15 @@ public: DirectOffset = Offset; } + bool isSignExt() const { + assert(isExtend() && "Invalid kind!"); + return SignExt; + } + void setSignExt(bool SExt) { + assert(isExtend() && "Invalid kind!"); + SignExt = SExt; + } + llvm::Type *getPaddingType() const { return (canHavePaddingType() ? PaddingType : nullptr); } @@ -351,7 +386,7 @@ public: AllocaFieldIndex = FieldIndex; } - /// \brief Return true if this field of an inalloca struct should be returned + /// Return true if this field of an inalloca struct should be returned /// to implement a struct return calling convention. bool getInAllocaSRet() const { assert(isInAlloca() && "Invalid kind!"); @@ -373,6 +408,16 @@ public: CanBeFlattened = Flatten; } + bool getSuppressSRet() const { + assert(isIndirect() && "Invalid kind!"); + return SuppressSRet; + } + + void setSuppressSRet(bool Suppress) { + assert(isIndirect() && "Invalid kind!"); + SuppressSRet = Suppress; + } + void dump() const; }; @@ -461,7 +506,7 @@ class CGFunctionInfo final unsigned EffectiveCallingConvention : 8; /// The clang::CallingConv that this was originally created with. - unsigned ASTCallingConvention : 7; + unsigned ASTCallingConvention : 6; /// Whether this is an instance method. unsigned InstanceMethod : 1; @@ -482,6 +527,9 @@ class CGFunctionInfo final unsigned HasRegParm : 1; unsigned RegParm : 3; + /// Whether this function has nocf_check attribute. + unsigned NoCfCheck : 1; + RequiredArgs Required; /// The struct representing all arguments passed in memory. Only used when @@ -566,6 +614,9 @@ public: /// Whether this function no longer saves caller registers. bool isNoCallerSavedRegs() const { return NoCallerSavedRegs; } + /// Whether this function has nocf_check attribute. + bool isNoCfCheck() const { return NoCfCheck; } + /// getASTCallingConvention() - Return the AST-specified calling /// convention. CallingConv getASTCallingConvention() const { @@ -591,7 +642,7 @@ public: FunctionType::ExtInfo getExtInfo() const { return FunctionType::ExtInfo(isNoReturn(), getHasRegParm(), getRegParm(), getASTCallingConvention(), isReturnsRetained(), - isNoCallerSavedRegs()); + isNoCallerSavedRegs(), isNoCfCheck()); } CanQualType getReturnType() const { return getArgsBuffer()[0].type; } @@ -609,10 +660,10 @@ public: return getExtParameterInfos()[argIndex]; } - /// \brief Return true if this function uses inalloca arguments. + /// Return true if this function uses inalloca arguments. bool usesInAlloca() const { return ArgStruct; } - /// \brief Get the struct type used to represent all the arguments in memory. + /// Get the struct type used to represent all the arguments in memory. llvm::StructType *getArgStruct() const { return ArgStruct; } CharUnits getArgStructAlignment() const { return CharUnits::fromQuantity(ArgStructAlign); @@ -631,6 +682,7 @@ public: ID.AddBoolean(NoCallerSavedRegs); ID.AddBoolean(HasRegParm); ID.AddInteger(RegParm); + ID.AddBoolean(NoCfCheck); ID.AddInteger(Required.getOpaqueData()); ID.AddBoolean(HasExtParameterInfos); if (HasExtParameterInfos) { @@ -657,6 +709,7 @@ public: ID.AddBoolean(info.getNoCallerSavedRegs()); ID.AddBoolean(info.getHasRegParm()); ID.AddInteger(info.getRegParm()); + ID.AddBoolean(info.getNoCfCheck()); ID.AddInteger(required.getOpaqueData()); ID.AddBoolean(!paramInfos.empty()); if (!paramInfos.empty()) { diff --git a/include/clang/CodeGen/ConstantInitBuilder.h b/include/clang/CodeGen/ConstantInitBuilder.h index 113d86d82c108..f2e78adb8cebb 100644 --- a/include/clang/CodeGen/ConstantInitBuilder.h +++ b/include/clang/CodeGen/ConstantInitBuilder.h @@ -266,7 +266,7 @@ public: /// (2) finishing the entire builder. /// /// This is useful for emitting certain kinds of structure which - /// contain some sort of summary field, generaly a count, before any + /// contain some sort of summary field, generally a count, before any /// of the data. By emitting a placeholder first, the structure can /// be emitted eagerly. PlaceholderPosition addPlaceholder() { @@ -295,7 +295,7 @@ public: slot = value; } - /// Produce an address which will eventually point to the the next + /// Produce an address which will eventually point to the next /// position to be filled. This is computed with an indexed /// getelementptr rather than by computing offsets. /// diff --git a/include/clang/CodeGen/SwiftCallingConv.h b/include/clang/CodeGen/SwiftCallingConv.h index 23db43e6739c4..45b3145ed9f1a 100644 --- a/include/clang/CodeGen/SwiftCallingConv.h +++ b/include/clang/CodeGen/SwiftCallingConv.h @@ -1,4 +1,4 @@ -//==-- SwiftCallingConv.h - Swift ABI lowering -----------------------------==// +//==-- SwiftCallingConv.h - Swift ABI lowering ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -116,6 +116,12 @@ private: void splitVectorEntry(unsigned index); }; +/// Should an aggregate which expands to the given type sequence +/// be passed/returned indirectly under swiftcall? +bool shouldPassIndirectly(CodeGenModule &CGM, + ArrayRef<llvm::Type*> types, + bool asReturnValue); + /// Return the maximum voluntary integer size for the current target. CharUnits getMaximumVoluntaryIntegerSize(CodeGenModule &CGM); @@ -146,9 +152,15 @@ void legalizeVectorType(CodeGenModule &CGM, CharUnits vectorSize, llvm::VectorType *vectorTy, llvm::SmallVectorImpl<llvm::Type*> &types); -/// Should a C++ record type be passed and returned indirectly? -bool shouldPassCXXRecordIndirectly(CodeGenModule &CGM, - const CXXRecordDecl *record); +/// Is the given record type required to be passed and returned indirectly +/// because of language restrictions? +/// +/// This considers *only* mandatory indirectness due to language restrictions, +/// such as C++'s non-trivially-copyable types and Objective-C's __weak +/// references. A record for which this returns true may still be passed +/// indirectly for other reasons, such as being too large to fit in a +/// reasonable number of registers. +bool mustPassRecordIndirectly(CodeGenModule &CGM, const RecordDecl *record); /// Classify the rules for how to return a particular type. ABIArgInfo classifyReturnType(CodeGenModule &CGM, CanQualType type); @@ -160,7 +172,7 @@ ABIArgInfo classifyArgumentType(CodeGenModule &CGM, CanQualType type); /// private interface for Clang. void computeABIInfo(CodeGenModule &CGM, CGFunctionInfo &FI); -/// Is swifterror lowered to a register by the target ABI. +/// Is swifterror lowered to a register by the target ABI? bool isSwiftErrorLoweredInRegister(CodeGenModule &CGM); } // end namespace swiftcall diff --git a/include/clang/Config/config.h.cmake b/include/clang/Config/config.h.cmake index daac9b7b45d1a..1d624450b9d90 100644 --- a/include/clang/Config/config.h.cmake +++ b/include/clang/Config/config.h.cmake @@ -11,6 +11,12 @@ /* Default linker to use. */ #define CLANG_DEFAULT_LINKER "${CLANG_DEFAULT_LINKER}" +/* Default C/ObjC standard to use. */ +#cmakedefine CLANG_DEFAULT_STD_C LangStandard::lang_${CLANG_DEFAULT_STD_C} + +/* Default C++/ObjC++ standard to use. */ +#cmakedefine CLANG_DEFAULT_STD_CXX LangStandard::lang_${CLANG_DEFAULT_STD_CXX} + /* Default C++ stdlib to use. */ #define CLANG_DEFAULT_CXX_STDLIB "${CLANG_DEFAULT_CXX_STDLIB}" @@ -35,6 +41,10 @@ /* Directories clang will search for headers */ #define C_INCLUDE_DIRS "${C_INCLUDE_DIRS}" +/* Directories clang will search for configuration files */ +#cmakedefine CLANG_CONFIG_FILE_SYSTEM_DIR "${CLANG_CONFIG_FILE_SYSTEM_DIR}" +#cmakedefine CLANG_CONFIG_FILE_USER_DIR "${CLANG_CONFIG_FILE_USER_DIR}" + /* Default <path> to all compiler invocations for --sysroot=<path>. */ #define DEFAULT_SYSROOT "${DEFAULT_SYSROOT}" @@ -62,6 +72,9 @@ /* enable x86 relax relocations by default */ #cmakedefine01 ENABLE_X86_RELAX_RELOCATIONS +/* Enable the experimental new pass manager by default */ +#cmakedefine01 ENABLE_EXPERIMENTAL_NEW_PASS_MANAGER + /* Enable each functionality of modules */ #cmakedefine01 CLANG_ENABLE_ARCMT #cmakedefine01 CLANG_ENABLE_OBJC_REWRITER diff --git a/include/clang/CrossTU/CrossTranslationUnit.h b/include/clang/CrossTU/CrossTranslationUnit.h index f2a1690250090..041f1a8eea590 100644 --- a/include/clang/CrossTU/CrossTranslationUnit.h +++ b/include/clang/CrossTU/CrossTranslationUnit.h @@ -62,7 +62,7 @@ private: int LineNo; }; -/// \brief This function parses an index file that determines which +/// This function parses an index file that determines which /// translation unit contains which definition. /// /// The index file format is the following: @@ -75,7 +75,7 @@ parseCrossTUIndex(StringRef IndexPath, StringRef CrossTUDir); std::string createCrossTUIndexString(const llvm::StringMap<std::string> &Index); -/// \brief This class is used for tools that requires cross translation +/// This class is used for tools that requires cross translation /// unit capability. /// /// This class can load function definitions from external AST files. @@ -90,7 +90,7 @@ public: CrossTranslationUnitContext(CompilerInstance &CI); ~CrossTranslationUnitContext(); - /// \brief This function loads a function definition from an external AST + /// This function loads a function definition from an external AST /// file and merge it into the original AST. /// /// This method should only be used on functions that have no definitions in @@ -110,7 +110,7 @@ public: getCrossTUDefinition(const FunctionDecl *FD, StringRef CrossTUDir, StringRef IndexName); - /// \brief This function loads a function definition from an external AST + /// This function loads a function definition from an external AST /// file. /// /// A function definition with the same declaration will be looked up in the @@ -126,17 +126,17 @@ public: StringRef CrossTUDir, StringRef IndexName); - /// \brief This function merges a definition from a separate AST Unit into + /// This function merges a definition from a separate AST Unit into /// the current one which was created by the compiler instance that /// was passed to the constructor. /// /// \return Returns the resulting definition or an error. llvm::Expected<const FunctionDecl *> importDefinition(const FunctionDecl *FD); - /// \brief Get a name to identify a function. + /// Get a name to identify a function. static std::string getLookupName(const NamedDecl *ND); - /// \brief Emit diagnostics for the user for potential configuration errors. + /// Emit diagnostics for the user for potential configuration errors. void emitCrossTUDiagnostics(const IndexError &IE); private: diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index 72456d34a0d95..723fbbed3598a 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -1,4 +1,4 @@ -//===--- Action.h - Abstract compilation steps ------------------*- C++ -*-===// +//===- Action.h - Abstract compilation steps --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,20 +10,23 @@ #ifndef LLVM_CLANG_DRIVER_ACTION_H #define LLVM_CLANG_DRIVER_ACTION_H -#include "clang/Basic/Cuda.h" +#include "clang/Basic/LLVM.h" #include "clang/Driver/Types.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include <string> namespace llvm { +namespace opt { -class StringRef; +class Arg; -namespace opt { - class Arg; -} -} +} // namespace opt +} // namespace llvm namespace clang { namespace driver { @@ -44,11 +47,11 @@ class ToolChain; /// actions via MakeAction(). class Action { public: - typedef ActionList::size_type size_type; - typedef ActionList::iterator input_iterator; - typedef ActionList::const_iterator input_const_iterator; - typedef llvm::iterator_range<input_iterator> input_range; - typedef llvm::iterator_range<input_const_iterator> input_const_range; + using size_type = ActionList::size_type; + using input_iterator = ActionList::iterator; + using input_const_iterator = ActionList::const_iterator; + using input_range = llvm::iterator_range<input_iterator>; + using input_const_range = llvm::iterator_range<input_const_iterator>; enum ActionClass { InputClass = 0, @@ -78,11 +81,14 @@ public: // to designate the host offloading tool chain. enum OffloadKind { OFK_None = 0x00, + // The host offloading tool chain. OFK_Host = 0x01, + // The device offloading tool chains - one bit for each programming model. OFK_Cuda = 0x02, OFK_OpenMP = 0x04, + OFK_HIP = 0x08, }; static const char *getClassName(ActionClass AC); @@ -110,8 +116,10 @@ protected: /// Multiple programming models may be supported simultaneously by the same /// host. unsigned ActiveOffloadKindMask = 0u; + /// Offloading kind of the device. OffloadKind OffloadingDeviceKind = OFK_None; + /// The Offloading architecture associated with this action. const char *OffloadingArch = nullptr; @@ -149,6 +157,7 @@ public: void setCannotBeCollapsedWithNextDependentAction() { CanBeCollapsedWithNextDependentAction = false; } + /// Return true if this function can be collapsed with others. bool isCollapsingWithNextDependentActionLegal() const { return CanBeCollapsedWithNextDependentAction; @@ -156,22 +165,26 @@ public: /// Return a string containing the offload kind of the action. std::string getOffloadingKindPrefix() const; + /// Return a string that can be used as prefix in order to generate unique /// files for each offloading kind. By default, no prefix is used for /// non-device kinds, except if \a CreatePrefixForHost is set. static std::string GetOffloadingFileNamePrefix(OffloadKind Kind, - llvm::StringRef NormalizedTriple, + StringRef NormalizedTriple, bool CreatePrefixForHost = false); + /// Return a string containing a offload kind name. static StringRef GetOffloadKindName(OffloadKind Kind); /// Set the device offload info of this action and propagate it to its /// dependences. void propagateDeviceOffloadInfo(OffloadKind OKind, const char *OArch); + /// Append the host offload info of this action and propagate it to its /// dependences. void propagateHostOffloadInfo(unsigned OKinds, const char *OArch); + /// Set the offload info of this action to be the same as the provided action, /// and propagate it to its dependences. void propagateOffloadInfo(const Action *A); @@ -179,6 +192,7 @@ public: unsigned getOffloadingHostActiveKinds() const { return ActiveOffloadKindMask; } + OffloadKind getOffloadingDeviceKind() const { return OffloadingDeviceKind; } const char *getOffloadingArch() const { return OffloadingArch; } @@ -196,9 +210,10 @@ public: }; class InputAction : public Action { - virtual void anchor(); const llvm::opt::Arg &Input; + virtual void anchor(); + public: InputAction(const llvm::opt::Arg &Input, types::ID Type); @@ -211,6 +226,7 @@ public: class BindArchAction : public Action { virtual void anchor(); + /// The architecture to bind, or 0 if the default architecture /// should be bound. StringRef ArchName; @@ -236,9 +252,9 @@ public: /// toolchain, and offload kind to each action. class DeviceDependences final { public: - typedef SmallVector<const ToolChain *, 3> ToolChainList; - typedef SmallVector<const char *, 3> BoundArchList; - typedef SmallVector<OffloadKind, 3> OffloadKindList; + using ToolChainList = SmallVector<const ToolChain *, 3>; + using BoundArchList = SmallVector<const char *, 3>; + using OffloadKindList = SmallVector<OffloadKind, 3>; private: // Lists that keep the information for each dependency. All the lists are @@ -248,10 +264,13 @@ public: /// The dependence actions. ActionList DeviceActions; + /// The offloading toolchains that should be used with the action. ToolChainList DeviceToolChains; + /// The architectures that should be used with this action. BoundArchList DeviceBoundArchs; + /// The offload kind of each dependence. OffloadKindList DeviceOffloadKinds; @@ -262,12 +281,12 @@ public: OffloadKind OKind); /// Get each of the individual arrays. - const ActionList &getActions() const { return DeviceActions; }; - const ToolChainList &getToolChains() const { return DeviceToolChains; }; - const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; }; + const ActionList &getActions() const { return DeviceActions; } + const ToolChainList &getToolChains() const { return DeviceToolChains; } + const BoundArchList &getBoundArchs() const { return DeviceBoundArchs; } const OffloadKindList &getOffloadKinds() const { return DeviceOffloadKinds; - }; + } }; /// Type used to communicate host actions. It associates bound architecture, @@ -275,10 +294,13 @@ public: class HostDependence final { /// The dependence action. Action &HostAction; + /// The offloading toolchain that should be used with the action. const ToolChain &HostToolChain; + /// The architectures that should be used with this action. const char *HostBoundArch = nullptr; + /// The offload kind of each dependence. unsigned HostOffloadKinds = 0u; @@ -286,19 +308,20 @@ public: HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, const unsigned OffloadKinds) : HostAction(A), HostToolChain(TC), HostBoundArch(BoundArch), - HostOffloadKinds(OffloadKinds){}; + HostOffloadKinds(OffloadKinds) {} + /// Constructor version that obtains the offload kinds from the device /// dependencies. HostDependence(Action &A, const ToolChain &TC, const char *BoundArch, const DeviceDependences &DDeps); - Action *getAction() const { return &HostAction; }; - const ToolChain *getToolChain() const { return &HostToolChain; }; - const char *getBoundArch() const { return HostBoundArch; }; - unsigned getOffloadKinds() const { return HostOffloadKinds; }; + Action *getAction() const { return &HostAction; } + const ToolChain *getToolChain() const { return &HostToolChain; } + const char *getBoundArch() const { return HostBoundArch; } + unsigned getOffloadKinds() const { return HostOffloadKinds; } }; - typedef llvm::function_ref<void(Action *, const ToolChain *, const char *)> - OffloadActionWorkTy; + using OffloadActionWorkTy = + llvm::function_ref<void(Action *, const ToolChain *, const char *)>; private: /// The host offloading toolchain that should be used with the action. @@ -349,6 +372,7 @@ public: class JobAction : public Action { virtual void anchor(); + protected: JobAction(ActionClass Kind, Action *Input, types::ID Type); JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type); @@ -362,6 +386,7 @@ public: class PreprocessJobAction : public JobAction { void anchor() override; + public: PreprocessJobAction(Action *Input, types::ID OutputType); @@ -372,6 +397,7 @@ public: class PrecompileJobAction : public JobAction { void anchor() override; + public: PrecompileJobAction(Action *Input, types::ID OutputType); @@ -382,6 +408,7 @@ public: class AnalyzeJobAction : public JobAction { void anchor() override; + public: AnalyzeJobAction(Action *Input, types::ID OutputType); @@ -392,6 +419,7 @@ public: class MigrateJobAction : public JobAction { void anchor() override; + public: MigrateJobAction(Action *Input, types::ID OutputType); @@ -402,6 +430,7 @@ public: class CompileJobAction : public JobAction { void anchor() override; + public: CompileJobAction(Action *Input, types::ID OutputType); @@ -412,6 +441,7 @@ public: class BackendJobAction : public JobAction { void anchor() override; + public: BackendJobAction(Action *Input, types::ID OutputType); @@ -422,6 +452,7 @@ public: class AssembleJobAction : public JobAction { void anchor() override; + public: AssembleJobAction(Action *Input, types::ID OutputType); @@ -432,6 +463,7 @@ public: class LinkJobAction : public JobAction { void anchor() override; + public: LinkJobAction(ActionList &Inputs, types::ID Type); @@ -442,6 +474,7 @@ public: class LipoJobAction : public JobAction { void anchor() override; + public: LipoJobAction(ActionList &Inputs, types::ID Type); @@ -452,6 +485,7 @@ public: class DsymutilJobAction : public JobAction { void anchor() override; + public: DsymutilJobAction(ActionList &Inputs, types::ID Type); @@ -462,8 +496,10 @@ public: class VerifyJobAction : public JobAction { void anchor() override; + public: VerifyJobAction(ActionClass Kind, Action *Input, types::ID Type); + static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass || A->getKind() == VerifyPCHJobClass; @@ -472,8 +508,10 @@ public: class VerifyDebugInfoJobAction : public VerifyJobAction { void anchor() override; + public: VerifyDebugInfoJobAction(Action *Input, types::ID Type); + static bool classof(const Action *A) { return A->getKind() == VerifyDebugInfoJobClass; } @@ -481,8 +519,10 @@ public: class VerifyPCHJobAction : public VerifyJobAction { void anchor() override; + public: VerifyPCHJobAction(Action *Input, types::ID Type); + static bool classof(const Action *A) { return A->getKind() == VerifyPCHJobClass; } @@ -507,18 +547,21 @@ public: /// Type that provides information about the actions that depend on this /// unbundling action. struct DependentActionInfo final { - /// \brief The tool chain of the dependent action. + /// The tool chain of the dependent action. const ToolChain *DependentToolChain = nullptr; - /// \brief The bound architecture of the dependent action. + + /// The bound architecture of the dependent action. StringRef DependentBoundArch; - /// \brief The offload kind of the dependent action. + + /// The offload kind of the dependent action. const OffloadKind DependentOffloadKind = OFK_None; + DependentActionInfo(const ToolChain *DependentToolChain, StringRef DependentBoundArch, const OffloadKind DependentOffloadKind) : DependentToolChain(DependentToolChain), DependentBoundArch(DependentBoundArch), - DependentOffloadKind(DependentOffloadKind){}; + DependentOffloadKind(DependentOffloadKind) {} }; private: @@ -546,7 +589,7 @@ public: } }; -} // end namespace driver -} // end namespace clang +} // namespace driver +} // namespace clang -#endif +#endif // LLVM_CLANG_DRIVER_ACTION_H diff --git a/include/clang/Driver/CC1Options.td b/include/clang/Driver/CC1Options.td index 7dea88b62cc19..7cb9724a57e19 100644 --- a/include/clang/Driver/CC1Options.td +++ b/include/clang/Driver/CC1Options.td @@ -36,6 +36,10 @@ def triple_EQ : Joined<["-"], "triple=">, Alias<triple>; def mfpmath : Separate<["-"], "mfpmath">, HelpText<"Which unit to use for fp math">; +def fpadding_on_unsigned_fixed_point : Flag<["-"], "fpadding-on-unsigned-fixed-point">, + HelpText<"Force each unsigned fixed point type to have an extra bit of padding to align their scales with those of signed fixed point types">; +def fno_padding_on_unsigned_fixed_point : Flag<["-"], "fno-padding-on-unsigned-fixed-point">; + //===----------------------------------------------------------------------===// // Analyzer Options //===----------------------------------------------------------------------===// @@ -275,8 +279,6 @@ def split_stacks : Flag<["-"], "split-stacks">, HelpText<"Try to use a split stack if possible.">; def mno_zero_initialized_in_bss : Flag<["-"], "mno-zero-initialized-in-bss">, HelpText<"Do not put zero initialized data in the BSS">; -def backend_option : Separate<["-"], "backend-option">, - HelpText<"Additional arguments to forward to LLVM backend (during code gen)">; def mregparm : Separate<["-"], "mregparm">, HelpText<"Limit the number of registers available for integer arguments">; def munwind_tables : Flag<["-"], "munwind-tables">, @@ -447,6 +449,8 @@ def no_code_completion_ns_level_decls : Flag<["-"], "no-code-completion-ns-level HelpText<"Do not include declarations inside namespaces (incl. global namespace) in the code-completion results.">; def code_completion_brief_comments : Flag<["-"], "code-completion-brief-comments">, HelpText<"Include brief documentation comments in code-completion results.">; +def code_completion_with_fixits : Flag<["-"], "code-completion-with-fixits">, + HelpText<"Include code completion results which require small fix-its.">; def disable_free : Flag<["-"], "disable-free">, HelpText<"Disable freeing of memory on exit">; def discard_value_names : Flag<["-"], "discard-value-names">, @@ -533,6 +537,8 @@ def ast_dump : Flag<["-"], "ast-dump">, HelpText<"Build ASTs and then debug dump them">; def ast_dump_all : Flag<["-"], "ast-dump-all">, HelpText<"Build ASTs and then debug dump them, forcing deserialization">; +def templight_dump : Flag<["-"], "templight-dump">, + HelpText<"Dump templight information to stdout">; 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">, @@ -561,6 +567,8 @@ def rewrite_macros : Flag<["-"], "rewrite-macros">, HelpText<"Expand macros without full preprocessing">; def migrate : Flag<["-"], "migrate">, HelpText<"Migrate source code">; +def compiler_options_dump : Flag<["-"], "compiler-options-dump">, + HelpText<"Dump the compiler configuration options">; } def emit_llvm_uselists : Flag<["-"], "emit-llvm-uselists">, @@ -599,13 +607,14 @@ def fixit_to_temp : Flag<["-"], "fixit-to-temporary">, def foverride_record_layout_EQ : Joined<["-"], "foverride-record-layout=">, HelpText<"Override record layouts with those in the given file">; -def find_pch_source_EQ : Joined<["-"], "find-pch-source=">, - HelpText<"When building a pch, try to find the input file in include " - "directories, as if it had been included by the argument passed " - "to this flag.">; +def pch_through_header_EQ : Joined<["-"], "pch-through-header=">, + HelpText<"Stop PCH generation after including this file. When using a PCH, " + "skip tokens until after this file is included.">; def fno_pch_timestamp : Flag<["-"], "fno-pch-timestamp">, HelpText<"Disable inclusion of timestamp in precompiled headers">; - +def building_pch_with_obj : Flag<["-"], "building-pch-with-obj">, + HelpText<"This compilation is part of building a PCH with corresponding object file.">; + def aligned_alloc_unavailable : Flag<["-"], "faligned-alloc-unavailable">, HelpText<"Aligned allocation/deallocation functions are unavailable">; @@ -619,6 +628,8 @@ def version : Flag<["-"], "version">, HelpText<"Print the compiler version">; def main_file_name : Separate<["-"], "main-file-name">, HelpText<"Main file name to use for debug info">; +def split_dwarf_file : Separate<["-"], "split-dwarf-file">, + HelpText<"File name to use for split dwarf debug info output">; } @@ -628,8 +639,6 @@ def fexternc_nounwind : Flag<["-"], "fexternc-nounwind">, HelpText<"Assume all functions with C linkage do not unwind">; def enable_split_dwarf : Flag<["-"], "enable-split-dwarf">, HelpText<"Use split dwarf/Fission">; -def split_dwarf_file : Separate<["-"], "split-dwarf-file">, - HelpText<"File name to use for split dwarf debug info output">; def fno_wchar : Flag<["-"], "fno-wchar">, HelpText<"Disable C++ builtin type wchar_t">; def fconstant_string_class : Separate<["-"], "fconstant-string-class">, @@ -645,6 +654,8 @@ def disable_objc_default_synthesize_properties : Flag<["-"], "disable-objc-defau HelpText<"disable the default synthesis of Objective-C properties">; def fencode_extended_block_signature : Flag<["-"], "fencode-extended-block-signature">, HelpText<"enable extended encoding of block type signature">; +def function_alignment : Separate<["-"], "function-alignment">, + HelpText<"default alignment for functions">; def pic_level : Separate<["-"], "pic-level">, HelpText<"Value for __PIC__">; def pic_is_pie : Flag<["-"], "pic-is-pie">, @@ -705,8 +716,6 @@ def fobjc_subscripting_legacy_runtime : Flag<["-"], "fobjc-subscripting-legacy-r 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 fnative_half_type: Flag<["-"], "fnative-half-type">, HelpText<"Use the native half type for __fp16 instead of promoting to float">; def fnative_half_arguments_and_returns : Flag<["-"], "fnative-half-arguments-and-returns">, diff --git a/include/clang/Driver/CLCompatOptions.td b/include/clang/Driver/CLCompatOptions.td index c1f0a89b5dc8f..78667851ca19c 100644 --- a/include/clang/Driver/CLCompatOptions.td +++ b/include/clang/Driver/CLCompatOptions.td @@ -61,6 +61,8 @@ def _SLASH_Brepro_ : CLFlag<"Brepro-">, def _SLASH_C : CLFlag<"C">, HelpText<"Don't discard comments when preprocessing">, Alias<C>; def _SLASH_c : CLFlag<"c">, HelpText<"Compile only">, Alias<c>; +def _SLASH_d1PP : CLFlag<"d1PP">, + HelpText<"Retain macro definitions in /E mode">, Alias<dD>; def _SLASH_d1reportAllClassLayout : CLFlag<"d1reportAllClassLayout">, HelpText<"Dump record layout information">, Alias<fdump_record_layouts>; def _SLASH_diagnostics_caret : CLFlag<"diagnostics:caret">, @@ -164,6 +166,9 @@ def _SLASH_wd4996 : CLFlag<"wd4996">, Alias<W_Joined>, AliasArgs<["no-deprecated-declarations"]>; def _SLASH_vd : CLJoined<"vd">, HelpText<"Control vtordisp placement">, Alias<vtordisp_mode_EQ>; +def _SLASH_X : CLFlag<"X">, + HelpText<"Don't add %INCLUDE% to the include search path">, + Alias<nostdlibinc>; def _SLASH_Zc_sizedDealloc : CLFlag<"Zc:sizedDealloc">, HelpText<"Enable C++14 sized global deallocation functions">, Alias<fsized_deallocation>; @@ -235,10 +240,12 @@ def _SLASH_Fi : CLCompileJoined<"Fi">, def _SLASH_Fo : CLCompileJoined<"Fo">, HelpText<"Set output object file, or directory (ends in / or \\) (with /c)">, MetaVarName<"<file or directory>">; +def _SLASH_Guard : CLJoined<"guard:">, + HelpText<"Enable Control Flow Guard with /guard:cf">; def _SLASH_GX : CLFlag<"GX">, HelpText<"Enable exception handling">; def _SLASH_GX_ : CLFlag<"GX-">, - HelpText<"Enable exception handling">; + HelpText<"Disable exception handling">; def _SLASH_imsvc : CLJoinedOrSeparate<"imsvc">, HelpText<"Add directory to system include search path, as if part of %INCLUDE%">, MetaVarName<"<dir>">; @@ -324,18 +331,20 @@ def _SLASH_kernel_ : CLIgnoredFlag<"kernel-">; def _SLASH_nologo : CLIgnoredFlag<"nologo">; def _SLASH_Og : CLIgnoredFlag<"Og">; def _SLASH_openmp_ : CLIgnoredFlag<"openmp-">; +def _SLASH_permissive_ : CLIgnoredFlag<"permissive-">; def _SLASH_RTC : CLIgnoredJoined<"RTC">; def _SLASH_sdl : CLIgnoredFlag<"sdl">; def _SLASH_sdl_ : CLIgnoredFlag<"sdl-">; def _SLASH_utf8 : CLIgnoredFlag<"utf-8">, HelpText<"Set source and runtime encoding to UTF-8 (default)">; def _SLASH_w : CLIgnoredJoined<"w">; +def _SLASH_Zc___cplusplus : CLIgnoredFlag<"Zc:__cplusplus">; 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_Zc_ternary : CLIgnoredFlag<"Zc:ternary">; +def _SLASH_Zc_wchar_t : CLIgnoredFlag<"Zc:wchar_t">; def _SLASH_Zm : CLIgnoredJoined<"Zm">; def _SLASH_Zo : CLIgnoredFlag<"Zo">; def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">; @@ -344,6 +353,8 @@ def _SLASH_Zo_ : CLIgnoredFlag<"Zo-">; // Unsupported: def _SLASH_AI : CLJoined<"AI">; +def _SLASH_Bt : CLFlag<"Bt">; +def _SLASH_Bt_plus : CLFlag<"Bt+">; def _SLASH_clr : CLJoined<"clr">; def _SLASH_doc : CLJoined<"doc">; def _SLASH_FA_joined : CLJoined<"FA">; @@ -364,7 +375,6 @@ def _SLASH_GL_ : CLFlag<"GL-">; def _SLASH_Gm : CLFlag<"Gm">; def _SLASH_Gm_ : CLFlag<"Gm-">; def _SLASH_GT : CLFlag<"GT">; -def _SLASH_Guard : CLJoined<"guard:">; def _SLASH_GZ : CLFlag<"GZ">; def _SLASH_H : CLFlag<"H">; def _SLASH_homeparams : CLFlag<"homeparams">; @@ -382,7 +392,6 @@ def _SLASH_u : CLFlag<"u">; def _SLASH_V : CLFlag<"V">; def _SLASH_WL : CLFlag<"WL">; def _SLASH_Wp64 : CLFlag<"Wp64">; -def _SLASH_X : CLFlag<"X">; def _SLASH_Yd : CLFlag<"Yd">; def _SLASH_Yl : CLJoined<"Yl">; def _SLASH_Za : CLFlag<"Za">; diff --git a/include/clang/Driver/Compilation.h b/include/clang/Driver/Compilation.h index 89c0def6c57a0..20eb07f6de8bd 100644 --- a/include/clang/Driver/Compilation.h +++ b/include/clang/Driver/Compilation.h @@ -1,4 +1,4 @@ -//===--- Compilation.h - Compilation Task Data Structure --------*- C++ -*-===// +//===- Compilation.h - Compilation Task Data Structure ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,24 +10,36 @@ #ifndef LLVM_CLANG_DRIVER_COMPILATION_H #define LLVM_CLANG_DRIVER_COMPILATION_H +#include "clang/Basic/LLVM.h" #include "clang/Driver/Action.h" #include "clang/Driver/Job.h" #include "clang/Driver/Util.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Option/Option.h" +#include <cassert> +#include <iterator> #include <map> +#include <memory> +#include <utility> +#include <vector> namespace llvm { namespace opt { - class DerivedArgList; - class InputArgList; -} -} + +class DerivedArgList; +class InputArgList; + +} // namespace opt +} // namespace llvm namespace clang { namespace driver { - class Driver; - class JobList; - class ToolChain; + +class Driver; +class ToolChain; /// Compilation - A set of tasks to perform for a single driver /// invocation. @@ -40,7 +52,7 @@ class Compilation { /// A mask of all the programming models the host has to support in the /// current compilation. - unsigned ActiveOffloadMask; + unsigned ActiveOffloadMask = 0; /// Array with the toolchains of offloading host and devices in the order they /// were requested by the user. We are preserving that order in case the code @@ -73,6 +85,11 @@ class Compilation { const ToolChain *TC = nullptr; StringRef BoundArch; Action::OffloadKind DeviceOffloadKind = Action::OFK_None; + + TCArgsKey(const ToolChain *TC, StringRef BoundArch, + Action::OffloadKind DeviceOffloadKind) + : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {} + bool operator<(const TCArgsKey &K) const { if (TC < K.TC) return true; @@ -83,9 +100,6 @@ class Compilation { return true; return false; } - TCArgsKey(const ToolChain *TC, StringRef BoundArch, - Action::OffloadKind DeviceOffloadKind) - : TC(TC), BoundArch(BoundArch), DeviceOffloadKind(DeviceOffloadKind) {} }; std::map<TCArgsKey, llvm::opt::DerivedArgList *> TCArgs; @@ -103,11 +117,14 @@ class Compilation { std::vector<Optional<StringRef>> Redirects; /// Whether we're compiling for diagnostic purposes. - bool ForDiagnostics; + bool ForDiagnostics = false; /// Whether an error during the parsing of the input args. bool ContainsError; + /// Whether to keep temporary files regardless of -save-temps. + bool ForceKeepTempFiles = false; + public: Compilation(const Driver &D, const ToolChain &DefaultToolChain, llvm::opt::InputArgList *Args, @@ -123,12 +140,12 @@ public: } /// Iterator that visits device toolchains of a given kind. - typedef const std::multimap<Action::OffloadKind, - const ToolChain *>::const_iterator - const_offload_toolchains_iterator; - typedef std::pair<const_offload_toolchains_iterator, - const_offload_toolchains_iterator> - const_offload_toolchains_range; + using const_offload_toolchains_iterator = + const std::multimap<Action::OffloadKind, + const ToolChain *>::const_iterator; + using const_offload_toolchains_range = + std::pair<const_offload_toolchains_iterator, + const_offload_toolchains_iterator>; template <Action::OffloadKind Kind> const_offload_toolchains_range getOffloadToolChains() const { @@ -289,7 +306,7 @@ public: void Redirect(ArrayRef<Optional<StringRef>> Redirects); }; -} // end namespace driver -} // end namespace clang +} // namespace driver +} // namespace clang -#endif +#endif // LLVM_CLANG_DRIVER_COMPILATION_H diff --git a/include/clang/Driver/Distro.h b/include/clang/Driver/Distro.h index 4ab4e2ae99370..7b34a0925603e 100644 --- a/include/clang/Driver/Distro.h +++ b/include/clang/Driver/Distro.h @@ -61,6 +61,7 @@ public: UbuntuZesty, UbuntuArtful, UbuntuBionic, + UbuntuCosmic, UnknownDistro }; @@ -114,7 +115,7 @@ public: } bool IsUbuntu() const { - return DistroVal >= UbuntuHardy && DistroVal <= UbuntuBionic; + return DistroVal >= UbuntuHardy && DistroVal <= UbuntuCosmic; } bool IsAlpineLinux() const { diff --git a/include/clang/Driver/Driver.h b/include/clang/Driver/Driver.h index a3662872a9531..017248c3690f1 100644 --- a/include/clang/Driver/Driver.h +++ b/include/clang/Driver/Driver.h @@ -19,6 +19,8 @@ #include "clang/Driver/Util.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/StringSaver.h" #include <list> #include <map> @@ -26,14 +28,6 @@ namespace llvm { class Triple; - -namespace opt { - class Arg; - class ArgList; - class DerivedArgList; - class InputArgList; - class OptTable; -} } namespace clang { @@ -138,6 +132,12 @@ public: /// The path to the compiler resource directory. std::string ResourceDir; + /// System directory for config files. + std::string SystemConfigDir; + + /// User directory for config files. + std::string UserConfigDir; + /// A prefix directory used to emulate a limited subset of GCC's '-Bprefix' /// functionality. /// FIXME: This type of customization should be removed in favor of the @@ -202,12 +202,27 @@ public: unsigned CCGenDiagnostics : 1; private: - /// Default target triple. - std::string DefaultTargetTriple; + /// Raw target triple. + std::string TargetTriple; /// Name to use when invoking gcc/g++. std::string CCCGenericGCCName; + /// Name of configuration file if used. + std::string ConfigFile; + + /// Allocator for string saver. + llvm::BumpPtrAllocator Alloc; + + /// Object that stores strings read from configuration file. + llvm::StringSaver Saver; + + /// Arguments originated from configuration file. + std::unique_ptr<llvm::opt::InputArgList> CfgOptions; + + /// Arguments originated from command line. + std::unique_ptr<llvm::opt::InputArgList> CLOptions; + /// Whether to check that input files exist when constructing compilation /// jobs. unsigned CheckInputsExist : 1; @@ -228,7 +243,7 @@ private: std::list<std::string> TempFiles; std::list<std::string> ResultFiles; - /// \brief Cache of all the ToolChains in use by the driver. + /// Cache of all the ToolChains in use by the driver. /// /// This maps from the string representation of a triple to a ToolChain /// created targeting that triple. The driver owns all the ToolChain objects @@ -252,7 +267,7 @@ private: void generatePrefixedToolNames(StringRef Tool, const ToolChain &TC, SmallVectorImpl<std::string> &Names) const; - /// \brief Find the appropriate .crash diagonostic file for the child crash + /// Find the appropriate .crash diagonostic file for the child crash /// under this driver and copy it out to a temporary destination with the /// other reproducer related files (.sh, .cache, etc). If not found, suggest a /// directory for the user to look at. @@ -267,7 +282,7 @@ private: SmallString<128> &CrashDiagDir); public: - Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple, + Driver(StringRef ClangExecutable, StringRef TargetTriple, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr); @@ -277,6 +292,8 @@ public: /// Name to use when invoking gcc/g++. const std::string &getCCCGenericGCCName() const { return CCCGenericGCCName; } + const std::string &getConfigFile() const { return ConfigFile; } + const llvm::opt::OptTable &getOpts() const { return *Opts; } const DiagnosticsEngine &getDiags() const { return Diags; } @@ -292,12 +309,14 @@ public: const std::string &getTitle() { return DriverTitle; } void setTitle(std::string Value) { DriverTitle = std::move(Value); } - /// \brief Get the path to the main clang executable. + std::string getTargetTriple() const { return TargetTriple; } + + /// Get the path to the main clang executable. const char *getClangProgramPath() const { return ClangExecutable.c_str(); } - /// \brief Get the path to where the clang executable was installed. + /// Get the path to where the clang executable was installed. const char *getInstalledDir() const { if (!InstalledDir.empty()) return InstalledDir.c_str(); @@ -388,11 +407,19 @@ public: int ExecuteCompilation(Compilation &C, SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands); - /// generateCompilationDiagnostics - Generate diagnostics information + /// Contains the files in the compilation diagnostic report generated by + /// generateCompilationDiagnostics. + struct CompilationDiagnosticReport { + llvm::SmallVector<std::string, 4> TemporaryFiles; + }; + + /// generateCompilationDiagnostics - Generate diagnostics information /// including preprocessed source file(s). - /// - void generateCompilationDiagnostics(Compilation &C, - const Command &FailingCommand); + /// + void generateCompilationDiagnostics( + Compilation &C, const Command &FailingCommand, + StringRef AdditionalInformation = "", + CompilationDiagnosticReport *GeneratedReport = nullptr); /// @} /// @name Helper Methods @@ -425,9 +452,9 @@ public: // FIXME: This should be in CompilationInfo. std::string GetProgramPath(StringRef Name, const ToolChain &TC) const; - /// handleAutocompletions - Handle --autocomplete by searching and printing + /// HandleAutocompletions - Handle --autocomplete by searching and printing /// possible flags, descriptions, and its arguments. - void handleAutocompletions(StringRef PassedFlags) const; + void HandleAutocompletions(StringRef PassedFlags) const; /// HandleImmediateArgs - Handle any arguments which should be /// treated before building actions or binding tools. @@ -439,8 +466,10 @@ 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(Compilation &C, const llvm::opt::ArgList &Args, - phases::ID Phase, Action *Input) const; + Action *ConstructPhaseAction( + Compilation &C, const llvm::opt::ArgList &Args, phases::ID Phase, + Action *Input, + Action::OffloadKind TargetDeviceOffloadKind = Action::OFK_None) const; /// BuildJobsForAction - Construct the jobs to perform for the action \p A and /// return an InputInfo for the result of running \p A. Will only construct @@ -493,6 +522,18 @@ public: LTOKind getLTOMode() const { return LTOMode; } private: + + /// Tries to load options from configuration file. + /// + /// \returns true if error occurred. + bool loadConfigFile(); + + /// Read options from the specified file. + /// + /// \param [in] FileName File to read. + /// \returns true, if error occurred while reading. + bool readConfigFile(StringRef FileName); + /// Set the driver mode (cl, gcc, etc) from an option string of the form /// --driver-mode=<mode>. void setDriverModeFromOption(StringRef Opt); @@ -501,7 +542,7 @@ private: /// compilation based on which -f(no-)?lto(=.*)? option occurs last. void setLTOMode(const llvm::opt::ArgList &Args); - /// \brief Retrieves a ToolChain for a particular \p Target triple. + /// Retrieves a ToolChain for a particular \p Target triple. /// /// Will cache ToolChains for the life of the driver object, and create them /// on-demand. @@ -510,7 +551,7 @@ private: /// @} - /// \brief Get bitmasks for which option flags to include and exclude based on + /// Get bitmasks for which option flags to include and exclude based on /// the driver mode. std::pair<unsigned, unsigned> getIncludeExcludeOptionFlagMasks() const; @@ -543,6 +584,8 @@ public: /// no extra characters remaining at the end. static bool GetReleaseVersion(StringRef Str, MutableArrayRef<unsigned> Digits); + /// Compute the default -fmodule-cache-path. + static void getDefaultModuleCachePath(SmallVectorImpl<char> &Result); }; /// \return True if the last defined optimization level is -Ofast. diff --git a/include/clang/Driver/Job.h b/include/clang/Driver/Job.h index b74b3b4b35e1b..47d9e992ba503 100644 --- a/include/clang/Driver/Job.h +++ b/include/clang/Driver/Job.h @@ -1,4 +1,4 @@ -//===--- Job.h - Commands to Execute ----------------------------*- C++ -*-===// +//===- Job.h - Commands to Execute ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,21 +12,22 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/iterator.h" #include "llvm/Option/Option.h" #include <memory> - -namespace llvm { - class raw_ostream; -} +#include <string> +#include <utility> +#include <vector> namespace clang { namespace driver { + class Action; -class Command; -class Tool; class InputInfo; +class Tool; // Re-export this as clang::driver::ArgStringList. using llvm::opt::ArgStringList; @@ -60,7 +61,7 @@ class Command { /// Response file name, if this command is set to use one, or nullptr /// otherwise - const char *ResponseFile; + const char *ResponseFile = nullptr; /// The input file list in case we need to emit a file list instead of a /// proper response file @@ -92,7 +93,7 @@ public: // FIXME: This really shouldn't be copyable, but is currently copied in some // error handling in Driver::generateCompilationDiagnostics. Command(const Command &) = default; - virtual ~Command() {} + virtual ~Command() = default; virtual void Print(llvm::raw_ostream &OS, const char *Terminator, bool Quote, CrashReportInfo *CrashInfo = nullptr) const; @@ -115,7 +116,7 @@ public: InputFileList = std::move(List); } - /// \brief Sets the environment to be used by the new process. + /// Sets the environment to be used by the new process. /// \param NewEnvironment An array of environment variables. /// \remark If the environment remains unset, then the environment /// from the parent process will be used. @@ -165,10 +166,10 @@ public: /// JobList - A sequence of jobs to perform. class JobList { public: - typedef SmallVector<std::unique_ptr<Command>, 4> list_type; - typedef list_type::size_type size_type; - typedef llvm::pointee_iterator<list_type::iterator> iterator; - typedef llvm::pointee_iterator<list_type::const_iterator> const_iterator; + using list_type = SmallVector<std::unique_ptr<Command>, 4>; + using size_type = list_type::size_type; + using iterator = llvm::pointee_iterator<list_type::iterator>; + using const_iterator = llvm::pointee_iterator<list_type::const_iterator>; private: list_type Jobs; @@ -193,7 +194,7 @@ public: const_iterator end() const { return Jobs.end(); } }; -} // end namespace driver -} // end namespace clang +} // namespace driver +} // namespace clang -#endif +#endif // LLVM_CLANG_DRIVER_JOB_H diff --git a/include/clang/Driver/Multilib.h b/include/clang/Driver/Multilib.h index 36d2493b1afca..132d981854fcb 100644 --- a/include/clang/Driver/Multilib.h +++ b/include/clang/Driver/Multilib.h @@ -1,4 +1,4 @@ -//===--- Multilib.h ---------------------------------------------*- C++ -*-===// +//===- Multilib.h -----------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,10 +11,14 @@ #define LLVM_CLANG_DRIVER_MULTILIB_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/STLExtras.h" -#include "llvm/Option/Option.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" +#include <cassert> #include <functional> #include <string> +#include <utility> #include <vector> namespace clang { @@ -24,7 +28,7 @@ namespace driver { /// by a command line flag class Multilib { public: - typedef std::vector<std::string> flags_list; + using flags_list = std::vector<std::string>; private: std::string GCCSuffix; @@ -33,40 +37,43 @@ private: flags_list Flags; public: - Multilib(StringRef GCCSuffix = "", StringRef OSSuffix = "", - StringRef IncludeSuffix = ""); + Multilib(StringRef GCCSuffix = {}, StringRef OSSuffix = {}, + StringRef IncludeSuffix = {}); - /// \brief Get the detected GCC installation path suffix for the multi-arch + /// Get the detected GCC installation path suffix for the multi-arch /// target variant. Always starts with a '/', unless empty const std::string &gccSuffix() const { assert(GCCSuffix.empty() || (StringRef(GCCSuffix).front() == '/' && GCCSuffix.size() > 1)); return GCCSuffix; } + /// Set the GCC installation path suffix. Multilib &gccSuffix(StringRef S); - /// \brief Get the detected os path suffix for the multi-arch + /// Get the detected os path suffix for the multi-arch /// target variant. Always starts with a '/', unless empty const std::string &osSuffix() const { assert(OSSuffix.empty() || (StringRef(OSSuffix).front() == '/' && OSSuffix.size() > 1)); return OSSuffix; } + /// Set the os path suffix. Multilib &osSuffix(StringRef S); - /// \brief Get the include directory suffix. Always starts with a '/', unless + /// Get the include directory suffix. Always starts with a '/', unless /// empty const std::string &includeSuffix() const { assert(IncludeSuffix.empty() || (StringRef(IncludeSuffix).front() == '/' && IncludeSuffix.size() > 1)); return IncludeSuffix; } + /// Set the include directory suffix Multilib &includeSuffix(StringRef S); - /// \brief Get the flags that indicate or contraindicate this multilib's use + /// Get the flags that indicate or contraindicate this multilib's use /// All elements begin with either '+' or '-' const flags_list &flags() const { return Flags; } flags_list &flags() { return Flags; } @@ -85,7 +92,7 @@ public: } LLVM_DUMP_METHOD void dump() const; - /// \brief print summary of the Multilib + /// print summary of the Multilib void print(raw_ostream &OS) const; /// Check whether any of the 'against' flags contradict the 'for' flags. @@ -102,14 +109,12 @@ raw_ostream &operator<<(raw_ostream &OS, const Multilib &M); class MultilibSet { public: - typedef std::vector<Multilib> multilib_list; - typedef multilib_list::iterator iterator; - typedef multilib_list::const_iterator const_iterator; - - typedef std::function<std::vector<std::string>(const Multilib &M)> - IncludeDirsFunc; - - typedef llvm::function_ref<bool(const Multilib &)> FilterCallback; + using multilib_list = std::vector<Multilib>; + using iterator = multilib_list::iterator; + using const_iterator = multilib_list::const_iterator; + using IncludeDirsFunc = + std::function<std::vector<std::string>(const Multilib &M)>; + using FilterCallback = llvm::function_ref<bool(const Multilib &)>; private: multilib_list Multilibs; @@ -117,7 +122,7 @@ private: IncludeDirsFunc FilePathsCallback; public: - MultilibSet() {} + MultilibSet() = default; /// Add an optional Multilib segment MultilibSet &Maybe(const Multilib &M); @@ -135,6 +140,7 @@ public: /// Filter out some subset of the Multilibs using a user defined callback MultilibSet &FilterOut(FilterCallback F); + /// Filter out those Multilibs whose gccSuffix matches the given expression MultilibSet &FilterOut(const char *Regex); @@ -144,7 +150,7 @@ public: /// Union this set of multilibs with another void combineWith(const MultilibSet &MS); - /// Remove all of thie multilibs from the set + /// Remove all of the multilibs from the set void clear() { Multilibs.clear(); } iterator begin() { return Multilibs.begin(); } @@ -165,12 +171,14 @@ public: IncludeCallback = std::move(F); return *this; } + const IncludeDirsFunc &includeDirsCallback() const { return IncludeCallback; } MultilibSet &setFilePathsCallback(IncludeDirsFunc F) { FilePathsCallback = std::move(F); return *this; } + const IncludeDirsFunc &filePathsCallback() const { return FilePathsCallback; } private: @@ -182,8 +190,8 @@ private: }; raw_ostream &operator<<(raw_ostream &OS, const MultilibSet &MS); -} -} -#endif +} // namespace driver +} // namespace clang +#endif // LLVM_CLANG_DRIVER_MULTILIB_H diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 09efd7b0af63f..2470638bec66b 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -143,14 +143,18 @@ def m_hexagon_Features_Group : OptionGroup<"<hexagon features group>">, // These are explicitly handled. def m_hexagon_Features_HVX_Group : OptionGroup<"<hexagon features group>">, Group<m_Group>, DocName<"Hexagon">; +def m_mips_Features_Group : OptionGroup<"<mips features group>">, + Group<m_Group>, DocName<"MIPS">; def m_ppc_Features_Group : OptionGroup<"<ppc features group>">, Group<m_Group>, DocName<"PowerPC">; def m_wasm_Features_Group : OptionGroup<"<wasm features group>">, Group<m_Group>, DocName<"WebAssembly">; def m_x86_Features_Group : OptionGroup<"<x86 features group>">, Group<m_Group>, Flags<[CoreOption]>, DocName<"X86">; +def m_riscv_Features_Group : OptionGroup<"<riscv features group>">, + Group<m_Group>, DocName<"RISCV">; -def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_Group>, +def m_libc_Group : OptionGroup<"<m libc group>">, Group<m_mips_Features_Group>, Flags<[HelpHidden]>; def O_Group : OptionGroup<"<O group>">, Group<CompileOnly_Group>, @@ -396,7 +400,12 @@ def O_flag : Flag<["-"], "O">, Flags<[CC1Option]>, Alias<O>, AliasArgs<["2"]>; def Ofast : Joined<["-"], "Ofast">, Group<O_Group>, Flags<[CC1Option]>; def P : Flag<["-"], "P">, Flags<[CC1Option]>, Group<Preprocessor_Group>, HelpText<"Disable linemarker output in -E mode">; -def Qn : Flag<["-"], "Qn">, IgnoredGCCCompat; +def Qy : Flag<["-"], "Qy">, Flags<[CC1Option]>, + HelpText<"Emit metadata containing compiler name and version">; +def Qn : Flag<["-"], "Qn">, Flags<[CC1Option]>, + HelpText<"Do not emit metadata containing compiler name and version">; +def : Flag<["-"], "fident">, Group<f_Group>, Alias<Qy>, Flags<[CC1Option]>; +def : Flag<["-"], "fno-ident">, Group<f_Group>, Alias<Qn>, Flags<[CC1Option]>; def Qunused_arguments : Flag<["-"], "Qunused-arguments">, Flags<[DriverOption, CoreOption]>, HelpText<"Don't emit warning for unused driver arguments">; def Q : Flag<["-"], "Q">, IgnoredGCCCompat; @@ -418,9 +427,9 @@ def S : Flag<["-"], "S">, Flags<[DriverOption,CC1Option]>, Group<Action_Group>, def Tbss : JoinedOrSeparate<["-"], "Tbss">, Group<T_Group>, MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">; def Tdata : JoinedOrSeparate<["-"], "Tdata">, Group<T_Group>, - MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">; + MetaVarName<"<addr>">, HelpText<"Set starting address of DATA to <addr>">; def Ttext : JoinedOrSeparate<["-"], "Ttext">, Group<T_Group>, - MetaVarName<"<addr>">, HelpText<"Set starting address of BSS to <addr>">; + MetaVarName<"<addr>">, HelpText<"Set starting address of TEXT to <addr>">; def T : JoinedOrSeparate<["-"], "T">, Group<T_Group>, MetaVarName<"<script>">, HelpText<"Specify <script> as linker script">; def U : JoinedOrSeparate<["-"], "U">, Group<Preprocessor_Group>, @@ -466,7 +475,8 @@ def Xcuda_ptxas : Separate<["-"], "Xcuda-ptxas">, def Xopenmp_target : Separate<["-"], "Xopenmp-target">, HelpText<"Pass <arg> to the target offloading toolchain.">, MetaVarName<"<arg>">; def Xopenmp_target_EQ : JoinedAndSeparate<["-"], "Xopenmp-target=">, - HelpText<"Pass <arg> to the specified target offloading toolchain. The triple that identifies the toolchain must be provided after the equals sign.">, MetaVarName<"<arg>">; + HelpText<"Pass <arg> to the target offloading toolchain identified by <triple>.">, + MetaVarName<"<triple> <arg>">; def z : Separate<["-"], "z">, Flags<[LinkerInput, RenderAsInput]>, HelpText<"Pass -z <arg> to the linker">, MetaVarName<"<arg>">, Group<Link_Group>; @@ -492,6 +502,8 @@ def bind__at__load : Flag<["-"], "bind_at_load">; def bundle__loader : Separate<["-"], "bundle_loader">; def bundle : Flag<["-"], "bundle">; def b : JoinedOrSeparate<["-"], "b">, Flags<[Unsupported]>; +def cfguard : Flag<["-"], "cfguard">, Flags<[CC1Option]>, + HelpText<"Emit tables required for Windows Control Flow Guard.">; def cl_opt_disable : Flag<["-"], "cl-opt-disable">, Group<opencl_Group>, Flags<[CC1Option]>, HelpText<"OpenCL only. This option disables all optimizations. By default optimizations are enabled.">; def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">, Group<opencl_Group>, Flags<[CC1Option]>, @@ -511,14 +523,22 @@ def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, Flags<[CC def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, Group<opencl_Group>, Flags<[CC1Option]>, HelpText<"OpenCL only. Allow use of less precise no signed zeros computations in the generated binary.">; def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, Flags<[CC1Option]>, - HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0">; + HelpText<"OpenCL language standard to compile for.">, Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,c++">; def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, Group<opencl_Group>, Flags<[CC1Option]>, HelpText<"OpenCL only. Allow denormals to be flushed to zero.">; def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], "cl-fp32-correctly-rounded-divide-sqrt">, Group<opencl_Group>, Flags<[CC1Option]>, HelpText<"OpenCL only. Specify that single precision floating-point divide and sqrt used in the program source are correctly rounded.">; +def cl_uniform_work_group_size : Flag<["-"], "cl-uniform-work-group-size">, Group<opencl_Group>, Flags<[CC1Option]>, + HelpText<"OpenCL only. Defines that the global work-size be a multiple of the work-group size specified to clEnqueueNDRangeKernel">; def client__name : JoinedOrSeparate<["-"], "client_name">; def combine : Flag<["-", "--"], "combine">, Flags<[DriverOption, Unsupported]>; def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">; +def config : Separate<["--"], "config">, Flags<[DriverOption]>, + HelpText<"Specifies configuration file">; +def config_system_dir_EQ : Joined<["--"], "config-system-dir=">, Flags<[DriverOption, HelpHidden]>, + HelpText<"System directory for configuration files">; +def config_user_dir_EQ : Joined<["--"], "config-user-dir=">, Flags<[DriverOption, HelpHidden]>, + HelpText<"User directory for configuration files">; def coverage : Flag<["-", "--"], "coverage">, Flags<[CoreOption]>; def cpp_precomp : Flag<["-"], "cpp-precomp">, Group<clang_ignored_f_Group>; def current__version : JoinedOrSeparate<["-"], "current_version">; @@ -535,8 +555,14 @@ def cuda_host_only : Flag<["--"], "cuda-host-only">, def cuda_compile_host_device : Flag<["--"], "cuda-compile-host-device">, HelpText<"Compile CUDA code for both host and device (default). Has no " "effect on non-CUDA compilations.">; +def cuda_include_ptx_EQ : Joined<["--"], "cuda-include-ptx=">, Flags<[DriverOption]>, + HelpText<"Include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; +def no_cuda_include_ptx_EQ : Joined<["--"], "no-cuda-include-ptx=">, Flags<[DriverOption]>, + HelpText<"Do not include PTX for the follwing GPU architecture (e.g. sm_35) or 'all'. May be specified more than once.">; def cuda_gpu_arch_EQ : Joined<["--"], "cuda-gpu-arch=">, Flags<[DriverOption]>, HelpText<"CUDA GPU architecture (e.g. sm_35). May be specified more than once.">; +def hip_link : Flag<["--"], "hip-link">, + HelpText<"Link clang-offload-bundler bundles for HIP">; def no_cuda_gpu_arch_EQ : Joined<["--"], "no-cuda-gpu-arch=">, Flags<[DriverOption]>, HelpText<"Remove GPU architecture (e.g. sm_35) from the list of GPUs to compile for. " "'all' resets the list to its default value.">; @@ -548,6 +574,8 @@ def no_cuda_version_check : Flag<["--"], "no-cuda-version-check">, def no_cuda_noopt_device_debug : Flag<["--"], "no-cuda-noopt-device-debug">; def cuda_path_EQ : Joined<["--"], "cuda-path=">, Group<i_Group>, HelpText<"CUDA installation path">; +def cuda_path_ignore_env : Flag<["--"], "cuda-path-ignore-env">, Group<i_Group>, + HelpText<"Ignore environment variables to detect CUDA installation">; def ptxas_path_EQ : Joined<["--"], "ptxas-path=">, Group<i_Group>, HelpText<"Path to ptxas (used for compiling CUDA code)">; def fcuda_flush_denormals_to_zero : Flag<["-"], "fcuda-flush-denormals-to-zero">, @@ -556,6 +584,18 @@ def fno_cuda_flush_denormals_to_zero : Flag<["-"], "fno-cuda-flush-denormals-to- def fcuda_approx_transcendentals : Flag<["-"], "fcuda-approx-transcendentals">, Flags<[CC1Option]>, HelpText<"Use approximate transcendental functions">; def fno_cuda_approx_transcendentals : Flag<["-"], "fno-cuda-approx-transcendentals">; +def fcuda_rdc : Flag<["-"], "fcuda-rdc">, Flags<[CC1Option]>, + HelpText<"Generate relocatable device code, also known as separate compilation mode.">; +def fno_cuda_rdc : Flag<["-"], "fno-cuda-rdc">; +def fcuda_short_ptr : Flag<["-"], "fcuda-short-ptr">, Flags<[CC1Option]>, + HelpText<"Use 32-bit pointers for accessing const/local/shared address spaces.">; +def fno_cuda_short_ptr : Flag<["-"], "fno-cuda-short-ptr">; +def hip_device_lib_path_EQ : Joined<["--"], "hip-device-lib-path=">, Group<Link_Group>, + HelpText<"HIP device library path">; +def hip_device_lib_EQ : Joined<["--"], "hip-device-lib=">, Group<Link_Group>, + HelpText<"HIP device library">; +def fhip_dump_offload_linker_script : Flag<["-"], "fhip-dump-offload-linker-script">, + Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>; def dA : Flag<["-"], "dA">, Group<d_Group>; def dD : Flag<["-"], "dD">, Group<d_Group>, Flags<[CC1Option]>, HelpText<"Print macro definitions in -E mode in addition to normal output">; @@ -591,6 +631,9 @@ 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 faccess_control : Flag<["-"], "faccess-control">, Group<f_Group>; +def falign_functions : Flag<["-"], "falign-functions">, Group<f_Group>; +def falign_functions_EQ : Joined<["-"], "falign-functions=">, Group<f_Group>; +def fno_align_functions: Flag<["-"], "fno-align-functions">, Group<f_Group>; def fallow_unsupported : Flag<["-"], "fallow-unsupported">, Group<f_Group>; def fapple_kext : Flag<["-"], "fapple-kext">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use Apple's kernel extensions ABI">; @@ -687,10 +730,10 @@ def fprofile_instr_use_EQ : Joined<["-"], "fprofile-instr-use=">, Group<f_Group>, Flags<[CoreOption]>, HelpText<"Use instrumentation data for profile-guided optimization">; def fcoverage_mapping : Flag<["-"], "fcoverage-mapping">, - Group<f_Group>, Flags<[CC1Option]>, + Group<f_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Generate coverage mapping to enable code coverage analysis">; def fno_coverage_mapping : Flag<["-"], "fno-coverage-mapping">, - Group<f_Group>, Flags<[DriverOption]>, + Group<f_Group>, Flags<[DriverOption, CoreOption]>, HelpText<"Disable code coverage analysis">; def fprofile_generate : Flag<["-"], "fprofile-generate">, Group<f_Group>, Flags<[DriverOption]>, @@ -715,12 +758,16 @@ def fno_profile_instr_use : Flag<["-"], "fno-profile-instr-use">, def fno_profile_use : Flag<["-"], "fno-profile-use">, Alias<fno_profile_instr_use>; -def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CC1Option]>, +def faddrsig : Flag<["-"], "faddrsig">, Group<f_Group>, Flags<[CoreOption, CC1Option]>, + HelpText<"Emit an address-significance table">; +def fno_addrsig : Flag<["-"], "fno-addrsig">, Group<f_Group>, Flags<[CoreOption]>, + HelpText<"Don't emit an address-significance table">; +def fblocks : Flag<["-"], "fblocks">, Group<f_Group>, Flags<[CoreOption, CC1Option]>, HelpText<"Enable the 'blocks' language feature">; def fbootclasspath_EQ : Joined<["-"], "fbootclasspath=">, Group<f_Group>; def fborland_extensions : Flag<["-"], "fborland-extensions">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Accept non-standard constructs supported by the Borland compiler">; -def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>; +def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>, Flags<[CoreOption]>; def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>, Flags<[DriverOption]>, HelpText<"Load the clang builtins module map file.">; def fcaret_diagnostics : Flag<["-"], "fcaret-diagnostics">, Group<f_Group>; @@ -741,6 +788,12 @@ def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, Gr def fparse_all_comments : Flag<["-"], "fparse-all-comments">, Group<f_clang_Group>, Flags<[CC1Option]>; def fcommon : Flag<["-"], "fcommon">, Group<f_Group>; def fcompile_resource_EQ : Joined<["-"], "fcompile-resource=">, Group<f_Group>; +def fcomplete_member_pointers : Flag<["-"], "fcomplete-member-pointers">, Group<f_clang_Group>, + Flags<[CoreOption, CC1Option]>, + HelpText<"Require member pointer base types to be complete if they would be significant under the Microsoft ABI">; +def fno_complete_member_pointers : Flag<["-"], "fno-complete-member-pointers">, Group<f_clang_Group>, + Flags<[CoreOption]>, + HelpText<"Do not require member pointer base types to be complete if they would be significant under the Microsoft ABI">; def fconstant_cfstrings : Flag<["-"], "fconstant-cfstrings">, Group<f_Group>; def fconstant_string_class_EQ : Joined<["-"], "fconstant-string-class=">, Group<f_Group>; def fconstexpr_depth_EQ : Joined<["-"], "fconstexpr-depth=">, Group<f_Group>; @@ -749,6 +802,7 @@ def fconstexpr_backtrace_limit_EQ : Joined<["-"], "fconstexpr-backtrace-limit="> Group<f_Group>; def fno_crash_diagnostics : Flag<["-"], "fno-crash-diagnostics">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>, HelpText<"Disable auto-generation of preprocessed source files and a script for reproduction during a clang crash">; +def fcrash_diagnostics_dir : Joined<["-"], "fcrash-diagnostics-dir=">, Group<f_clang_Group>, Flags<[NoArgumentUnused]>; def fcreate_profile : Flag<["-"], "fcreate-profile">, Group<f_Group>; def fcxx_exceptions: Flag<["-"], "fcxx-exceptions">, Group<f_Group>, HelpText<"Enable C++ exceptions">, Flags<[CC1Option]>; @@ -780,6 +834,10 @@ def fdiagnostics_show_template_tree : Flag<["-"], "fdiagnostics-show-template-tr HelpText<"Print a template comparison tree for differing templates">; def fdeclspec : Flag<["-"], "fdeclspec">, Group<f_clang_Group>, HelpText<"Allow __declspec as a keyword">, Flags<[CC1Option]>; +def fdiscard_value_names : Flag<["-"], "fdiscard-value-names">, Group<f_clang_Group>, + HelpText<"Discard value names in LLVM IR">, Flags<[DriverOption]>; +def fno_discard_value_names : Flag<["-"], "fno-discard-value-names">, Group<f_clang_Group>, + HelpText<"Do not discard value names in LLVM IR">, Flags<[DriverOption]>; def fdollars_in_identifiers : Flag<["-"], "fdollars-in-identifiers">, Group<f_Group>, HelpText<"Allow '$' in identifiers">, Flags<[CC1Option]>; def fdwarf2_cfi_asm : Flag<["-"], "fdwarf2-cfi-asm">, Group<clang_ignored_f_Group>; @@ -795,7 +853,7 @@ def femit_all_decls : Flag<["-"], "femit-all-decls">, Group<f_Group>, Flags<[CC1 HelpText<"Emit all declarations, even if unused">; def femulated_tls : Flag<["-"], "femulated-tls">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Use emutls functions to access thread_local variables">; -def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>; +def fno_emulated_tls : Flag<["-"], "fno-emulated-tls">, Group<f_Group>, Flags<[CC1Option]>; 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]>, @@ -829,6 +887,17 @@ def fno_signaling_math : Flag<["-"], "fno-signaling-math">, Group<f_Group>; def fjump_tables : Flag<["-"], "fjump-tables">, Group<f_Group>; def fno_jump_tables : Flag<["-"], "fno-jump-tables">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Do not use jump tables for lowering switches">; +def fforce_enable_int128 : Flag<["-"], "fforce-enable-int128">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable support for int128_t type">; +def fno_force_enable_int128 : Flag<["-"], "fno-force-enable-int128">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Disable support for int128_t type">; + +def ffixed_point : Flag<["-"], "ffixed-point">, Group<f_Group>, + Flags<[CC1Option]>, HelpText<"Enable fixed point types">; +def fno_fixed_point : Flag<["-"], "fno-fixed-point">, Group<f_Group>, + HelpText<"Disable fixed point types">; // Begin sanitizer flags. These should all be core options exposed in all driver // modes. @@ -881,6 +950,14 @@ def fno_sanitize_address_use_after_scope : Flag<["-"], "fno-sanitize-address-use Group<f_clang_Group>, Flags<[CoreOption, DriverOption]>, HelpText<"Disable use-after-scope detection in AddressSanitizer">; +def fsanitize_address_poison_class_member_array_new_cookie + : Flag<[ "-" ], "fsanitize-address-poison-class-member-array-new-cookie">, + Group<f_clang_Group>, + HelpText<"Enable poisoning array cookies when using class member operator new[] in AddressSanitizer">; +def fno_sanitize_address_poison_class_member_array_new_cookie + : Flag<[ "-" ], "fno-sanitize-address-poison-class-member-array-new-cookie">, + Group<f_clang_Group>, + HelpText<"Disable poisoning array cookies when using class member operator new[] in AddressSanitizer">; def fsanitize_address_globals_dead_stripping : Flag<["-"], "fsanitize-address-globals-dead-stripping">, Group<f_clang_Group>, HelpText<"Enable linker dead stripping of globals in AddressSanitizer">; @@ -985,6 +1062,13 @@ def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">, Values<"fast,on,off">; +def fstrict_float_cast_overflow : Flag<["-"], + "fstrict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Assume that overflowing float-to-int casts are undefined (default)">; +def fno_strict_float_cast_overflow : Flag<["-"], + "fno-strict-float-cast-overflow">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Relax language rules and try to match the behavior of the target's native float-to-int conversion instructions">; + def ffor_scope : Flag<["-"], "ffor-scope">, Group<f_Group>; def fno_for_scope : Flag<["-"], "fno-for-scope">, Group<f_Group>; @@ -996,6 +1080,13 @@ def frewrite_imports : Flag<["-"], "frewrite-imports">, Group<f_Group>, Flags<[CC1Option]>; def fno_rewrite_imports : Flag<["-"], "fno-rewrite-imports">, Group<f_Group>; +def fdelete_null_pointer_checks : Flag<["-"], + "fdelete-null-pointer-checks">, Group<f_Group>, + HelpText<"Treat usage of null pointers as undefined behavior.">; +def fno_delete_null_pointer_checks : Flag<["-"], + "fno-delete-null-pointer-checks">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Do not treat usage of null pointers as undefined behavior.">; + def frewrite_map_file : Separate<["-"], "frewrite-map-file">, Group<f_Group>, Flags<[ DriverOption, CC1Option ]>; @@ -1025,6 +1116,8 @@ def finline_functions : Flag<["-"], "finline-functions">, Group<f_clang_Group>, def finline_hint_functions: Flag<["-"], "finline-hint-functions">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Inline functions which are (explicitly or implicitly) marked inline">; def finline : Flag<["-"], "finline">, Group<clang_ignored_f_Group>; +def fexperimental_isel : Flag<["-"], "fexperimental-isel">, Group<f_clang_Group>, + HelpText<"Enables the experimental global instruction selector">; def fexperimental_new_pass_manager : Flag<["-"], "fexperimental-new-pass-manager">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Enables an experimental new pass manager in LLVM.">; @@ -1036,6 +1129,11 @@ def finstrument_functions_after_inlining : Flag<["-"], "finstrument-functions-af HelpText<"Like -finstrument-functions, but insert the calls after inlining">; def finstrument_function_entry_bare : Flag<["-"], "finstrument-function-entry-bare">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Instrument function entry only, after inlining, without arguments to the instrumentation call">; +def fcf_protection_EQ : Joined<["-"], "fcf-protection=">, Flags<[CoreOption, CC1Option]>, Group<f_Group>, + HelpText<"Instrument control-flow architecture protection. Options: return, branch, full, none.">, Values<"return,branch,full,none">; +def fcf_protection : Flag<["-"], "fcf-protection">, Group<f_Group>, Flags<[CoreOption, CC1Option]>, + Alias<fcf_protection_EQ>, AliasArgs<["full"]>, + HelpText<"Enable cf-protection in 'full' mode">; def fxray_instrument : Flag<["-"], "fxray-instrument">, Group<f_Group>, Flags<[CC1Option]>, @@ -1054,11 +1152,19 @@ def fxray_instruction_threshold_ : def fxray_always_instrument : JoinedOrSeparate<["-"], "fxray-always-instrument=">, Group<f_Group>, Flags<[CC1Option]>, - HelpText<"Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; + HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'always instrument' XRay attribute.">; def fxray_never_instrument : JoinedOrSeparate<["-"], "fxray-never-instrument=">, Group<f_Group>, Flags<[CC1Option]>, - HelpText<"Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; + HelpText<"DEPRECATED: Filename defining the whitelist for imbuing the 'never instrument' XRay attribute.">; +def fxray_attr_list : + JoinedOrSeparate<["-"], "fxray-attr-list=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Filename defining the list of functions/types for imbuing XRay attributes.">; +def fxray_modes : + JoinedOrSeparate<["-"], "fxray-modes=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"List of modes to link in by default into XRay instrumented binaries.">; def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents">, Group<f_Group>, Flags<[CC1Option]>, @@ -1066,9 +1172,26 @@ def fxray_always_emit_customevents : Flag<["-"], "fxray-always-emit-customevents def fnoxray_always_emit_customevents : Flag<["-"], "fno-xray-always-emit-customevents">, Group<f_Group>, Flags<[CC1Option]>; +def fxray_always_emit_typedevents : Flag<["-"], "fxray-always-emit-typedevents">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Determine whether to always emit __xray_typedevent(...) calls even if the function it appears in is not always instrumented.">; +def fnoxray_always_emit_typedevents : Flag<["-"], "fno-xray-always-emit-typedevents">, Group<f_Group>, + Flags<[CC1Option]>; + +def fxray_link_deps : Flag<["-"], "fxray-link-deps">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Tells clang to add the link dependencies for XRay.">; +def fnoxray_link_deps : Flag<["-"], "fnoxray-link-deps">, Group<f_Group>, + Flags<[CC1Option]>; + +def fxray_instrumentation_bundle : + JoinedOrSeparate<["-"], "fxray-instrumentation-bundle=">, + Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Select which XRay instrumentation points to emit. Options: all, none, function, custom. Default is 'all'.">; + def ffine_grained_bitfield_accesses : Flag<["-"], "ffine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>, - HelpText<"Use separate accesses for bitfields with legal widths and alignments.">; + HelpText<"Use separate accesses for consecutive bitfield runs with legal widths and alignments.">; def fno_fine_grained_bitfield_accesses : Flag<["-"], "fno-fine-grained-bitfield-accesses">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Use large-integer access for consecutive bitfield runs.">; @@ -1092,7 +1215,8 @@ def fthinlto_index_EQ : Joined<["-"], "fthinlto-index=">, HelpText<"Perform ThinLTO importing using provided function summary index">; def fmacro_backtrace_limit_EQ : Joined<["-"], "fmacro-backtrace-limit=">, Group<f_Group>, Flags<[DriverOption, CoreOption]>; -def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>; +def fmerge_all_constants : Flag<["-"], "fmerge-all-constants">, Group<f_Group>, + Flags<[CC1Option, CoreOption]>, HelpText<"Allow merging of constants">; def fmessage_length_EQ : Joined<["-"], "fmessage-length=">, Group<f_Group>; def fms_extensions : Flag<["-"], "fms-extensions">, Group<f_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Accept some non-standard constructs supported by the Microsoft compiler">; @@ -1146,6 +1270,8 @@ def fmodules_disable_diagnostic_validation : Flag<["-"], "fmodules-disable-diagn 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">; +def fno_modules_validate_system_headers : Flag<["-"], "fno-modules-validate-system-headers">, + Group<i_Group>, Flags<[DriverOption]>; def fmodules : Flag <["-"], "fmodules">, Group<f_Group>, Flags<[DriverOption, CC1Option]>, HelpText<"Enable the 'modules' language feature">; @@ -1194,11 +1320,11 @@ def fno_asynchronous_unwind_tables : Flag<["-"], "fno-asynchronous-unwind-tables def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">, Group<f_Group>, HelpText<"Don't assume that C++'s global operator new can't alias any pointer">, Flags<[CC1Option]>; -def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>; +def fno_blocks : Flag<["-"], "fno-blocks">, Group<f_Group>, Flags<[CoreOption]>; def fno_borland_extensions : Flag<["-"], "fno-borland-extensions">, Group<f_Group>; -def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option]>, +def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Disable implicit builtin knowledge of functions">; -def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option]>, +def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>, Flags<[CC1Option, CoreOption]>, HelpText<"Disable implicit builtin knowledge of a specific function">; def fno_caret_diagnostics : Flag<["-"], "fno-caret-diagnostics">, Group<f_Group>, Flags<[CC1Option]>; @@ -1220,6 +1346,10 @@ def fno_diagnostics_show_hotness : Flag<["-"], "fno-diagnostics-show-hotness">, def fno_diagnostics_show_option : Flag<["-"], "fno-diagnostics-show-option">, Group<f_Group>; def fno_diagnostics_show_note_include_stack : Flag<["-"], "fno-diagnostics-show-note-include-stack">, Flags<[CC1Option]>, Group<f_Group>; +def fdigraphs : Flag<["-"], "fdigraphs">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:' (default)">; +def fno_digraphs : Flag<["-"], "fno-digraphs">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Disallow alternative token representations '<:', ':>', '<%', '%>', '%:', '%:%:'">; def fno_declspec : Flag<["-"], "fno-declspec">, Group<f_clang_Group>, HelpText<"Disallow __declspec as a keyword">, Flags<[CC1Option]>; def fno_dollars_in_identifiers : Flag<["-"], "fno-dollars-in-identifiers">, Group<f_Group>, @@ -1231,6 +1361,8 @@ def fno_exceptions : Flag<["-"], "fno-exceptions">, Group<f_Group>; def fno_gnu_keywords : Flag<["-"], "fno-gnu-keywords">, Group<f_Group>, Flags<[CC1Option]>; def fno_inline_functions : Flag<["-"], "fno-inline-functions">, Group<f_clang_Group>, Flags<[CC1Option]>; def fno_inline : Flag<["-"], "fno-inline">, Group<f_clang_Group>, Flags<[CC1Option]>; +def fno_experimental_isel : Flag<["-"], "fno-experimental-isel">, Group<f_clang_Group>, + HelpText<"Disables the experimental global instruction selector">; def fno_experimental_new_pass_manager : Flag<["-"], "fno-experimental-new-pass-manager">, Group<f_clang_Group>, Flags<[CC1Option]>, HelpText<"Disables an experimental new pass manager in LLVM.">; @@ -1239,7 +1371,7 @@ def fveclib : Joined<["-"], "fveclib=">, Group<f_Group>, Flags<[CC1Option]>, def fno_lax_vector_conversions : Flag<["-"], "fno-lax-vector-conversions">, Group<f_Group>, HelpText<"Disallow implicit conversions between vectors with a different number of elements or different element types">, Flags<[CC1Option]>; def fno_merge_all_constants : Flag<["-"], "fno-merge-all-constants">, Group<f_Group>, - Flags<[CC1Option]>, HelpText<"Disallow merging of constants">; + HelpText<"Disallow merging of constants">; def fno_modules : Flag <["-"], "fno-modules">, Group<f_Group>, Flags<[DriverOption]>; def fno_implicit_module_maps : Flag <["-"], "fno-implicit-module-maps">, Group<f_Group>, @@ -1272,6 +1404,8 @@ def fno_operator_names : Flag<["-"], "fno-operator-names">, Group<f_Group>, def fno_pascal_strings : Flag<["-"], "fno-pascal-strings">, Group<f_Group>; def fno_rtti : Flag<["-"], "fno-rtti">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Disable generation of rtti information">; +def fno_rtti_data : Flag<["-"], "fno-rtti-data">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Control emission of RTTI data">; def fno_short_enums : Flag<["-"], "fno-short-enums">, Group<f_Group>; def fno_show_column : Flag<["-"], "fno-show-column">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Do not include column number on diagnostics">; @@ -1295,6 +1429,8 @@ def fno_threadsafe_statics : Flag<["-"], "fno-threadsafe-statics">, Group<f_Grou Flags<[CC1Option]>, HelpText<"Do not emit code to make initialization of local statics thread safe">; def fno_use_cxa_atexit : Flag<["-"], "fno-use-cxa-atexit">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Don't use __cxa_atexit for calling destructors">; +def fno_register_global_dtors_with_atexit : Flag<["-"], "fno-register-global-dtors-with-atexit">, Group<f_Group>, + HelpText<"Don't use atexit or __cxa_atexit to register global destructors">; def fno_use_init_array : Flag<["-"], "fno-use-init-array">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Don't use .init_array instead of .ctors">; def fno_unit_at_a_time : Flag<["-"], "fno-unit-at-a-time">, Group<f_Group>; @@ -1361,22 +1497,34 @@ def fno_objc_nonfragile_abi : Flag<["-"], "fno-objc-nonfragile-abi">, Group<f_Gr def fobjc_sender_dependent_dispatch : Flag<["-"], "fobjc-sender-dependent-dispatch">, Group<f_Group>; def fomit_frame_pointer : Flag<["-"], "fomit-frame-pointer">, Group<f_Group>; -def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>; +def fopenmp : Flag<["-"], "fopenmp">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>, + HelpText<"Parse OpenMP pragmas and generate parallel code.">; def fno_openmp : Flag<["-"], "fno-openmp">, Group<f_Group>, Flags<[NoArgumentUnused]>; def fopenmp_version_EQ : Joined<["-"], "fopenmp-version=">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>; def fopenmp_EQ : Joined<["-"], "fopenmp=">, Group<f_Group>; -def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, Flags<[NoArgumentUnused]>; -def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>; +def fopenmp_use_tls : Flag<["-"], "fopenmp-use-tls">, Group<f_Group>, + Flags<[NoArgumentUnused, HelpHidden]>; +def fnoopenmp_use_tls : Flag<["-"], "fnoopenmp-use-tls">, Group<f_Group>, + Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; def fopenmp_targets_EQ : CommaJoined<["-"], "fopenmp-targets=">, Flags<[DriverOption, CC1Option]>, HelpText<"Specify comma-separated list of triples OpenMP offloading targets to be supported">; -def fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">, Group<f_Group>, - Flags<[NoArgumentUnused]>; -def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>, - HelpText<"OpenMP target code is compiled as relocatable using the -c flag. For OpenMP targets the code is relocatable by default.">; -def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>, - HelpText<"Do not compile OpenMP target code as relocatable.">; +def fopenmp_dump_offload_linker_script : Flag<["-"], "fopenmp-dump-offload-linker-script">, + Group<f_Group>, Flags<[NoArgumentUnused, HelpHidden]>; +def fopenmp_relocatable_target : Flag<["-"], "fopenmp-relocatable-target">, + Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; +def fnoopenmp_relocatable_target : Flag<["-"], "fnoopenmp-relocatable-target">, + Group<f_Group>, Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; +def fopenmp_simd : Flag<["-"], "fopenmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>, + HelpText<"Emit OpenMP code only for SIMD-based constructs.">; +def fno_openmp_simd : Flag<["-"], "fno-openmp-simd">, Group<f_Group>, Flags<[CC1Option, NoArgumentUnused]>; +def fopenmp_cuda_mode : Flag<["-"], "fopenmp-cuda-mode">, Group<f_Group>, + Flags<[CC1Option, NoArgumentUnused, HelpHidden]>; +def fno_openmp_cuda_mode : Flag<["-"], "fno-openmp-cuda-mode">, Group<f_Group>, + Flags<[NoArgumentUnused, HelpHidden]>; def fno_optimize_sibling_calls : Flag<["-"], "fno-optimize-sibling-calls">, Group<f_Group>; def foptimize_sibling_calls : Flag<["-"], "foptimize-sibling-calls">, Group<f_Group>; +def fno_escaping_block_tail_calls : Flag<["-"], "fno-escaping-block-tail-calls">, Group<f_Group>, Flags<[CC1Option]>; +def fescaping_block_tail_calls : Flag<["-"], "fescaping-block-tail-calls">, Group<f_Group>; def force__cpusubtype__ALL : Flag<["-"], "force_cpusubtype_ALL">; def force__flat__namespace : Flag<["-"], "force_flat_namespace">; def force__load : Separate<["-"], "force_load">; @@ -1421,6 +1569,10 @@ 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 fchar8__t : Flag<["-"], "fchar8_t">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Enable C++ builtin type char8_t">; +def fno_char8__t : Flag<["-"], "fno-char8_t">, Group<f_Group>, + HelpText<"Disable C++ builtin type char8_t">; def fshort_wchar : Flag<["-"], "fshort-wchar">, Group<f_Group>, HelpText<"Force wchar_t to be a short unsigned int">; def fno_short_wchar : Flag<["-"], "fno-short-wchar">, Group<f_Group>, @@ -1533,6 +1685,8 @@ def funsigned_char : Flag<["-"], "funsigned-char">, Group<f_Group>; def fno_unsigned_char : Flag<["-"], "fno-unsigned-char">; def funwind_tables : Flag<["-"], "funwind-tables">, Group<f_Group>; def fuse_cxa_atexit : Flag<["-"], "fuse-cxa-atexit">, Group<f_Group>; +def fregister_global_dtors_with_atexit : Flag<["-"], "fregister-global-dtors-with-atexit">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Use atexit or __cxa_atexit to register global destructors">; 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>; @@ -1540,7 +1694,7 @@ 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">, Values<"hidden,default">; def fvisibility_inlines_hidden : Flag<["-"], "fvisibility-inlines-hidden">, Group<f_Group>, - HelpText<"Give inline C++ member functions default visibility by default">, + HelpText<"Give inline C++ member functions hidden visibility by default">, Flags<[CC1Option]>; def fvisibility_ms_compat : Flag<["-"], "fvisibility-ms-compat">, Group<f_Group>, HelpText<"Give global types 'default' visibility and global functions and " @@ -1550,6 +1704,11 @@ def fwhole_program_vtables : Flag<["-"], "fwhole-program-vtables">, Group<f_Grou HelpText<"Enables whole-program vtable optimization. Requires -flto">; def fno_whole_program_vtables : Flag<["-"], "fno-whole-program-vtables">, Group<f_Group>, Flags<[CoreOption]>; +def fforce_emit_vtables : Flag<["-"], "fforce-emit-vtables">, Group<f_Group>, + Flags<[CC1Option]>, + HelpText<"Emits more virtual tables to improve devirtualization">; +def fno_force_emit_vtables : Flag<["-"], "fno-force-emit-vtables">, Group<f_Group>, + Flags<[CoreOption]>; def fwrapv : Flag<["-"], "fwrapv">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Treat signed integer overflow as two's complement">; def fwritable_strings : Flag<["-"], "fwritable-strings">, Group<f_Group>, Flags<[CC1Option]>, @@ -1564,6 +1723,10 @@ def fdata_sections : Flag <["-"], "fdata-sections">, Group<f_Group>, Flags<[CC1Option]>, HelpText<"Place each data in its own section (ELF Only)">; def fno_data_sections : Flag <["-"], "fno-data-sections">, Group<f_Group>, Flags<[CC1Option]>; +def fstack_size_section : Flag<["-"], "fstack-size-section">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Emit section containing metadata on function stack sizes">; +def fno_stack_size_section : Flag<["-"], "fno-stack-size-section">, Group<f_Group>, Flags<[CC1Option]>, + HelpText<"Don't emit section containing metadata on function stack sizes">; def funique_section_names : Flag <["-"], "funique-section-names">, Group<f_Group>, Flags<[CC1Option]>, @@ -1589,11 +1752,12 @@ def fdebug_types_section: Flag <["-"], "fdebug-types-section">, Group<f_Group>, def fno_debug_types_section: Flag<["-"], "fno-debug-types-section">, Group<f_Group>, Flags<[CC1Option]>; def fsplit_dwarf_inlining: Flag <["-"], "fsplit-dwarf-inlining">, Group<f_Group>, - Flags<[CC1Option]>, HelpText<"Place debug types in their own section (ELF Only)">; + Flags<[CC1Option]>, HelpText<"Provide minimal debug info in the object/executable to facilitate online symbolication/stack traces in the absence of .dwo/.dwp files when using Split DWARF">; def fno_split_dwarf_inlining: Flag<["-"], "fno-split-dwarf-inlining">, Group<f_Group>, Flags<[CC1Option]>; def fdebug_prefix_map_EQ - : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>, Flags<[CC1Option]>, + : Joined<["-"], "fdebug-prefix-map=">, Group<f_Group>, + Flags<[CC1Option,CC1AsOption]>, HelpText<"remap file source paths in debug info">; def g_Flag : Flag<["-"], "g">, Group<g_Group>, HelpText<"Generate source-level debug information">; @@ -1642,6 +1806,7 @@ def gcolumn_info : Flag<["-"], "gcolumn-info">, Group<g_flags_Group>, Flags<[Cor def gno_column_info : Flag<["-"], "gno-column-info">, Group<g_flags_Group>, Flags<[CoreOption]>; def gsplit_dwarf : Flag<["-"], "gsplit-dwarf">, Group<g_flags_Group>; def ggnu_pubnames : Flag<["-"], "ggnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>; +def gno_gnu_pubnames : Flag<["-"], "gno-gnu-pubnames">, Group<g_flags_Group>, Flags<[CC1Option]>; def gdwarf_aranges : Flag<["-"], "gdwarf-aranges">, Group<g_flags_Group>; def gmodules : Flag <["-"], "gmodules">, Group<gN_Group>, HelpText<"Generate debug info with external references to clang modules" @@ -1650,6 +1815,11 @@ def gz : Flag<["-"], "gz">, Group<g_flags_Group>, HelpText<"DWARF debug sections compression type">; def gz_EQ : Joined<["-"], "gz=">, Group<g_flags_Group>, HelpText<"DWARF debug sections compression type">; +def gembed_source : Flag<["-"], "gembed-source">, Group<g_flags_Group>, Flags<[CC1Option]>, + HelpText<"Embed source text in DWARF debug sections">; +def gno_embed_source : Flag<["-"], "gno-embed-source">, Group<g_flags_Group>, + Flags<[DriverOption]>, + HelpText<"Restore the default behavior of not embedding source text in DWARF debug sections">; def headerpad__max__install__names : Joined<["-"], "headerpad_max_install_names">; def help : Flag<["-", "--"], "help">, Flags<[CC1Option,CC1AsOption]>, HelpText<"Display available options">; @@ -1700,7 +1870,7 @@ def iwithsysroot : JoinedOrSeparate<["-"], "iwithsysroot">, Group<clang_i_Group> Flags<[CC1Option]>; def ivfsoverlay : JoinedOrSeparate<["-"], "ivfsoverlay">, Group<clang_i_Group>, Flags<[CC1Option]>, HelpText<"Overlay the virtual filesystem described by file over the real file system">; -def i : Joined<["-"], "i">, Group<i_Group>; +def imultilib : Separate<["-"], "imultilib">, Group<gfortran_Group>; def keep__private__externs : Flag<["-"], "keep_private_externs">; def l : JoinedOrSeparate<["-"], "l">, Flags<[LinkerInput, RenderJoined]>, Group<Link_Group>; @@ -1787,6 +1957,10 @@ def mmacos_version_min_EQ : Joined<["-"], "mmacos-version-min=">, Group<m_Group>, Alias<mmacosx_version_min_EQ>; 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 moutline : Flag<["-"], "moutline">, Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Enable function outlining (AArch64 only)">; +def mno_outline : Flag<["-"], "mno-outline">, Group<f_clang_Group>, Flags<[CC1Option]>, + HelpText<"Disable function outlining (AArch64 only)">; def mno_ms_bitfields : Flag<["-"], "mno-ms-bitfields">, Group<m_Group>, HelpText<"Do not set the default structure layout to be compatible with the Microsoft compiler standard">; def mstackrealign : Flag<["-"], "mstackrealign">, Group<m_Group>, Flags<[CC1Option]>, @@ -1795,6 +1969,10 @@ def mstack_alignment : Joined<["-"], "mstack-alignment=">, Group<m_Group>, Flags HelpText<"Set the stack alignment">; def mstack_probe_size : Joined<["-"], "mstack-probe-size=">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"Set the stack probe size">; +def mstack_arg_probe : Flag<["-"], "mstack-arg-probe">, Group<m_Group>, + HelpText<"Enable stack probes">; +def mno_stack_arg_probe : Flag<["-"], "mno-stack-arg-probe">, Group<m_Group>, Flags<[CC1Option]>, + HelpText<"Disable stack probes which are enabled by default">; def mthread_model : Separate<["-"], "mthread-model">, Group<m_Group>, Flags<[CC1Option]>, HelpText<"The thread model to use, e.g. posix, single (posix by default)">, Values<"posix,single">; def meabi : Separate<["-"], "meabi">, Group<m_Group>, Flags<[CC1Option]>, @@ -1811,6 +1989,11 @@ def mno_rtd: Flag<["-"], "mno-rtd">, Group<m_Group>; def mno_soft_float : Flag<["-"], "mno-soft-float">, Group<m_Group>; def mno_stackrealign : Flag<["-"], "mno-stackrealign">, Group<m_Group>; +def mrelax : Flag<["-"], "mrelax">, Group<m_riscv_Features_Group>, + HelpText<"Enable linker relaxation">; +def mno_relax : Flag<["-"], "mno-relax">, Group<m_riscv_Features_Group>, + HelpText<"Disable linker relaxation">; + def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>, HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">; def mno_unaligned_access : Flag<["-"], "mno-unaligned-access">, Group<m_arm_Features_Group>, @@ -1827,8 +2010,8 @@ def ffixed_r9 : Flag<["-"], "ffixed-r9">, Group<m_arm_Features_Group>, HelpText<"Reserve the r9 register (ARM only)">; def mno_movt : Flag<["-"], "mno-movt">, Group<m_arm_Features_Group>, HelpText<"Disallow use of movt/movw pairs (ARM only)">; -def mcrc : Flag<["-"], "mcrc">, Group<m_arm_Features_Group>, - HelpText<"Allow use of CRC instructions (ARM only)">; +def mcrc : Flag<["-"], "mcrc">, Group<m_Group>, + HelpText<"Allow use of CRC instructions (ARM/Mips only)">; def mnocrc : Flag<["-"], "mnocrc">, Group<m_arm_Features_Group>, HelpText<"Disallow use of CRC instructions (ARM only)">; def mno_neg_immediates: Flag<["-"], "mno-neg-immediates">, Group<m_arm_Features_Group>, @@ -1844,11 +2027,17 @@ def mno_fix_cortex_a53_835769 : Flag<["-"], "mno-fix-cortex-a53-835769">, HelpText<"Don't workaround Cortex-A53 erratum 835769 (AArch64 only)">; def ffixed_x18 : Flag<["-"], "ffixed-x18">, Group<m_aarch64_Features_Group>, HelpText<"Reserve the x18 register (AArch64 only)">; +def ffixed_x20 : Flag<["-"], "ffixed-x20">, Group<m_aarch64_Features_Group>, + HelpText<"Reserve the x20 register (AArch64 only)">; def msimd128 : Flag<["-"], "msimd128">, Group<m_wasm_Features_Group>; def mno_simd128 : Flag<["-"], "mno-simd128">, Group<m_wasm_Features_Group>; def mnontrapping_fptoint : Flag<["-"], "mnontrapping-fptoint">, Group<m_wasm_Features_Group>; def mno_nontrapping_fptoint : Flag<["-"], "mno-nontrapping-fptoint">, Group<m_wasm_Features_Group>; +def msign_ext : Flag<["-"], "msign-ext">, Group<m_wasm_Features_Group>; +def mno_sign_ext : Flag<["-"], "mno-sign-ext">, Group<m_wasm_Features_Group>; +def mexception_handing : Flag<["-"], "mexception-handling">, Group<m_wasm_Features_Group>; +def mno_exception_handing : Flag<["-"], "mno-exception-handling">, Group<m_wasm_Features_Group>; def mamdgpu_debugger_abi : Joined<["-"], "mamdgpu-debugger-abi=">, Flags<[HelpHidden]>, @@ -1866,6 +2055,7 @@ def maltivec : Flag<["-"], "maltivec">, Group<m_ppc_Features_Group>; def mno_altivec : Flag<["-"], "mno-altivec">, Group<m_ppc_Features_Group>; def mvsx : Flag<["-"], "mvsx">, Group<m_ppc_Features_Group>; def mno_vsx : Flag<["-"], "mno-vsx">, Group<m_ppc_Features_Group>; +def msecure_plt : Flag<["-"], "msecure-plt">, Group<m_ppc_Features_Group>; def mpower8_vector : Flag<["-"], "mpower8-vector">, Group<m_ppc_Features_Group>; def mno_power8_vector : Flag<["-"], "mno-power8-vector">, @@ -1962,124 +2152,141 @@ def mpie_copy_relocations : Flag<["-"], "mpie-copy-relocations">, Group<m_Group> def mno_pie_copy_relocations : Flag<["-"], "mno-pie-copy-relocations">, Group<m_Group>; def mfentry : Flag<["-"], "mfentry">, HelpText<"Insert calls to fentry at function entry (x86 only)">, Flags<[CC1Option]>, Group<m_Group>; -def mips16 : Flag<["-"], "mips16">, Group<m_Group>; -def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_Group>; -def mmicromips : Flag<["-"], "mmicromips">, Group<m_Group>; -def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_Group>; -def mxgot : Flag<["-"], "mxgot">, Group<m_Group>; -def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_Group>; -def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_Group>; -def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_Group>; -def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, Group<m_Group>; +def mips16 : Flag<["-"], "mips16">, Group<m_mips_Features_Group>; +def mno_mips16 : Flag<["-"], "mno-mips16">, Group<m_mips_Features_Group>; +def mmicromips : Flag<["-"], "mmicromips">, Group<m_mips_Features_Group>; +def mno_micromips : Flag<["-"], "mno-micromips">, Group<m_mips_Features_Group>; +def mxgot : Flag<["-"], "mxgot">, Group<m_mips_Features_Group>; +def mno_xgot : Flag<["-"], "mno-xgot">, Group<m_mips_Features_Group>; +def mldc1_sdc1 : Flag<["-"], "mldc1-sdc1">, Group<m_mips_Features_Group>; +def mno_ldc1_sdc1 : Flag<["-"], "mno-ldc1-sdc1">, Group<m_mips_Features_Group>; +def mcheck_zero_division : Flag<["-"], "mcheck-zero-division">, + Group<m_mips_Features_Group>; def mno_check_zero_division : Flag<["-"], "mno-check-zero-division">, - Group<m_Group>; -def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, Group<m_Group>; + Group<m_mips_Features_Group>; +def mcompact_branches_EQ : Joined<["-"], "mcompact-branches=">, + Group<m_mips_Features_Group>; def mbranch_likely : Flag<["-"], "mbranch-likely">, Group<m_Group>, IgnoredGCCCompat; def mno_branch_likely : Flag<["-"], "mno-branch-likely">, Group<m_Group>, IgnoredGCCCompat; -def mdsp : Flag<["-"], "mdsp">, Group<m_Group>; -def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_Group>; -def mdspr2 : Flag<["-"], "mdspr2">, Group<m_Group>; -def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_Group>; -def msingle_float : Flag<["-"], "msingle-float">, Group<m_Group>; -def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_Group>; -def mmadd4 : Flag<["-"], "mmadd4">, Group<m_Group>, +def mindirect_jump_EQ : Joined<["-"], "mindirect-jump=">, + Group<m_mips_Features_Group>, + HelpText<"Change indirect jump instructions to inhibit speculation">; +def mdsp : Flag<["-"], "mdsp">, Group<m_mips_Features_Group>; +def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_mips_Features_Group>; +def mdspr2 : Flag<["-"], "mdspr2">, Group<m_mips_Features_Group>; +def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_mips_Features_Group>; +def msingle_float : Flag<["-"], "msingle-float">, Group<m_mips_Features_Group>; +def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_mips_Features_Group>; +def mmadd4 : Flag<["-"], "mmadd4">, Group<m_mips_Features_Group>, HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">; -def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_Group>, +def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_mips_Features_Group>, HelpText<"Disable the generation of 4-operand madd.s, madd.d and related instructions.">; -def mmsa : Flag<["-"], "mmsa">, Group<m_Group>, +def mmsa : Flag<["-"], "mmsa">, Group<m_mips_Features_Group>, HelpText<"Enable MSA ASE (MIPS only)">; -def mno_msa : Flag<["-"], "mno-msa">, Group<m_Group>, +def mno_msa : Flag<["-"], "mno-msa">, Group<m_mips_Features_Group>, HelpText<"Disable MSA ASE (MIPS only)">; -def mmt : Flag<["-"], "mmt">, Group<m_Group>, +def mmt : Flag<["-"], "mmt">, Group<m_mips_Features_Group>, HelpText<"Enable MT ASE (MIPS only)">; -def mno_mt : Flag<["-"], "mno-mt">, Group<m_Group>, +def mno_mt : Flag<["-"], "mno-mt">, Group<m_mips_Features_Group>, HelpText<"Disable MT ASE (MIPS only)">; -def mfp64 : Flag<["-"], "mfp64">, Group<m_Group>, +def mfp64 : Flag<["-"], "mfp64">, Group<m_mips_Features_Group>, HelpText<"Use 64-bit floating point registers (MIPS only)">; -def mfp32 : Flag<["-"], "mfp32">, Group<m_Group>, +def mfp32 : Flag<["-"], "mfp32">, Group<m_mips_Features_Group>, HelpText<"Use 32-bit floating point registers (MIPS only)">; -def mgpopt : Flag<["-"], "mgpopt">, Group<m_Group>, +def mgpopt : Flag<["-"], "mgpopt">, Group<m_mips_Features_Group>, HelpText<"Use GP relative accesses for symbols known to be in a small" " data section (MIPS)">; -def mno_gpopt : Flag<["-"], "mno-gpopt">, Group<m_Group>, +def mno_gpopt : Flag<["-"], "mno-gpopt">, Group<m_mips_Features_Group>, HelpText<"Do not use GP relative accesses for symbols known to be in a small" " data section (MIPS)">; -def mlocal_sdata : Flag<["-"], "mlocal-sdata">, Group<m_Group>, +def mlocal_sdata : Flag<["-"], "mlocal-sdata">, + Group<m_mips_Features_Group>, HelpText<"Extend the -G behaviour to object local data (MIPS)">; -def mno_local_sdata : Flag<["-"], "mno-local-sdata">, Group<m_Group>, +def mno_local_sdata : Flag<["-"], "mno-local-sdata">, + Group<m_mips_Features_Group>, HelpText<"Do not extend the -G behaviour to object local data (MIPS)">; -def mextern_sdata : Flag<["-"], "mextern-sdata">, Group<m_Group>, +def mextern_sdata : Flag<["-"], "mextern-sdata">, + Group<m_mips_Features_Group>, HelpText<"Assume that externally defined data is in the small data if it" " meets the -G <size> threshold (MIPS)">; -def mno_extern_sdata : Flag<["-"], "mno-extern-sdata">, Group<m_Group>, +def mno_extern_sdata : Flag<["-"], "mno-extern-sdata">, + Group<m_mips_Features_Group>, HelpText<"Do not assume that externally defined data is in the small data if" " it meets the -G <size> threshold (MIPS)">; -def membedded_data : Flag<["-"], "membedded-data">, Group<m_Group>, +def membedded_data : Flag<["-"], "membedded-data">, + Group<m_mips_Features_Group>, HelpText<"Place constants in the .rodata section instead of the .sdata " "section even if they meet the -G <size> threshold (MIPS)">; -def mno_embedded_data : Flag<["-"], "mno-embedded-data">, Group<m_Group>, +def mno_embedded_data : Flag<["-"], "mno-embedded-data">, + Group<m_mips_Features_Group>, HelpText<"Do not place constants in the .rodata section instead of the " ".sdata if they meet the -G <size> threshold (MIPS)">; -def mnan_EQ : Joined<["-"], "mnan=">, Group<m_Group>; -def mabs_EQ : Joined<["-"], "mabs=">, Group<m_Group>; -def mabicalls : Flag<["-"], "mabicalls">, Group<m_Group>, +def mnan_EQ : Joined<["-"], "mnan=">, Group<m_mips_Features_Group>; +def mabs_EQ : Joined<["-"], "mabs=">, Group<m_mips_Features_Group>; +def mabicalls : Flag<["-"], "mabicalls">, Group<m_mips_Features_Group>, HelpText<"Enable SVR4-style position-independent code (Mips only)">; -def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_Group>, +def mno_abicalls : Flag<["-"], "mno-abicalls">, Group<m_mips_Features_Group>, HelpText<"Disable SVR4-style position-independent code (Mips only)">; +def mno_crc : Flag<["-"], "mno-crc">, Group<m_mips_Features_Group>, + HelpText<"Disallow use of CRC instructions (Mips only)">; +def mvirt : Flag<["-"], "mvirt">, Group<m_mips_Features_Group>; +def mno_virt : Flag<["-"], "mno-virt">, Group<m_mips_Features_Group>; +def mginv : Flag<["-"], "mginv">, Group<m_mips_Features_Group>; +def mno_ginv : Flag<["-"], "mno-ginv">, Group<m_mips_Features_Group>; def mips1 : Flag<["-"], "mips1">, - Alias<march_EQ>, AliasArgs<["mips1"]>, + Alias<march_EQ>, AliasArgs<["mips1"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips1">, Flags<[HelpHidden]>; def mips2 : Flag<["-"], "mips2">, - Alias<march_EQ>, AliasArgs<["mips2"]>, + Alias<march_EQ>, AliasArgs<["mips2"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips2">, Flags<[HelpHidden]>; def mips3 : Flag<["-"], "mips3">, - Alias<march_EQ>, AliasArgs<["mips3"]>, + Alias<march_EQ>, AliasArgs<["mips3"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips3">, Flags<[HelpHidden]>; def mips4 : Flag<["-"], "mips4">, - Alias<march_EQ>, AliasArgs<["mips4"]>, + Alias<march_EQ>, AliasArgs<["mips4"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips4">, Flags<[HelpHidden]>; def mips5 : Flag<["-"], "mips5">, - Alias<march_EQ>, AliasArgs<["mips5"]>, + Alias<march_EQ>, AliasArgs<["mips5"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips5">, Flags<[HelpHidden]>; def mips32 : Flag<["-"], "mips32">, - Alias<march_EQ>, AliasArgs<["mips32"]>, + Alias<march_EQ>, AliasArgs<["mips32"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips32">, Flags<[HelpHidden]>; def mips32r2 : Flag<["-"], "mips32r2">, - Alias<march_EQ>, AliasArgs<["mips32r2"]>, + Alias<march_EQ>, AliasArgs<["mips32r2"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips32r2">, Flags<[HelpHidden]>; def mips32r3 : Flag<["-"], "mips32r3">, - Alias<march_EQ>, AliasArgs<["mips32r3"]>, + Alias<march_EQ>, AliasArgs<["mips32r3"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips32r3">, Flags<[HelpHidden]>; def mips32r5 : Flag<["-"], "mips32r5">, - Alias<march_EQ>, AliasArgs<["mips32r5"]>, + Alias<march_EQ>, AliasArgs<["mips32r5"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips32r5">, Flags<[HelpHidden]>; def mips32r6 : Flag<["-"], "mips32r6">, - Alias<march_EQ>, AliasArgs<["mips32r6"]>, + Alias<march_EQ>, AliasArgs<["mips32r6"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips32r6">, Flags<[HelpHidden]>; def mips64 : Flag<["-"], "mips64">, - Alias<march_EQ>, AliasArgs<["mips64"]>, + Alias<march_EQ>, AliasArgs<["mips64"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips64">, Flags<[HelpHidden]>; def mips64r2 : Flag<["-"], "mips64r2">, - Alias<march_EQ>, AliasArgs<["mips64r2"]>, + Alias<march_EQ>, AliasArgs<["mips64r2"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips64r2">, Flags<[HelpHidden]>; def mips64r3 : Flag<["-"], "mips64r3">, - Alias<march_EQ>, AliasArgs<["mips64r3"]>, + Alias<march_EQ>, AliasArgs<["mips64r3"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips64r3">, Flags<[HelpHidden]>; def mips64r5 : Flag<["-"], "mips64r5">, - Alias<march_EQ>, AliasArgs<["mips64r5"]>, + Alias<march_EQ>, AliasArgs<["mips64r5"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips64r5">, Flags<[HelpHidden]>; def mips64r6 : Flag<["-"], "mips64r6">, - Alias<march_EQ>, AliasArgs<["mips64r6"]>, + Alias<march_EQ>, AliasArgs<["mips64r6"]>, Group<m_mips_Features_Group>, HelpText<"Equivalent to -march=mips64r6">, Flags<[HelpHidden]>; -def mfpxx : Flag<["-"], "mfpxx">, Group<m_Group>, +def mfpxx : Flag<["-"], "mfpxx">, Group<m_mips_Features_Group>, HelpText<"Avoid FPU mode dependent operations when used with the O32 ABI">, Flags<[HelpHidden]>; -def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_Group>, +def modd_spreg : Flag<["-"], "modd-spreg">, Group<m_mips_Features_Group>, HelpText<"Enable odd single-precision floating point registers">, Flags<[HelpHidden]>; -def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_Group>, +def mno_odd_spreg : Flag<["-"], "mno-odd-spreg">, Group<m_mips_Features_Group>, HelpText<"Disable odd single-precision floating point registers">, Flags<[HelpHidden]>; def mglibc : Flag<["-"], "mglibc">, Group<m_libc_Group>, Flags<[HelpHidden]>; @@ -2092,7 +2299,7 @@ def multi__module : Flag<["-"], "multi_module">; def multiply__defined__unused : Separate<["-"], "multiply_defined_unused">; def multiply__defined : Separate<["-"], "multiply_defined">; def mwarn_nonportable_cfstrings : Flag<["-"], "mwarn-nonportable-cfstrings">, Group<m_Group>; -def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden]>, +def no_canonical_prefixes : Flag<["-"], "no-canonical-prefixes">, Flags<[HelpHidden, CoreOption]>, HelpText<"Use relative instead of canonical paths">; def no_cpp_precomp : Flag<["-"], "no-cpp-precomp">, Group<clang_ignored_f_Group>; def no_integrated_cpp : Flag<["-", "--"], "no-integrated-cpp">, Flags<[DriverOption]>; @@ -2175,7 +2382,7 @@ def fno_rtlib_add_rpath: Flag<["-"], "fno-rtlib-add-rpath">, Flags<[NoArgumentUn HelpText<"Do not add -rpath with architecture-specific resource directory to the linker flags">; def r : Flag<["-"], "r">, Flags<[LinkerInput,NoArgumentUnused]>, Group<Link_Group>; -def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[DriverOption]>, +def save_temps_EQ : Joined<["-", "--"], "save-temps=">, Flags<[CC1Option, DriverOption]>, HelpText<"Save intermediate compilation results.">; def save_temps : Flag<["-", "--"], "save-temps">, Flags<[DriverOption]>, Alias<save_temps_EQ>, AliasArgs<["cwd"]>, @@ -2326,7 +2533,8 @@ def _for_linker_EQ : Joined<["--"], "for-linker=">, Alias<Xlinker>; def _for_linker : Separate<["--"], "for-linker">, Alias<Xlinker>; def _force_link_EQ : Joined<["--"], "force-link=">, Alias<u>; def _force_link : Separate<["--"], "force-link">, Alias<u>; -def _help_hidden : Flag<["--"], "help-hidden">; +def _help_hidden : Flag<["--"], "help-hidden">, + HelpText<"Display help for hidden options">; def _imacros_EQ : Joined<["--"], "imacros=">, Alias<imacros>; def _include_barrier : Flag<["--"], "include-barrier">, Alias<I_>; def _include_directory_after_EQ : Joined<["--"], "include-directory-after=">, Alias<idirafter>; @@ -2396,39 +2604,50 @@ def _write_dependencies : Flag<["--"], "write-dependencies">, Alias<MD>; def _write_user_dependencies : Flag<["--"], "write-user-dependencies">, Alias<MMD>; def _ : Joined<["--"], "">, Flags<[Unsupported]>; -def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, Group<m_hexagon_Features_Group>; +// Hexagon feature flags. +def mieee_rnd_near : Flag<["-"], "mieee-rnd-near">, + Group<m_hexagon_Features_Group>; def mv4 : Flag<["-"], "mv4">, Group<m_hexagon_Features_Group>, - Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>; + Alias<mcpu_EQ>, AliasArgs<["hexagonv4"]>; def mv5 : Flag<["-"], "mv5">, Group<m_hexagon_Features_Group>, Alias<mcpu_EQ>, - AliasArgs<["hexagonv5"]>; + AliasArgs<["hexagonv5"]>; def mv55 : Flag<["-"], "mv55">, Group<m_hexagon_Features_Group>, - Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>; + Alias<mcpu_EQ>, AliasArgs<["hexagonv55"]>; def mv60 : Flag<["-"], "mv60">, Group<m_hexagon_Features_Group>, - Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>; + Alias<mcpu_EQ>, AliasArgs<["hexagonv60"]>; def mv62 : Flag<["-"], "mv62">, Group<m_hexagon_Features_Group>, - Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>; + Alias<mcpu_EQ>, AliasArgs<["hexagonv62"]>; def mv65 : Flag<["-"], "mv65">, Group<m_hexagon_Features_Group>, - Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>; -def mhexagon_hvx : Flag<[ "-" ], "mhvx">, - Group<m_hexagon_Features_HVX_Group>, - HelpText<"Enable Hexagon Vector eXtensions">; -def mhexagon_hvx_EQ : Joined<[ "-" ], "mhvx=">, - Group<m_hexagon_Features_HVX_Group>, - HelpText<"Enable Hexagon Vector eXtensions">; -def mno_hexagon_hvx : Flag<[ "-" ], "mno-hvx">, - Group<m_hexagon_Features_HVX_Group>, - HelpText<"Disable Hexagon Vector eXtensions">; -def mhexagon_hvx_length_EQ : Joined<[ "-" ], "mhvx-length=">, - Group<m_hexagon_Features_HVX_Group>, - HelpText<"Set Hexagon Vector Length">, Values<"64B,128B">; -// hvx-double deprecrated flag. -def mhexagon_hvx_double : Flag<[ "-" ], "mhvx-double">, - Group<m_hexagon_Features_HVX_Group>, - HelpText<"Enable Hexagon Double Vector eXtensions">; -def mno_hexagon_hvx_double - : Flag<[ "-" ], "mno-hvx-double">, - Group<m_hexagon_Features_HVX_Group>, - HelpText<"Disable Hexagon Double Vector eXtensions">; + Alias<mcpu_EQ>, AliasArgs<["hexagonv65"]>; +def mhexagon_hvx : Flag<["-"], "mhvx">, Group<m_hexagon_Features_HVX_Group>, + HelpText<"Enable Hexagon Vector eXtensions">; +def mhexagon_hvx_EQ : Joined<["-"], "mhvx=">, + Group<m_hexagon_Features_HVX_Group>, + HelpText<"Enable Hexagon Vector eXtensions">; +def mno_hexagon_hvx : Flag<["-"], "mno-hvx">, + Group<m_hexagon_Features_HVX_Group>, + HelpText<"Disable Hexagon Vector eXtensions">; +def mhexagon_hvx_length_EQ : Joined<["-"], "mhvx-length=">, + Group<m_hexagon_Features_HVX_Group>, HelpText<"Set Hexagon Vector Length">, + Values<"64B,128B">; +def ffixed_r19: Flag<["-"], "ffixed-r19">, + HelpText<"Reserve register r19 (Hexagon only)">; +def mmemops : Flag<["-"], "mmemops">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Enable generation of memop instructions">; +def mno_memops : Flag<["-"], "mno-memops">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Disable generation of memop instructions">; +def mpackets : Flag<["-"], "mpackets">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Enable generation of instruction packets">; +def mno_packets : Flag<["-"], "mno-packets">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Disable generation of instruction packets">; +def mnvj : Flag<["-"], "mnvj">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Enable generation of new-value jumps">; +def mno_nvj : Flag<["-"], "mno-nvj">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Disable generation of new-value jumps">; +def mnvs : Flag<["-"], "mnvs">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Enable generation of new-value stores">; +def mno_nvs : Flag<["-"], "mno-nvs">, Group<m_hexagon_Features_Group>, + Flags<[CC1Option]>, HelpText<"Disable generation of new-value stores">; // X86 feature flags @@ -2499,10 +2718,14 @@ def mbmi : Flag<["-"], "mbmi">, Group<m_x86_Features_Group>; def mno_bmi : Flag<["-"], "mno-bmi">, Group<m_x86_Features_Group>; def mbmi2 : Flag<["-"], "mbmi2">, Group<m_x86_Features_Group>; def mno_bmi2 : Flag<["-"], "mno-bmi2">, Group<m_x86_Features_Group>; +def mcldemote : Flag<["-"], "mcldemote">, Group<m_x86_Features_Group>; +def mno_cldemote : Flag<["-"], "mno-cldemote">, Group<m_x86_Features_Group>; def mclflushopt : Flag<["-"], "mclflushopt">, Group<m_x86_Features_Group>; def mno_clflushopt : Flag<["-"], "mno-clflushopt">, Group<m_x86_Features_Group>; def mclwb : Flag<["-"], "mclwb">, Group<m_x86_Features_Group>; def mno_clwb : Flag<["-"], "mno-clwb">, Group<m_x86_Features_Group>; +def mwbnoinvd : Flag<["-"], "mwbnoinvd">, Group<m_x86_Features_Group>; +def mno_wbnoinvd : Flag<["-"], "mno-wbnoinvd">, Group<m_x86_Features_Group>; def mclzero : Flag<["-"], "mclzero">, Group<m_x86_Features_Group>; def mno_clzero : Flag<["-"], "mno-clzero">, Group<m_x86_Features_Group>; def mcx16 : Flag<["-"], "mcx16">, Group<m_x86_Features_Group>; @@ -2517,6 +2740,8 @@ def mfsgsbase : Flag<["-"], "mfsgsbase">, Group<m_x86_Features_Group>; def mno_fsgsbase : Flag<["-"], "mno-fsgsbase">, Group<m_x86_Features_Group>; def mfxsr : Flag<["-"], "mfxsr">, Group<m_x86_Features_Group>; def mno_fxsr : Flag<["-"], "mno-fxsr">, Group<m_x86_Features_Group>; +def minvpcid : Flag<["-"], "minvpcid">, Group<m_x86_Features_Group>; +def mno_invpcid : Flag<["-"], "mno-invpcid">, Group<m_x86_Features_Group>; def mgfni : Flag<["-"], "mgfni">, Group<m_x86_Features_Group>; def mno_gfni : Flag<["-"], "mno-gfni">, Group<m_x86_Features_Group>; def mlwp : Flag<["-"], "mlwp">, Group<m_x86_Features_Group>; @@ -2525,6 +2750,10 @@ def mlzcnt : Flag<["-"], "mlzcnt">, Group<m_x86_Features_Group>; def mno_lzcnt : Flag<["-"], "mno-lzcnt">, Group<m_x86_Features_Group>; def mmovbe : Flag<["-"], "mmovbe">, Group<m_x86_Features_Group>; def mno_movbe : Flag<["-"], "mno-movbe">, Group<m_x86_Features_Group>; +def mmovdiri : Flag<["-"], "mmovdiri">, Group<m_x86_Features_Group>; +def mno_movdiri : Flag<["-"], "mno-movdiri">, Group<m_x86_Features_Group>; +def mmovdir64b : Flag<["-"], "mmovdir64b">, Group<m_x86_Features_Group>; +def mno_movdir64b : Flag<["-"], "mno-movdir64b">, Group<m_x86_Features_Group>; def mmpx : Flag<["-"], "mmpx">, Group<m_x86_Features_Group>; def mno_mpx : Flag<["-"], "mno-mpx">, Group<m_x86_Features_Group>; def mmwaitx : Flag<["-"], "mmwaitx">, Group<m_x86_Features_Group>; @@ -2533,18 +2762,26 @@ def mpku : Flag<["-"], "mpku">, Group<m_x86_Features_Group>; def mno_pku : Flag<["-"], "mno-pku">, Group<m_x86_Features_Group>; def mpclmul : Flag<["-"], "mpclmul">, Group<m_x86_Features_Group>; def mno_pclmul : Flag<["-"], "mno-pclmul">, Group<m_x86_Features_Group>; +def mpconfig : Flag<["-"], "mpconfig">, Group<m_x86_Features_Group>; +def mno_pconfig : Flag<["-"], "mno-pconfig">, Group<m_x86_Features_Group>; def mpopcnt : Flag<["-"], "mpopcnt">, Group<m_x86_Features_Group>; def mno_popcnt : Flag<["-"], "mno-popcnt">, Group<m_x86_Features_Group>; def mprefetchwt1 : Flag<["-"], "mprefetchwt1">, Group<m_x86_Features_Group>; def mno_prefetchwt1 : Flag<["-"], "mno-prefetchwt1">, Group<m_x86_Features_Group>; def mprfchw : Flag<["-"], "mprfchw">, Group<m_x86_Features_Group>; def mno_prfchw : Flag<["-"], "mno-prfchw">, Group<m_x86_Features_Group>; +def mptwrite : Flag<["-"], "mptwrite">, Group<m_x86_Features_Group>; +def mno_ptwrite : Flag<["-"], "mno-ptwrite">, Group<m_x86_Features_Group>; +def mrdpid : Flag<["-"], "mrdpid">, Group<m_x86_Features_Group>; +def mno_rdpid : Flag<["-"], "mno-rdpid">, Group<m_x86_Features_Group>; def mrdrnd : Flag<["-"], "mrdrnd">, Group<m_x86_Features_Group>; def mno_rdrnd : Flag<["-"], "mno-rdrnd">, Group<m_x86_Features_Group>; def mrtm : Flag<["-"], "mrtm">, Group<m_x86_Features_Group>; def mno_rtm : Flag<["-"], "mno-rtm">, Group<m_x86_Features_Group>; def mrdseed : Flag<["-"], "mrdseed">, Group<m_x86_Features_Group>; def mno_rdseed : Flag<["-"], "mno-rdseed">, Group<m_x86_Features_Group>; +def msahf : Flag<["-"], "msahf">, Group<m_x86_Features_Group>; +def mno_sahf : Flag<["-"], "mno-sahf">, Group<m_x86_Features_Group>; def msgx : Flag<["-"], "msgx">, Group<m_x86_Features_Group>; def mno_sgx : Flag<["-"], "mno-sgx">, Group<m_x86_Features_Group>; def msha : Flag<["-"], "msha">, Group<m_x86_Features_Group>; @@ -2555,6 +2792,8 @@ def mvaes : Flag<["-"], "mvaes">, Group<m_x86_Features_Group>; def mno_vaes : Flag<["-"], "mno-vaes">, Group<m_x86_Features_Group>; def mvpclmulqdq : Flag<["-"], "mvpclmulqdq">, Group<m_x86_Features_Group>; def mno_vpclmulqdq : Flag<["-"], "mno-vpclmulqdq">, Group<m_x86_Features_Group>; +def mwaitpkg : Flag<["-"], "mwaitpkg">, Group<m_x86_Features_Group>; +def mno_waitpkg : Flag<["-"], "mno-waitpkg">, Group<m_x86_Features_Group>; def mxop : Flag<["-"], "mxop">, Group<m_x86_Features_Group>; def mno_xop : Flag<["-"], "mno-xop">, Group<m_x86_Features_Group>; def mxsave : Flag<["-"], "mxsave">, Group<m_x86_Features_Group>; @@ -2567,8 +2806,10 @@ def mxsaves : Flag<["-"], "mxsaves">, Group<m_x86_Features_Group>; def mno_xsaves : Flag<["-"], "mno-xsaves">, Group<m_x86_Features_Group>; def mshstk : Flag<["-"], "mshstk">, Group<m_x86_Features_Group>; def mno_shstk : Flag<["-"], "mno-shstk">, Group<m_x86_Features_Group>; -def mibt : Flag<["-"], "mibt">, Group<m_x86_Features_Group>; -def mno_ibt : Flag<["-"], "mno-ibt">, Group<m_x86_Features_Group>; +def mretpoline : Flag<["-"], "mretpoline">, Group<m_x86_Features_Group>; +def mno_retpoline : Flag<["-"], "mno-retpoline">, Group<m_x86_Features_Group>; +def mretpoline_external_thunk : Flag<["-"], "mretpoline-external-thunk">, Group<m_x86_Features_Group>; +def mno_retpoline_external_thunk : Flag<["-"], "mno-retpoline-external-thunk">, Group<m_x86_Features_Group>; // These are legacy user-facing driver-level option spellings. They are always // aliases for options that are spelled using the more common Unix / GNU flag @@ -2604,8 +2845,6 @@ def fprofile_dir : Joined<["-"], "fprofile-dir=">, Group<f_Group>; def fuse_ld_EQ : Joined<["-"], "fuse-ld=">, Group<f_Group>, Flags<[CoreOption]>; -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>; @@ -2623,8 +2862,6 @@ defm reorder_blocks : BooleanFFlag<"reorder-blocks">, Group<clang_ignored_gcc_op 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>; @@ -2634,7 +2871,6 @@ defm gcse_after_reload: BooleanFFlag<"gcse-after-reload">, Group<clang_ignored_g 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>; diff --git a/include/clang/Driver/SanitizerArgs.h b/include/clang/Driver/SanitizerArgs.h index a31ac05afc1bb..d144e488b56bb 100644 --- a/include/clang/Driver/SanitizerArgs.h +++ b/include/clang/Driver/SanitizerArgs.h @@ -30,7 +30,7 @@ class SanitizerArgs { std::vector<std::string> ExtraDeps; int CoverageFeatures = 0; int MsanTrackOrigins = 0; - bool MsanUseAfterDtor = false; + bool MsanUseAfterDtor = true; bool CfiCrossDso = false; bool CfiICallGeneralizePointers = false; int AsanFieldPadding = 0; diff --git a/include/clang/Driver/Tool.h b/include/clang/Driver/Tool.h index 8f76e17c48bae..b02ac66d3b5cf 100644 --- a/include/clang/Driver/Tool.h +++ b/include/clang/Driver/Tool.h @@ -88,12 +88,12 @@ public: 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, + /// 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 + /// 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. /// @@ -108,11 +108,11 @@ public: llvm::sys::WindowsEncodingMethod getResponseFileEncoding() const { return ResponseEncoding; } - /// \brief Returns which prefix to use when passing the name of a response + /// 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 + /// Does this tool have "good" standardized diagnostics, or should the /// driver add an additional "command failed" diagnostic on failures. virtual bool hasGoodDiagnostics() const { return false; } diff --git a/include/clang/Driver/ToolChain.h b/include/clang/Driver/ToolChain.h index 13f54d3718b4c..addf7aa6a9c8d 100644 --- a/include/clang/Driver/ToolChain.h +++ b/include/clang/Driver/ToolChain.h @@ -1,4 +1,4 @@ -//===--- ToolChain.h - Collections of tools for one platform ----*- C++ -*-===// +//===- ToolChain.h - Collections of tools for one platform ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,69 +10,84 @@ #ifndef LLVM_CLANG_DRIVER_TOOLCHAIN_H #define LLVM_CLANG_DRIVER_TOOLCHAIN_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/Sanitizers.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Driver/Action.h" #include "clang/Driver/Multilib.h" #include "clang/Driver/Types.h" -#include "clang/Driver/Util.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/Triple.h" +#include "llvm/MC/MCTargetOptions.h" +#include "llvm/Option/Option.h" +#include "llvm/Support/VersionTuple.h" #include "llvm/Target/TargetOptions.h" +#include <cassert> #include <memory> #include <string> +#include <utility> namespace llvm { namespace opt { - class ArgList; - class DerivedArgList; - class InputArgList; -} -} + +class Arg; +class ArgList; +class DerivedArgList; + +} // namespace opt +} // namespace llvm namespace clang { + class ObjCRuntime; + namespace vfs { + class FileSystem; -} + +} // namespace vfs namespace driver { - class Compilation; - class CudaInstallationDetector; - class Driver; - class InputInfo; - class JobAction; - class RegisterEffectiveTriple; - class SanitizerArgs; - class Tool; - class XRayArgs; + +class Driver; +class InputInfo; +class SanitizerArgs; +class Tool; +class XRayArgs; /// Helper structure used to pass information extracted from clang executable /// name such as `i686-linux-android-g++`. -/// struct ParsedClangName { /// Target part of the executable name, as `i686-linux-android`. std::string TargetPrefix; + /// Driver mode part of the executable name, as `g++`. std::string ModeSuffix; + /// Corresponding driver mode argument, as '--driver-mode=g++' - const char *DriverMode; + const char *DriverMode = nullptr; + /// True if TargetPrefix is recognized as a registered target name. - bool TargetIsValid; + bool TargetIsValid = false; - ParsedClangName() : DriverMode(nullptr), TargetIsValid(false) {} + ParsedClangName() = default; ParsedClangName(std::string Suffix, const char *Mode) - : ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(false) {} + : ModeSuffix(Suffix), DriverMode(Mode) {} ParsedClangName(std::string Target, std::string Suffix, const char *Mode, bool IsRegistered) : TargetPrefix(Target), ModeSuffix(Suffix), DriverMode(Mode), TargetIsValid(IsRegistered) {} + + bool isEmpty() const { + return TargetPrefix.empty() && ModeSuffix.empty() && DriverMode == nullptr; + } }; /// ToolChain - Access to tools for a single platform. class ToolChain { public: - typedef SmallVector<std::string, 16> path_list; + using path_list = SmallVector<std::string, 16>; enum CXXStdlibType { CST_Libcxx, @@ -85,32 +100,33 @@ public: }; enum RTTIMode { - RM_EnabledExplicitly, - RM_EnabledImplicitly, - RM_DisabledExplicitly, - RM_DisabledImplicitly + RM_Enabled, + RM_Disabled, }; private: + friend class RegisterEffectiveTriple; + const Driver &D; llvm::Triple Triple; const llvm::opt::ArgList &Args; + // We need to initialize CachedRTTIArg before CachedRTTIMode const llvm::opt::Arg *const CachedRTTIArg; + const RTTIMode CachedRTTIMode; - /// The list of toolchain specific path prefixes to search for - /// files. + /// The list of toolchain specific path prefixes to search for files. path_list FilePaths; - /// The list of toolchain specific path prefixes to search for - /// programs. + /// The list of toolchain specific path prefixes to search for programs. path_list ProgramPaths; mutable std::unique_ptr<Tool> Clang; mutable std::unique_ptr<Tool> Assemble; mutable std::unique_ptr<Tool> Link; mutable std::unique_ptr<Tool> OffloadBundler; + Tool *getClang() const; Tool *getAssemble() const; Tool *getLink() const; @@ -128,8 +144,6 @@ private: EffectiveTriple = std::move(ET); } - friend class RegisterEffectiveTriple; - protected: MultilibSet Multilibs; @@ -185,7 +199,7 @@ public: StringRef getPlatform() const { return Triple.getVendorName(); } StringRef getOS() const { return Triple.getOSName(); } - /// \brief Provide the default architecture name (as expected by -arch) for + /// Provide the default architecture name (as expected by -arch) for /// this toolchain. StringRef getDefaultUniversalArchName() const; @@ -217,7 +231,7 @@ public: // Returns the RTTIMode for the toolchain with the current arguments. RTTIMode getRTTIMode() const { return CachedRTTIMode; } - /// \brief Return any implicit target and/or mode flag for an invocation of + /// Return any implicit target and/or mode flag for an invocation of /// the compiler driver as `ProgName`. /// /// For example, when called with i686-linux-android-g++, the first element @@ -231,7 +245,6 @@ public: /// e.g., argv[0]). /// \return A structure of type ParsedClangName that contains the executable /// name parts. - /// static ParsedClangName getTargetAndModeFromProgramName(StringRef ProgName); // Tool access. @@ -272,7 +285,7 @@ public: /// the linker suffix or name. std::string GetLinkerPath() const; - /// \brief Dispatch to the specific toolchain for verbose printing. + /// Dispatch to the specific toolchain for verbose printing. /// /// This is used when handling the verbose option to print detailed, /// toolchain-specific information useful for understanding the behavior of @@ -281,7 +294,7 @@ public: // Platform defaults information - /// \brief Returns true if the toolchain is targeting a non-native + /// Returns true if the toolchain is targeting a non-native /// architecture. virtual bool isCrossCompiling() const; @@ -300,7 +313,7 @@ public: /// by default. virtual bool IsIntegratedAssemblerDefault() const { return false; } - /// \brief Check if the toolchain should use the integrated assembler. + /// Check if the toolchain should use the integrated assembler. virtual bool useIntegratedAs() const; /// IsMathErrnoDefault - Does this tool chain use -fmath-errno by default. @@ -318,7 +331,7 @@ public: /// mixed dispatch method be used? virtual bool UseObjCMixedDispatch() const { return false; } - /// \brief Check whether to enable x86 relax relocations by default. + /// Check whether to enable x86 relax relocations by default. virtual bool useRelaxRelocations() const; /// GetDefaultStackProtectorLevel - Get the default stack protector level for @@ -328,9 +341,7 @@ public: } /// GetDefaultLinker - Get the default linker to use. - virtual const char *getDefaultLinker() const { - return "ld"; - } + virtual const char *getDefaultLinker() const { return "ld"; } /// GetDefaultRuntimeLibType - Get the default runtime library variant to use. virtual RuntimeLibType GetDefaultRuntimeLibType() const { @@ -355,6 +366,9 @@ public: // as OpenMP) to find arch-specific libraries. std::string getArchSpecificLibPath() const; + // Returns <OSname> part of above. + StringRef getOSLibName() const; + /// needsProfileRT - returns true if instrumentation profile is on. static bool needsProfileRT(const llvm::opt::ArgList &Args); @@ -362,13 +376,13 @@ public: /// by default. virtual bool IsUnwindTablesDefault(const llvm::opt::ArgList &Args) const; - /// \brief Test whether this toolchain defaults to PIC. + /// Test whether this toolchain defaults to PIC. virtual bool isPICDefault() const = 0; - /// \brief Test whether this toolchain defaults to PIE. + /// Test whether this toolchain defaults to PIE. virtual bool isPIEDefault() const = 0; - /// \brief Tests whether this toolchain forces its default for PIC, PIE or + /// Tests whether this toolchain forces its default for PIC, PIE or /// non-PIC. If this returns true, any PIC related flags should be ignored /// and instead the results of \c isPICDefault() and \c isPIEDefault() are /// used exclusively. @@ -404,9 +418,7 @@ public: GetExceptionModel(const llvm::opt::ArgList &Args) const; /// SupportsEmbeddedBitcode - Does this tool chain support embedded bitcode. - virtual bool SupportsEmbeddedBitcode() const { - return false; - } + virtual bool SupportsEmbeddedBitcode() const { return false; } /// getThreadModel() - Which thread model does this target use? virtual std::string getThreadModel() const { return "posix"; } @@ -442,7 +454,7 @@ public: /// FIXME: this really belongs on some sort of DeploymentTarget abstraction virtual bool hasBlocksRuntime() const { return true; } - /// \brief Add the clang cc1 arguments for system include paths. + /// Add the clang cc1 arguments for system include paths. /// /// This routine is responsible for adding the necessary cc1 arguments to /// include headers from standard system header directories. @@ -450,12 +462,12 @@ public: AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; - /// \brief Add options that need to be passed to cc1 for this target. + /// Add options that need to be passed to cc1 for this target. virtual void addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, Action::OffloadKind DeviceOffloadKind) const; - /// \brief Add warning options that need to be passed to cc1 for this target. + /// Add warning options that need to be passed to cc1 for this target. virtual void addClangWarningOptions(llvm::opt::ArgStringList &CC1Args) const; // GetRuntimeLibType - Determine the runtime library type to use with the @@ -497,27 +509,28 @@ public: /// This checks for presence of the -Ofast, -ffast-math or -funsafe-math flags. virtual bool AddFastMathRuntimeIfAvailable( const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + /// addProfileRTLibs - When -fprofile-instr-profile is specified, try to pass /// a suitable profile runtime library to the linker. virtual void addProfileRTLibs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; - /// \brief Add arguments to use system-specific CUDA includes. + /// Add arguments to use system-specific CUDA includes. virtual void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; - /// \brief Add arguments to use MCU GCC toolchain includes. + /// Add arguments to use MCU GCC toolchain includes. virtual void AddIAMCUIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const; - /// \brief On Windows, returns the MSVC compatibility version. + /// On Windows, returns the MSVC compatibility version. virtual VersionTuple computeMSVCVersion(const Driver *D, const llvm::opt::ArgList &Args) const; - /// \brief Return sanitizers which are available in this toolchain. + /// Return sanitizers which are available in this toolchain. virtual SanitizerMask getSupportedSanitizers() const; - /// \brief Return sanitizers which are enabled by default. + /// Return sanitizers which are enabled by default. virtual SanitizerMask getDefaultSanitizers() const { return 0; } }; @@ -534,7 +547,8 @@ public: ~RegisterEffectiveTriple() { TC.setEffectiveTriple(llvm::Triple()); } }; -} // end namespace driver -} // end namespace clang +} // namespace driver + +} // namespace clang -#endif +#endif // LLVM_CLANG_DRIVER_TOOLCHAIN_H diff --git a/include/clang/Driver/Types.def b/include/clang/Driver/Types.def index 2430b5b924c32..c23f1f13361f7 100644 --- a/include/clang/Driver/Types.def +++ b/include/clang/Driver/Types.def @@ -46,6 +46,9 @@ TYPE("cl", CL, PP_C, "cl", "u") TYPE("cuda-cpp-output", PP_CUDA, INVALID, "cui", "u") TYPE("cuda", CUDA, PP_CUDA, "cu", "u") TYPE("cuda", CUDA_DEVICE, PP_CUDA, "cu", "") +TYPE("hip-cpp-output", PP_HIP, INVALID, "cui", "u") +TYPE("hip", HIP, PP_HIP, "cu", "u") +TYPE("hip", HIP_DEVICE, PP_HIP, "cu", "") TYPE("objective-c-cpp-output", PP_ObjC, INVALID, "mi", "u") TYPE("objc-cpp-output", PP_ObjC_Alias, INVALID, "mi", "u") TYPE("objective-c", ObjC, PP_ObjC, "m", "u") diff --git a/include/clang/Driver/Types.h b/include/clang/Driver/Types.h index 22a26ae46a0b9..5bc6668a0d1de 100644 --- a/include/clang/Driver/Types.h +++ b/include/clang/Driver/Types.h @@ -77,6 +77,9 @@ namespace types { /// isCuda - Is this a CUDA input. bool isCuda(ID Id); + /// isHIP - Is this a HIP input. + bool isHIP(ID Id); + /// isObjC - Is this an "ObjC" input (Obj-C and Obj-C++ sources and headers). bool isObjC(ID Id); diff --git a/include/clang/Driver/XRayArgs.h b/include/clang/Driver/XRayArgs.h index e5b76162de8e2..c7ca945291758 100644 --- a/include/clang/Driver/XRayArgs.h +++ b/include/clang/Driver/XRayArgs.h @@ -9,6 +9,7 @@ #ifndef LLVM_CLANG_DRIVER_XRAYARGS_H #define LLVM_CLANG_DRIVER_XRAYARGS_H +#include "clang/Basic/XRayInstr.h" #include "clang/Driver/Types.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" @@ -21,16 +22,25 @@ class ToolChain; class XRayArgs { std::vector<std::string> AlwaysInstrumentFiles; std::vector<std::string> NeverInstrumentFiles; + std::vector<std::string> AttrListFiles; std::vector<std::string> ExtraDeps; + std::vector<std::string> Modes; + XRayInstrSet InstrumentationBundle; bool XRayInstrument = false; int InstructionThreshold = 200; bool XRayAlwaysEmitCustomEvents = false; + bool XRayAlwaysEmitTypedEvents = false; + bool XRayRT = true; public: /// Parses the XRay arguments from an argument list. XRayArgs(const ToolChain &TC, const llvm::opt::ArgList &Args); void addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs, types::ID InputType) const; + + bool needsXRayRt() const { return XRayInstrument && XRayRT; } + llvm::ArrayRef<std::string> modeList() const { return Modes; } + XRayInstrSet instrumentationBundle() const { return InstrumentationBundle; } }; } // namespace driver diff --git a/include/clang/Edit/Commit.h b/include/clang/Edit/Commit.h index ac4bb471fe1c9..a574b8ef4cd24 100644 --- a/include/clang/Edit/Commit.h +++ b/include/clang/Edit/Commit.h @@ -1,4 +1,4 @@ -//===----- Commit.h - A unit of edits ---------------------------*- C++ -*-===// +//===- Commit.h - A unit of edits -------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,17 +10,22 @@ #ifndef LLVM_CLANG_EDIT_COMMIT_H #define LLVM_CLANG_EDIT_COMMIT_H +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Edit/FileOffset.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" namespace clang { - class LangOptions; - class PPConditionalDirectiveRecord; + +class LangOptions; +class PPConditionalDirectiveRecord; +class SourceManager; namespace edit { - class EditedSource; + +class EditedSource; class Commit { public: @@ -48,9 +53,9 @@ private: const SourceManager &SourceMgr; const LangOptions &LangOpts; const PPConditionalDirectiveRecord *PPRec; - EditedSource *Editor; + EditedSource *Editor = nullptr; - bool IsCommitable; + bool IsCommitable = true; SmallVector<Edit, 8> CachedEdits; llvm::BumpPtrAllocator StrAlloc; @@ -59,21 +64,23 @@ public: explicit Commit(EditedSource &Editor); Commit(const SourceManager &SM, const LangOptions &LangOpts, const PPConditionalDirectiveRecord *PPRec = nullptr) - : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), Editor(nullptr), - IsCommitable(true) { } + : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec) {} bool isCommitable() const { return IsCommitable; } bool insert(SourceLocation loc, StringRef text, bool afterToken = false, bool beforePreviousInsertions = false); + bool insertAfterToken(SourceLocation loc, StringRef text, bool beforePreviousInsertions = false) { return insert(loc, text, /*afterToken=*/true, beforePreviousInsertions); } + bool insertBefore(SourceLocation loc, StringRef text) { return insert(loc, text, /*afterToken=*/false, /*beforePreviousInsertions=*/true); } + bool insertFromRange(SourceLocation loc, CharSourceRange range, bool afterToken = false, bool beforePreviousInsertions = false); @@ -92,21 +99,26 @@ public: return insertFromRange(loc, CharSourceRange::getTokenRange(TokenRange), afterToken, beforePreviousInsertions); } + bool insertWrap(StringRef before, SourceRange TokenRange, StringRef after) { return insertWrap(before, CharSourceRange::getTokenRange(TokenRange), after); } + bool remove(SourceRange TokenRange) { return remove(CharSourceRange::getTokenRange(TokenRange)); } + bool replace(SourceRange TokenRange, StringRef text) { return replace(CharSourceRange::getTokenRange(TokenRange), text); } + bool replaceWithInner(SourceRange TokenRange, SourceRange TokenInnerRange) { return replaceWithInner(CharSourceRange::getTokenRange(TokenRange), CharSourceRange::getTokenRange(TokenInnerRange)); } - typedef SmallVectorImpl<Edit>::const_iterator edit_iterator; + using edit_iterator = SmallVectorImpl<Edit>::const_iterator; + edit_iterator edit_begin() const { return CachedEdits.begin(); } edit_iterator edit_end() const { return CachedEdits.end(); } @@ -136,8 +148,8 @@ private: SourceLocation *MacroEnd = nullptr) const; }; -} +} // namespace edit -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_EDIT_COMMIT_H diff --git a/include/clang/Edit/EditedSource.h b/include/clang/Edit/EditedSource.h index d95a0c2be805d..3d33688f5f737 100644 --- a/include/clang/Edit/EditedSource.h +++ b/include/clang/Edit/EditedSource.h @@ -1,4 +1,4 @@ -//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===// +//===- EditedSource.h - Collection of source edits --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,21 +11,27 @@ #define LLVM_CLANG_EDIT_EDITEDSOURCE_H #include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Edit/FileOffset.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" -#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" #include <map> #include <tuple> +#include <utility> namespace clang { - class LangOptions; - class PPConditionalDirectiveRecord; + +class LangOptions; +class PPConditionalDirectiveRecord; +class SourceManager; namespace edit { - class Commit; - class EditsReceiver; + +class Commit; +class EditsReceiver; class EditedSource { const SourceManager &SourceMgr; @@ -34,17 +40,19 @@ class EditedSource { struct FileEdit { StringRef Text; - unsigned RemoveLen; + unsigned RemoveLen = 0; - FileEdit() : RemoveLen(0) {} + FileEdit() = default; }; - typedef std::map<FileOffset, FileEdit> FileEditsTy; + using FileEditsTy = std::map<FileOffset, FileEdit>; + FileEditsTy FileEdits; struct MacroArgUse { IdentifierInfo *Identifier; SourceLocation ImmediateExpansionLoc; + // Location of argument use inside the top-level macro SourceLocation UseLoc; @@ -65,11 +73,11 @@ class EditedSource { public: EditedSource(const SourceManager &SM, const LangOptions &LangOpts, const PPConditionalDirectiveRecord *PPRec = nullptr) - : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts), - StrAlloc() { } + : SourceMgr(SM), LangOpts(LangOpts), PPRec(PPRec), IdentTable(LangOpts) {} const SourceManager &getSourceManager() const { return SourceMgr; } const LangOptions &getLangOpts() const { return LangOpts; } + const PPConditionalDirectiveRecord *getPPCondDirectiveRecord() const { return PPRec; } @@ -103,8 +111,8 @@ private: void finishedCommit(); }; -} +} // namespace edit -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_EDIT_EDITEDSOURCE_H diff --git a/include/clang/Edit/EditsReceiver.h b/include/clang/Edit/EditsReceiver.h index 600ac28ea920e..1bebbeb873a71 100644 --- a/include/clang/Edit/EditsReceiver.h +++ b/include/clang/Edit/EditsReceiver.h @@ -1,4 +1,4 @@ -//===----- EditedSource.h - Collection of source edits ----------*- C++ -*-===// +//===- EditedSource.h - Collection of source edits --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,25 +11,24 @@ #define LLVM_CLANG_EDIT_EDITSRECEIVER_H #include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/StringRef.h" namespace clang { - class SourceLocation; - class CharSourceRange; - namespace edit { class EditsReceiver { public: - virtual ~EditsReceiver() { } + virtual ~EditsReceiver() = default; virtual void insert(SourceLocation loc, StringRef text) = 0; virtual void replace(CharSourceRange range, StringRef text) = 0; - /// \brief By default it calls replace with an empty string. + + /// By default it calls replace with an empty string. virtual void remove(CharSourceRange range); }; -} - -} // end namespace clang +} // namespace edit +} // namespace clang -#endif +#endif // LLVM_CLANG_EDIT_EDITSRECEIVER_H diff --git a/include/clang/Edit/FileOffset.h b/include/clang/Edit/FileOffset.h index 0c1e72b84e51b..02c1b96b3331b 100644 --- a/include/clang/Edit/FileOffset.h +++ b/include/clang/Edit/FileOffset.h @@ -1,4 +1,4 @@ -//===----- FileOffset.h - Offset in a file ----------------------*- C++ -*-===// +//===- FileOffset.h - Offset in a file --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,17 +11,18 @@ #define LLVM_CLANG_EDIT_FILEOFFSET_H #include "clang/Basic/SourceLocation.h" +#include <tuple> namespace clang { - namespace edit { class FileOffset { FileID FID; - unsigned Offs; + unsigned Offs = 0; + public: - FileOffset() : Offs(0) { } - FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) { } + FileOffset() = default; + FileOffset(FileID fid, unsigned offs) : FID(fid), Offs(offs) {} bool isInvalid() const { return FID.isInvalid(); } @@ -37,25 +38,29 @@ public: friend bool operator==(FileOffset LHS, FileOffset RHS) { return LHS.FID == RHS.FID && LHS.Offs == RHS.Offs; } + friend bool operator!=(FileOffset LHS, FileOffset RHS) { return !(LHS == RHS); } + friend bool operator<(FileOffset LHS, FileOffset RHS) { return std::tie(LHS.FID, LHS.Offs) < std::tie(RHS.FID, RHS.Offs); } + friend bool operator>(FileOffset LHS, FileOffset RHS) { return RHS < LHS; } + friend bool operator>=(FileOffset LHS, FileOffset RHS) { return !(LHS < RHS); } + friend bool operator<=(FileOffset LHS, FileOffset RHS) { return !(RHS < LHS); } }; -} - -} // end namespace clang +} // namespace edit +} // namespace clang -#endif +#endif // LLVM_CLANG_EDIT_FILEOFFSET_H diff --git a/include/clang/Format/Format.h b/include/clang/Format/Format.h index d27d934f76798..85dda948c11f5 100644 --- a/include/clang/Format/Format.h +++ b/include/clang/Format/Format.h @@ -17,7 +17,9 @@ #include "clang/Basic/LangOptions.h" #include "clang/Tooling/Core/Replacement.h" +#include "clang/Tooling/Inclusions/IncludeStyle.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/Regex.h" #include <system_error> namespace clang { @@ -41,27 +43,27 @@ public: const std::error_category &getParseCategory(); std::error_code make_error_code(ParseError e); -/// \brief The ``FormatStyle`` is used to configure the formatting to follow +/// The ``FormatStyle`` is used to configure the formatting to follow /// specific guidelines. struct FormatStyle { - /// \brief The extra indent or outdent of access modifiers, e.g. ``public:``. + /// The extra indent or outdent of access modifiers, e.g. ``public:``. int AccessModifierOffset; - /// \brief Different styles for aligning after open brackets. + /// Different styles for aligning after open brackets. enum BracketAlignmentStyle { - /// \brief Align parameters on the open bracket, e.g.: + /// Align parameters on the open bracket, e.g.: /// \code /// someLongFunction(argument1, /// argument2); /// \endcode BAS_Align, - /// \brief Don't align, instead use ``ContinuationIndentWidth``, e.g.: + /// Don't align, instead use ``ContinuationIndentWidth``, e.g.: /// \code /// someLongFunction(argument1, /// argument2); /// \endcode BAS_DontAlign, - /// \brief Always break after an open bracket, if the parameters don't fit + /// Always break after an open bracket, if the parameters don't fit /// on a single line, e.g.: /// \code /// someLongFunction( @@ -70,13 +72,13 @@ struct FormatStyle { BAS_AlwaysBreak, }; - /// \brief If ``true``, horizontally aligns arguments after an open bracket. + /// If ``true``, horizontally aligns arguments after an open bracket. /// /// This applies to round brackets (parentheses), angle brackets and square /// brackets. BracketAlignmentStyle AlignAfterOpenBracket; - /// \brief If ``true``, aligns consecutive assignments. + /// If ``true``, aligns consecutive assignments. /// /// This will align the assignment operators of consecutive lines. This /// will result in formattings like @@ -87,7 +89,7 @@ struct FormatStyle { /// \endcode bool AlignConsecutiveAssignments; - /// \brief If ``true``, aligns consecutive declarations. + /// If ``true``, aligns consecutive declarations. /// /// This will align the declaration names of consecutive lines. This /// will result in formattings like @@ -98,9 +100,9 @@ struct FormatStyle { /// \endcode bool AlignConsecutiveDeclarations; - /// \brief Different styles for aligning escaped newlines. + /// Different styles for aligning escaped newlines. enum EscapedNewlineAlignmentStyle { - /// \brief Don't align escaped newlines. + /// Don't align escaped newlines. /// \code /// #define A \ /// int aaaa; \ @@ -108,7 +110,7 @@ struct FormatStyle { /// int dddddddddd; /// \endcode ENAS_DontAlign, - /// \brief Align escaped newlines as far left as possible. + /// Align escaped newlines as far left as possible. /// \code /// true: /// #define A \ @@ -119,7 +121,7 @@ struct FormatStyle { /// false: /// \endcode ENAS_Left, - /// \brief Align escaped newlines in the right-most column. + /// Align escaped newlines in the right-most column. /// \code /// #define A \ /// int aaaa; \ @@ -129,10 +131,10 @@ struct FormatStyle { ENAS_Right, }; - /// \brief Options for aligning backslashes in escaped newlines. + /// Options for aligning backslashes in escaped newlines. EscapedNewlineAlignmentStyle AlignEscapedNewlines; - /// \brief If ``true``, horizontally align operands of binary and ternary + /// If ``true``, horizontally align operands of binary and ternary /// expressions. /// /// Specifically, this aligns operands of a single expression that needs to be @@ -143,7 +145,7 @@ struct FormatStyle { /// \endcode bool AlignOperands; - /// \brief If ``true``, aligns trailing comments. + /// If ``true``, aligns trailing comments. /// \code /// true: false: /// int a; // My comment a vs. int a; // My comment a @@ -151,7 +153,7 @@ struct FormatStyle { /// \endcode bool AlignTrailingComments; - /// \brief If the function declaration doesn't fit on a line, + /// If the function declaration doesn't fit on a line, /// allow putting all parameters of a function declaration onto /// the next line even if ``BinPackParameters`` is ``false``. /// \code @@ -168,12 +170,12 @@ struct FormatStyle { /// \endcode bool AllowAllParametersOfDeclarationOnNextLine; - /// \brief Allows contracting simple braced statements to a single line. + /// Allows contracting simple braced statements to a single line. /// /// E.g., this allows ``if (a) { return; }`` to be put on a single line. bool AllowShortBlocksOnASingleLine; - /// \brief If ``true``, short case labels will be contracted to a single line. + /// If ``true``, short case labels will be contracted to a single line. /// \code /// true: false: /// switch (a) { vs. switch (a) { @@ -186,12 +188,12 @@ struct FormatStyle { /// \endcode bool AllowShortCaseLabelsOnASingleLine; - /// \brief Different styles for merging short functions containing at most one + /// Different styles for merging short functions containing at most one /// statement. enum ShortFunctionStyle { - /// \brief Never merge functions into a single line. + /// Never merge functions into a single line. SFS_None, - /// \brief Only merge functions defined inside a class. Same as "inline", + /// Only merge functions defined inside a class. Same as "inline", /// except it does not implies "empty": i.e. top level empty functions /// are not merged either. /// \code @@ -205,7 +207,7 @@ struct FormatStyle { /// } /// \endcode SFS_InlineOnly, - /// \brief Only merge empty functions. + /// Only merge empty functions. /// \code /// void f() {} /// void f2() { @@ -213,7 +215,7 @@ struct FormatStyle { /// } /// \endcode SFS_Empty, - /// \brief Only merge functions defined inside a class. Implies "empty". + /// Only merge functions defined inside a class. Implies "empty". /// \code /// class Foo { /// void f() { foo(); } @@ -224,7 +226,7 @@ struct FormatStyle { /// void f() {} /// \endcode SFS_Inline, - /// \brief Merge all functions fitting on a single line. + /// Merge all functions fitting on a single line. /// \code /// class Foo { /// void f() { foo(); } @@ -234,18 +236,18 @@ struct FormatStyle { SFS_All, }; - /// \brief Dependent on the value, ``int f() { return 0; }`` can be put on a + /// Dependent on the value, ``int f() { return 0; }`` can be put on a /// single line. ShortFunctionStyle AllowShortFunctionsOnASingleLine; - /// \brief If ``true``, ``if (a) return;`` can be put on a single line. + /// If ``true``, ``if (a) return;`` can be put on a single line. bool AllowShortIfStatementsOnASingleLine; - /// \brief If ``true``, ``while (true) continue;`` can be put on a single + /// If ``true``, ``while (true) continue;`` can be put on a single /// line. bool AllowShortLoopsOnASingleLine; - /// \brief Different ways to break after the function definition return type. + /// Different ways to break after the function definition return type. /// This option is **deprecated** and is retained for backwards compatibility. enum DefinitionReturnTypeBreakingStyle { /// Break after return type automatically. @@ -257,7 +259,7 @@ struct FormatStyle { DRTBS_TopLevel, }; - /// \brief Different ways to break after the function definition or + /// Different ways to break after the function definition or /// declaration return type. enum ReturnTypeBreakingStyle { /// Break after return type automatically. @@ -328,14 +330,14 @@ struct FormatStyle { RTBS_TopLevelDefinitions, }; - /// \brief The function definition return type breaking style to use. This + /// The function definition return type breaking style to use. This /// option is **deprecated** and is retained for backwards compatibility. DefinitionReturnTypeBreakingStyle AlwaysBreakAfterDefinitionReturnType; - /// \brief The function declaration return type breaking style to use. + /// The function declaration return type breaking style to use. ReturnTypeBreakingStyle AlwaysBreakAfterReturnType; - /// \brief If ``true``, always break before multiline string literals. + /// If ``true``, always break before multiline string literals. /// /// This flag is mean to make cases where there are multiple multiline strings /// in a file look more consistent. Thus, it will only take effect if wrapping @@ -349,16 +351,46 @@ struct FormatStyle { /// \endcode bool AlwaysBreakBeforeMultilineStrings; - /// \brief If ``true``, always break after the ``template<...>`` of a template - /// declaration. - /// \code - /// true: false: - /// template <typename T> vs. template <typename T> class C {}; - /// class C {}; - /// \endcode - bool AlwaysBreakTemplateDeclarations; + /// Different ways to break after the template declaration. + enum BreakTemplateDeclarationsStyle { + /// Do not force break before declaration. + /// ``PenaltyBreakTemplateDeclaration`` is taken into account. + /// \code + /// template <typename T> T foo() { + /// } + /// template <typename T> T foo(int aaaaaaaaaaaaaaaaaaaaa, + /// int bbbbbbbbbbbbbbbbbbbbb) { + /// } + /// \endcode + BTDS_No, + /// Force break after template declaration only when the following + /// declaration spans multiple lines. + /// \code + /// template <typename T> T foo() { + /// } + /// template <typename T> + /// T foo(int aaaaaaaaaaaaaaaaaaaaa, + /// int bbbbbbbbbbbbbbbbbbbbb) { + /// } + /// \endcode + BTDS_MultiLine, + /// Always break after template declaration. + /// \code + /// template <typename T> + /// T foo() { + /// } + /// template <typename T> + /// T foo(int aaaaaaaaaaaaaaaaaaaaa, + /// int bbbbbbbbbbbbbbbbbbbbb) { + /// } + /// \endcode + BTDS_Yes + }; + + /// The template declaration breaking style to use. + BreakTemplateDeclarationsStyle AlwaysBreakTemplateDeclarations; - /// \brief If ``false``, a function call's arguments will either be all on the + /// If ``false``, a function call's arguments will either be all on the /// same line or will have one line each. /// \code /// true: @@ -376,7 +408,7 @@ struct FormatStyle { /// \endcode bool BinPackArguments; - /// \brief If ``false``, a function declaration's or function definition's + /// If ``false``, a function declaration's or function definition's /// parameters will either all be on the same line or will have one line each. /// \code /// true: @@ -390,7 +422,18 @@ struct FormatStyle { /// \endcode bool BinPackParameters; - /// \brief The style of breaking before or after binary operators. + /// The style of wrapping parameters on the same line (bin-packed) or + /// on one line each. + enum BinPackStyle { + /// Automatically determine parameter bin-packing behavior. + BPS_Auto, + /// Always bin-pack parameters. + BPS_Always, + /// Never bin-pack parameters. + BPS_Never, + }; + + /// The style of breaking before or after binary operators. enum BinaryOperatorStyle { /// Break after operators. /// \code @@ -430,10 +473,10 @@ struct FormatStyle { BOS_All, }; - /// \brief The way to wrap binary operators. + /// The way to wrap binary operators. BinaryOperatorStyle BreakBeforeBinaryOperators; - /// \brief Different ways to attach braces to their surrounding context. + /// Different ways to attach braces to their surrounding context. enum BraceBreakingStyle { /// Always attach braces to surrounding context. /// \code @@ -568,10 +611,10 @@ struct FormatStyle { BS_Custom }; - /// \brief The brace breaking style to use. + /// The brace breaking style to use. BraceBreakingStyle BreakBeforeBraces; - /// \brief Precise control over the wrapping of braces. + /// Precise control over the wrapping of braces. /// \code /// # Should be declared this way: /// BreakBeforeBraces: Custom @@ -579,7 +622,7 @@ struct FormatStyle { /// AfterClass: true /// \endcode struct BraceWrappingFlags { - /// \brief Wrap class definitions. + /// Wrap class definitions. /// \code /// true: /// class foo {}; @@ -589,7 +632,7 @@ struct FormatStyle { /// {}; /// \endcode bool AfterClass; - /// \brief Wrap control statements (``if``/``for``/``while``/``switch``/..). + /// Wrap control statements (``if``/``for``/``while``/``switch``/..). /// \code /// true: /// if (foo()) @@ -607,7 +650,7 @@ struct FormatStyle { /// } /// \endcode bool AfterControlStatement; - /// \brief Wrap enum definitions. + /// Wrap enum definitions. /// \code /// true: /// enum X : int @@ -619,7 +662,7 @@ struct FormatStyle { /// enum X : int { B }; /// \endcode bool AfterEnum; - /// \brief Wrap function definitions. + /// Wrap function definitions. /// \code /// true: /// void foo() @@ -635,7 +678,7 @@ struct FormatStyle { /// } /// \endcode bool AfterFunction; - /// \brief Wrap namespace definitions. + /// Wrap namespace definitions. /// \code /// true: /// namespace @@ -651,9 +694,11 @@ struct FormatStyle { /// } /// \endcode bool AfterNamespace; - /// \brief Wrap ObjC definitions (``@autoreleasepool``, interfaces, ..). + /// Wrap ObjC definitions (interfaces, implementations...). + /// \note @autoreleasepool and @synchronized blocks are wrapped + /// according to `AfterControlStatement` flag. bool AfterObjCDeclaration; - /// \brief Wrap struct definitions. + /// Wrap struct definitions. /// \code /// true: /// struct foo @@ -667,7 +712,7 @@ struct FormatStyle { /// }; /// \endcode bool AfterStruct; - /// \brief Wrap union definitions. + /// Wrap union definitions. /// \code /// true: /// union foo @@ -681,7 +726,7 @@ struct FormatStyle { /// } /// \endcode bool AfterUnion; - /// \brief Wrap extern blocks. + /// Wrap extern blocks. /// \code /// true: /// extern "C" @@ -695,7 +740,7 @@ struct FormatStyle { /// } /// \endcode bool AfterExternBlock; - /// \brief Wrap before ``catch``. + /// Wrap before ``catch``. /// \code /// true: /// try { @@ -711,7 +756,7 @@ struct FormatStyle { /// } /// \endcode bool BeforeCatch; - /// \brief Wrap before ``else``. + /// Wrap before ``else``. /// \code /// true: /// if (foo()) { @@ -725,9 +770,9 @@ struct FormatStyle { /// } /// \endcode bool BeforeElse; - /// \brief Indent the wrapped braces themselves. + /// Indent the wrapped braces themselves. bool IndentBraces; - /// \brief If ``false``, empty function body can be put on a single line. + /// If ``false``, empty function body can be put on a single line. /// This option is used only if the opening brace of the function has /// already been wrapped, i.e. the `AfterFunction` brace wrapping mode is /// set, and the function could/should not be put on a single line (as per @@ -739,7 +784,7 @@ struct FormatStyle { /// \endcode /// bool SplitEmptyFunction; - /// \brief If ``false``, empty record (e.g. class, struct or union) body + /// If ``false``, empty record (e.g. class, struct or union) body /// can be put on a single line. This option is used only if the opening /// brace of the record has already been wrapped, i.e. the `AfterClass` /// (for classes) brace wrapping mode is set. @@ -750,7 +795,7 @@ struct FormatStyle { /// \endcode /// bool SplitEmptyRecord; - /// \brief If ``false``, empty namespace body can be put on a single line. + /// If ``false``, empty namespace body can be put on a single line. /// This option is used only if the opening brace of the namespace has /// already been wrapped, i.e. the `AfterNamespace` brace wrapping mode is /// set. @@ -763,7 +808,7 @@ struct FormatStyle { bool SplitEmptyNamespace; }; - /// \brief Control of individual brace wrapping cases. + /// Control of individual brace wrapping cases. /// /// If ``BreakBeforeBraces`` is set to ``BS_Custom``, use this to specify how /// each individual brace case should be handled. Otherwise, this is ignored. @@ -777,7 +822,7 @@ struct FormatStyle { /// \endcode BraceWrappingFlags BraceWrapping; - /// \brief If ``true``, ternary operators will be placed after line breaks. + /// If ``true``, ternary operators will be placed after line breaks. /// \code /// true: /// veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongDescription @@ -791,36 +836,36 @@ struct FormatStyle { /// \endcode bool BreakBeforeTernaryOperators; - /// \brief Different ways to break initializers. + /// Different ways to break initializers. enum BreakConstructorInitializersStyle { /// Break constructor initializers before the colon and after the commas. /// \code - /// Constructor() - /// : initializer1(), - /// initializer2() + /// Constructor() + /// : initializer1(), + /// initializer2() /// \endcode BCIS_BeforeColon, /// Break constructor initializers before the colon and commas, and align /// the commas with the colon. /// \code - /// Constructor() - /// : initializer1() - /// , initializer2() + /// Constructor() + /// : initializer1() + /// , initializer2() /// \endcode BCIS_BeforeComma, /// Break constructor initializers after the colon and commas. /// \code - /// Constructor() : - /// initializer1(), - /// initializer2() + /// Constructor() : + /// initializer1(), + /// initializer2() /// \endcode BCIS_AfterColon }; - /// \brief The constructor initializers style to use. + /// The constructor initializers style to use. BreakConstructorInitializersStyle BreakConstructorInitializers; - /// \brief Break after each annotation on a field in Java files. + /// Break after each annotation on a field in Java files. /// \code{.java} /// true: false: /// @Partial vs. @Partial @Mock DataLoad loader; @@ -829,17 +874,17 @@ struct FormatStyle { /// \endcode bool BreakAfterJavaFieldAnnotations; - /// \brief Allow breaking string literals when formatting. + /// Allow breaking string literals when formatting. bool BreakStringLiterals; - /// \brief The column limit. + /// The column limit. /// /// A column limit of ``0`` means that there is no column limit. In this case, /// clang-format will respect the input's line breaking decisions within /// statements unless they contradict other rules. unsigned ColumnLimit; - /// \brief A regular expression that describes comments with special meaning, + /// A regular expression that describes comments with special meaning, /// which should not be split into lines or otherwise changed. /// \code /// // CommentPragmas: '^ FOOBAR pragma:' @@ -848,18 +893,39 @@ struct FormatStyle { /// \endcode std::string CommentPragmas; - /// \brief If ``true``, in the class inheritance expression clang-format will - /// break before ``:`` and ``,`` if there is multiple inheritance. - /// \code - /// true: false: - /// class MyClass vs. class MyClass : public X, public Y { - /// : public X }; - /// , public Y { - /// }; - /// \endcode - bool BreakBeforeInheritanceComma; + /// Different ways to break inheritance list. + enum BreakInheritanceListStyle { + /// Break inheritance list before the colon and after the commas. + /// \code + /// class Foo + /// : Base1, + /// Base2 + /// {}; + /// \endcode + BILS_BeforeColon, + /// Break inheritance list before the colon and commas, and align + /// the commas with the colon. + /// \code + /// class Foo + /// : Base1 + /// , Base2 + /// {}; + /// \endcode + BILS_BeforeComma, + /// Break inheritance list after the colon and commas. + /// \code + /// class Foo : + /// Base1, + /// Base2 + /// {}; + /// \endcode + BILS_AfterColon + }; + + /// The inheritance list style to use. + BreakInheritanceListStyle BreakInheritanceList; - /// \brief If ``true``, consecutive namespace declarations will be on the same + /// If ``true``, consecutive namespace declarations will be on the same /// line. If ``false``, each namespace is declared on a new line. /// \code /// true: @@ -882,7 +948,7 @@ struct FormatStyle { /// \endcode bool CompactNamespaces; - /// \brief If the constructor initializers don't fit on a line, put each + /// If the constructor initializers don't fit on a line, put each /// initializer on its own line. /// \code /// true: @@ -900,11 +966,11 @@ struct FormatStyle { /// \endcode bool ConstructorInitializerAllOnOneLineOrOnePerLine; - /// \brief The number of characters to use for indentation of constructor - /// initializer lists. + /// The number of characters to use for indentation of constructor + /// initializer lists as well as inheritance lists. unsigned ConstructorInitializerIndentWidth; - /// \brief Indent width for line continuations. + /// Indent width for line continuations. /// \code /// ContinuationIndentWidth: 2 /// @@ -914,7 +980,7 @@ struct FormatStyle { /// \endcode unsigned ContinuationIndentWidth; - /// \brief If ``true``, format braced lists as best suited for C++11 braced + /// If ``true``, format braced lists as best suited for C++11 braced /// lists. /// /// Important differences: @@ -936,17 +1002,17 @@ struct FormatStyle { /// \endcode bool Cpp11BracedListStyle; - /// \brief If ``true``, analyze the formatted file for the most common + /// If ``true``, analyze the formatted file for the most common /// alignment of ``&`` and ``*``. /// Pointer and reference alignment styles are going to be updated according /// to the preferences found in the file. /// ``PointerAlignment`` is then used only as fallback. bool DerivePointerAlignment; - /// \brief Disables formatting completely. + /// Disables formatting completely. bool DisableFormat; - /// \brief If ``true``, clang-format detects whether function calls and + /// If ``true``, clang-format detects whether function calls and /// definitions are formatted with one parameter per line. /// /// Each call can be bin-packed, one-per-line or inconclusive. If it is @@ -958,7 +1024,7 @@ struct FormatStyle { /// not use this in config files, etc. Use at your own risk. bool ExperimentalAutoDetectBinPacking; - /// \brief If ``true``, clang-format adds missing namespace end comments and + /// If ``true``, clang-format adds missing namespace end comments and /// fixes invalid existing ones. /// \code /// true: false: @@ -968,7 +1034,7 @@ struct FormatStyle { /// \endcode bool FixNamespaceComments; - /// \brief A vector of macros that should be interpreted as foreach loops + /// A vector of macros that should be interpreted as foreach loops /// instead of as function calls. /// /// These are expected to be macros of the form: @@ -985,93 +1051,9 @@ struct FormatStyle { /// For example: BOOST_FOREACH. std::vector<std::string> ForEachMacros; - /// \brief Styles for sorting multiple ``#include`` blocks. - enum IncludeBlocksStyle { - /// \brief Sort each ``#include`` block separately. - /// \code - /// #include "b.h" into #include "b.h" - /// - /// #include <lib/main.h> #include "a.h" - /// #include "a.h" #include <lib/main.h> - /// \endcode - IBS_Preserve, - /// \brief Merge multiple ``#include`` blocks together and sort as one. - /// \code - /// #include "b.h" into #include "a.h" - /// #include "b.h" - /// #include <lib/main.h> #include <lib/main.h> - /// #include "a.h" - /// \endcode - IBS_Merge, - /// \brief Merge multiple ``#include`` blocks together and sort as one. - /// Then split into groups based on category priority. See - /// ``IncludeCategories``. - /// \code - /// #include "b.h" into #include "a.h" - /// #include "b.h" - /// #include <lib/main.h> - /// #include "a.h" #include <lib/main.h> - /// \endcode - IBS_Regroup, - }; - - /// \brief Dependent on the value, multiple ``#include`` blocks can be sorted - /// as one and divided based on category. - IncludeBlocksStyle IncludeBlocks; - - /// \brief See documentation of ``IncludeCategories``. - struct IncludeCategory { - /// \brief The regular expression that this category matches. - std::string Regex; - /// \brief The priority to assign to this category. - int Priority; - bool operator==(const IncludeCategory &Other) const { - return Regex == Other.Regex && Priority == Other.Priority; - } - }; + tooling::IncludeStyle IncludeStyle; - /// \brief Regular expressions denoting the different ``#include`` categories - /// used for ordering ``#includes``. - /// - /// These regular expressions are matched against the filename of an include - /// (including the <> or "") in order. The value belonging to the first - /// matching regular expression is assigned and ``#includes`` are sorted first - /// according to increasing category number and then alphabetically within - /// each category. - /// - /// If none of the regular expressions match, INT_MAX is assigned as - /// category. The main header for a source file automatically gets category 0. - /// so that it is generally kept at the beginning of the ``#includes`` - /// (http://llvm.org/docs/CodingStandards.html#include-style). However, you - /// can also assign negative priorities if you have certain headers that - /// always need to be first. - /// - /// To configure this in the .clang-format file, use: - /// \code{.yaml} - /// IncludeCategories: - /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/' - /// Priority: 2 - /// - Regex: '^(<|"(gtest|gmock|isl|json)/)' - /// Priority: 3 - /// - Regex: '.*' - /// Priority: 1 - /// \endcode - std::vector<IncludeCategory> IncludeCategories; - - /// \brief Specify a regular expression of suffixes that are allowed in the - /// file-to-main-include mapping. - /// - /// When guessing whether a #include is the "main" include (to assign - /// category 0, see above), use this regex of allowed suffixes to the header - /// stem. A partial match is done, so that: - /// - "" means "arbitrary suffix" - /// - "$" means "no suffix" - /// - /// For example, if configured to "(_test)?$", then a header a.h would be seen - /// as the "main" include in both a.cc and a_test.cc. - std::string IncludeIsMainRegex; - - /// \brief Indent case labels one level from the switch statement. + /// Indent case labels one level from the switch statement. /// /// When ``false``, use the same indentation level as for the switch statement. /// Switch statement body is always indented one level more than case labels. @@ -1087,7 +1069,7 @@ struct FormatStyle { /// \endcode bool IndentCaseLabels; - /// \brief Options for indenting preprocessor directives. + /// Options for indenting preprocessor directives. enum PPDirectiveIndentStyle { /// Does not indent any directives. /// \code @@ -1109,10 +1091,10 @@ struct FormatStyle { PPDIS_AfterHash }; - /// \brief The preprocessor directive indenting style to use. + /// The preprocessor directive indenting style to use. PPDirectiveIndentStyle IndentPPDirectives; - /// \brief The number of columns to use for indentation. + /// The number of columns to use for indentation. /// \code /// IndentWidth: 3 /// @@ -1125,7 +1107,7 @@ struct FormatStyle { /// \endcode unsigned IndentWidth; - /// \brief Indent if a function definition or declaration is wrapped after the + /// Indent if a function definition or declaration is wrapped after the /// type. /// \code /// true: @@ -1138,7 +1120,7 @@ struct FormatStyle { /// \endcode bool IndentWrappedFunctionNames; - /// \brief Quotation styles for JavaScript strings. Does not affect template + /// Quotation styles for JavaScript strings. Does not affect template /// strings. enum JavaScriptQuoteStyle { /// Leave string quotes as they are. @@ -1161,10 +1143,10 @@ struct FormatStyle { JSQS_Double }; - /// \brief The JavaScriptQuoteStyle to use for JavaScript strings. + /// The JavaScriptQuoteStyle to use for JavaScript strings. JavaScriptQuoteStyle JavaScriptQuotes; - /// \brief Whether to wrap JavaScript import/export statements. + /// Whether to wrap JavaScript import/export statements. /// \code{.js} /// true: /// import { @@ -1178,7 +1160,7 @@ struct FormatStyle { /// \endcode bool JavaScriptWrapImports; - /// \brief If true, the empty line at the start of blocks is kept. + /// If true, the empty line at the start of blocks is kept. /// \code /// true: false: /// if (foo) { vs. if (foo) { @@ -1188,7 +1170,7 @@ struct FormatStyle { /// \endcode bool KeepEmptyLinesAtTheStartOfBlocks; - /// \brief Supported languages. + /// Supported languages. /// /// When stored in a configuration file, specifies the language, that the /// configuration targets. When passed to the ``reformat()`` function, enables @@ -1215,10 +1197,10 @@ struct FormatStyle { }; bool isCpp() const { return Language == LK_Cpp || Language == LK_ObjC; } - /// \brief Language, this format style is targeted at. + /// Language, this format style is targeted at. LanguageKind Language; - /// \brief A regular expression matching macros that start a block. + /// A regular expression matching macros that start a block. /// \code /// # With: /// MacroBlockBegin: "^NS_MAP_BEGIN|\ @@ -1246,10 +1228,10 @@ struct FormatStyle { /// \endcode std::string MacroBlockBegin; - /// \brief A regular expression matching macros that end a block. + /// A regular expression matching macros that end a block. std::string MacroBlockEnd; - /// \brief The maximum number of consecutive empty lines to keep. + /// The maximum number of consecutive empty lines to keep. /// \code /// MaxEmptyLinesToKeep: 1 vs. MaxEmptyLinesToKeep: 0 /// int f() { int f() { @@ -1262,7 +1244,7 @@ struct FormatStyle { /// \endcode unsigned MaxEmptyLinesToKeep; - /// \brief Different ways to indent namespace contents. + /// Different ways to indent namespace contents. enum NamespaceIndentationKind { /// Don't indent in namespaces. /// \code @@ -1296,10 +1278,42 @@ struct FormatStyle { NI_All }; - /// \brief The indentation used for namespaces. + /// The indentation used for namespaces. NamespaceIndentationKind NamespaceIndentation; - /// \brief The number of characters to use for indentation of ObjC blocks. + /// Controls bin-packing Objective-C protocol conformance list + /// items into as few lines as possible when they go over ``ColumnLimit``. + /// + /// If ``Auto`` (the default), delegates to the value in + /// ``BinPackParameters``. If that is ``true``, bin-packs Objective-C + /// protocol conformance list items into as few lines as possible + /// whenever they go over ``ColumnLimit``. + /// + /// If ``Always``, always bin-packs Objective-C protocol conformance + /// list items into as few lines as possible whenever they go over + /// ``ColumnLimit``. + /// + /// If ``Never``, lays out Objective-C protocol conformance list items + /// onto individual lines whenever they go over ``ColumnLimit``. + /// + /// \code{.objc} + /// Always (or Auto, if BinPackParameters=true): + /// @interface ccccccccccccc () < + /// ccccccccccccc, ccccccccccccc, + /// ccccccccccccc, ccccccccccccc> { + /// } + /// + /// Never (or Auto, if BinPackParameters=false): + /// @interface ddddddddddddd () < + /// ddddddddddddd, + /// ddddddddddddd, + /// ddddddddddddd, + /// ddddddddddddd> { + /// } + /// \endcode + BinPackStyle ObjCBinPackProtocolList; + + /// The number of characters to use for indentation of ObjC blocks. /// \code{.objc} /// ObjCBlockIndentWidth: 4 /// @@ -1309,37 +1323,40 @@ struct FormatStyle { /// \endcode unsigned ObjCBlockIndentWidth; - /// \brief Add a space after ``@property`` in Objective-C, i.e. use + /// Add a space after ``@property`` in Objective-C, i.e. use /// ``@property (readonly)`` instead of ``@property(readonly)``. bool ObjCSpaceAfterProperty; - /// \brief Add a space in front of an Objective-C protocol list, i.e. use + /// Add a space in front of an Objective-C protocol list, i.e. use /// ``Foo <Protocol>`` instead of ``Foo<Protocol>``. bool ObjCSpaceBeforeProtocolList; - /// \brief The penalty for breaking around an assignment operator. + /// The penalty for breaking around an assignment operator. unsigned PenaltyBreakAssignment; - /// \brief The penalty for breaking a function call after ``call(``. + /// The penalty for breaking a function call after ``call(``. unsigned PenaltyBreakBeforeFirstCallParameter; - /// \brief The penalty for each line break introduced inside a comment. + /// The penalty for each line break introduced inside a comment. unsigned PenaltyBreakComment; - /// \brief The penalty for breaking before the first ``<<``. + /// The penalty for breaking before the first ``<<``. unsigned PenaltyBreakFirstLessLess; - /// \brief The penalty for each line break introduced inside a string literal. + /// The penalty for each line break introduced inside a string literal. unsigned PenaltyBreakString; - /// \brief The penalty for each character outside of the column limit. + /// The penalty for breaking after template declaration. + unsigned PenaltyBreakTemplateDeclaration; + + /// The penalty for each character outside of the column limit. unsigned PenaltyExcessCharacter; - /// \brief Penalty for putting the return type of a function onto its own + /// Penalty for putting the return type of a function onto its own /// line. unsigned PenaltyReturnTypeOnItsOwnLine; - /// \brief The ``&`` and ``*`` alignment style. + /// The ``&`` and ``*`` alignment style. enum PointerAlignmentStyle { /// Align pointer to the left. /// \code @@ -1358,45 +1375,69 @@ struct FormatStyle { PAS_Middle }; - /// \brief Pointer and reference alignment style. + /// Pointer and reference alignment style. PointerAlignmentStyle PointerAlignment; /// See documentation of ``RawStringFormats``. struct RawStringFormat { - /// \brief The delimiter that this raw string format matches. - std::string Delimiter; - /// \brief The language of this raw string. + /// The language of this raw string. LanguageKind Language; - /// \brief The style name on which this raw string format is based on. + /// A list of raw string delimiters that match this language. + std::vector<std::string> Delimiters; + /// A list of enclosing function names that match this language. + std::vector<std::string> EnclosingFunctions; + /// The canonical delimiter for this language. + std::string CanonicalDelimiter; + /// The style name on which this raw string format is based on. /// If not specified, the raw string format is based on the style that this /// format is based on. std::string BasedOnStyle; bool operator==(const RawStringFormat &Other) const { - return Delimiter == Other.Delimiter && Language == Other.Language && + return Language == Other.Language && Delimiters == Other.Delimiters && + EnclosingFunctions == Other.EnclosingFunctions && + CanonicalDelimiter == Other.CanonicalDelimiter && BasedOnStyle == Other.BasedOnStyle; } }; - /// \brief Raw string delimiters denoting that the raw string contents are - /// code in a particular language and can be reformatted. + /// Defines hints for detecting supported languages code blocks in raw + /// strings. + /// + /// A raw string with a matching delimiter or a matching enclosing function + /// name will be reformatted assuming the specified language based on the + /// style for that language defined in the .clang-format file. If no style has + /// been defined in the .clang-format file for the specific language, a + /// predefined style given by 'BasedOnStyle' is used. If 'BasedOnStyle' is not + /// found, the formatting is based on llvm style. A matching delimiter takes + /// precedence over a matching enclosing function name for determining the + /// language of the raw string contents. /// - /// A raw string with a matching delimiter will be reformatted assuming the - /// specified language based on a predefined style given by 'BasedOnStyle'. - /// If 'BasedOnStyle' is not found, the formatting is based on llvm style. + /// If a canonical delimiter is specified, occurrences of other delimiters for + /// the same language will be updated to the canonical if possible. + /// + /// There should be at most one specification per language and each delimiter + /// and enclosing function should not occur in multiple specifications. /// /// To configure this in the .clang-format file, use: /// \code{.yaml} /// RawStringFormats: - /// - Delimiter: 'pb' - /// Language: TextProto - /// BasedOnStyle: llvm - /// - Delimiter: 'proto' - /// Language: TextProto - /// BasedOnStyle: google + /// - Language: TextProto + /// Delimiters: + /// - 'pb' + /// - 'proto' + /// EnclosingFunctions: + /// - 'PARSE_TEXT_PROTO' + /// BasedOnStyle: google + /// - Language: Cpp + /// Delimiters: + /// - 'cc' + /// - 'cpp' + /// BasedOnStyle: llvm + /// CanonicalDelimiter: 'cc' /// \endcode std::vector<RawStringFormat> RawStringFormats; - /// \brief If ``true``, clang-format will attempt to re-flow comments. + /// If ``true``, clang-format will attempt to re-flow comments. /// \code /// false: /// // veryVeryVeryVeryVeryVeryVeryVeryVeryVeryVeryLongComment with plenty of information @@ -1410,7 +1451,7 @@ struct FormatStyle { /// \endcode bool ReflowComments; - /// \brief If ``true``, clang-format will sort ``#includes``. + /// If ``true``, clang-format will sort ``#includes``. /// \code /// false: true: /// #include "b.h" vs. #include "a.h" @@ -1418,7 +1459,7 @@ struct FormatStyle { /// \endcode bool SortIncludes; - /// \brief If ``true``, clang-format will sort using declarations. + /// If ``true``, clang-format will sort using declarations. /// /// The order of using declarations is defined as follows: /// Split the strings by "::" and discard any initial empty strings. The last @@ -1434,21 +1475,21 @@ struct FormatStyle { /// \endcode bool SortUsingDeclarations; - /// \brief If ``true``, a space is inserted after C style casts. + /// If ``true``, a space is inserted after C style casts. /// \code /// true: false: - /// (int)i; vs. (int) i; + /// (int) i; vs. (int)i; /// \endcode bool SpaceAfterCStyleCast; - /// \brief If \c true, a space will be inserted after the 'template' keyword. + /// If \c true, a space will be inserted after the 'template' keyword. /// \code /// true: false: /// template <int> void foo(); vs. template<int> void foo(); /// \endcode bool SpaceAfterTemplateKeyword; - /// \brief If ``false``, spaces will be removed before assignment operators. + /// If ``false``, spaces will be removed before assignment operators. /// \code /// true: false: /// int a = 5; vs. int a=5; @@ -1456,7 +1497,33 @@ struct FormatStyle { /// \endcode bool SpaceBeforeAssignmentOperators; - /// \brief Different ways to put a space before opening parentheses. + /// If ``true``, a space will be inserted before a C++11 braced list + /// used to initialize an object (after the preceding identifier or type). + /// \code + /// true: false: + /// Foo foo { bar }; vs. Foo foo{ bar }; + /// Foo {}; Foo{}; + /// vector<int> { 1, 2, 3 }; vector<int>{ 1, 2, 3 }; + /// new int[3] { 1, 2, 3 }; new int[3]{ 1, 2, 3 }; + /// \endcode + bool SpaceBeforeCpp11BracedList; + + /// If ``false``, spaces will be removed before constructor initializer + /// colon. + /// \code + /// true: false: + /// Foo::Foo() : a(a) {} Foo::Foo(): a(a) {} + /// \endcode + bool SpaceBeforeCtorInitializerColon; + + /// If ``false``, spaces will be removed before inheritance colon. + /// \code + /// true: false: + /// class Foo : Bar {} vs. class Foo: Bar {} + /// \endcode + bool SpaceBeforeInheritanceColon; + + /// Different ways to put a space before opening parentheses. enum SpaceBeforeParensOptions { /// Never put a space before opening parentheses. /// \code @@ -1491,10 +1558,18 @@ struct FormatStyle { SBPO_Always }; - /// \brief Defines in which cases to put a space before opening parentheses. + /// Defines in which cases to put a space before opening parentheses. SpaceBeforeParensOptions SpaceBeforeParens; - /// \brief If ``true``, spaces may be inserted into ``()``. + /// If ``false``, spaces will be removed before range-based for loop + /// colon. + /// \code + /// true: false: + /// for (auto v : values) {} vs. for(auto v: values) {} + /// \endcode + bool SpaceBeforeRangeBasedForLoopColon; + + /// If ``true``, spaces may be inserted into ``()``. /// \code /// true: false: /// void f( ) { vs. void f() { @@ -1506,7 +1581,7 @@ struct FormatStyle { /// \endcode bool SpaceInEmptyParentheses; - /// \brief The number of spaces before trailing line comments + /// The number of spaces before trailing line comments /// (``//`` - comments). /// /// This does not affect trailing block comments (``/*`` - comments) as @@ -1522,7 +1597,7 @@ struct FormatStyle { /// \endcode unsigned SpacesBeforeTrailingComments; - /// \brief If ``true``, spaces will be inserted after ``<`` and before ``>`` + /// If ``true``, spaces will be inserted after ``<`` and before ``>`` /// in template argument lists. /// \code /// true: false: @@ -1531,7 +1606,7 @@ struct FormatStyle { /// \endcode bool SpacesInAngles; - /// \brief If ``true``, spaces are inserted inside container literals (e.g. + /// If ``true``, spaces are inserted inside container literals (e.g. /// ObjC and Javascript array and dict literals). /// \code{.js} /// true: false: @@ -1540,21 +1615,21 @@ struct FormatStyle { /// \endcode bool SpacesInContainerLiterals; - /// \brief If ``true``, spaces may be inserted into C style casts. + /// If ``true``, spaces may be inserted into C style casts. /// \code /// true: false: /// x = ( int32 )y vs. x = (int32)y /// \endcode bool SpacesInCStyleCastParentheses; - /// \brief If ``true``, spaces will be inserted after ``(`` and before ``)``. + /// If ``true``, spaces will be inserted after ``(`` and before ``)``. /// \code /// true: false: /// t f( Deleted & ) & = delete; vs. t f(Deleted &) & = delete; /// \endcode bool SpacesInParentheses; - /// \brief If ``true``, spaces will be inserted after ``[`` and before ``]``. + /// If ``true``, spaces will be inserted after ``[`` and before ``]``. /// Lambdas or unspecified size array declarations will not be affected. /// \code /// true: false: @@ -1563,7 +1638,7 @@ struct FormatStyle { /// \endcode bool SpacesInSquareBrackets; - /// \brief Supported language standards. + /// Supported language standards. enum LanguageStandard { /// Use C++03-compatible syntax. LS_Cpp03, @@ -1574,14 +1649,14 @@ struct FormatStyle { LS_Auto }; - /// \brief Format compatible with this standard, e.g. use ``A<A<int> >`` + /// Format compatible with this standard, e.g. use ``A<A<int> >`` /// instead of ``A<A<int>>`` for ``LS_Cpp03``. LanguageStandard Standard; - /// \brief The number of columns used for tab stops. + /// The number of columns used for tab stops. unsigned TabWidth; - /// \brief Different ways to use tab in formatting. + /// Different ways to use tab in formatting. enum UseTabStyle { /// Never use tab. UT_Never, @@ -1594,7 +1669,7 @@ struct FormatStyle { UT_Always }; - /// \brief The way to use tab characters in the resulting file. + /// The way to use tab characters in the resulting file. UseTabStyle UseTab; bool operator==(const FormatStyle &R) const { @@ -1630,7 +1705,7 @@ struct FormatStyle { BreakAfterJavaFieldAnnotations == R.BreakAfterJavaFieldAnnotations && BreakStringLiterals == R.BreakStringLiterals && ColumnLimit == R.ColumnLimit && CommentPragmas == R.CommentPragmas && - BreakBeforeInheritanceComma == R.BreakBeforeInheritanceComma && + BreakInheritanceList == R.BreakInheritanceList && ConstructorInitializerAllOnOneLineOrOnePerLine == R.ConstructorInitializerAllOnOneLineOrOnePerLine && ConstructorInitializerIndentWidth == @@ -1643,8 +1718,8 @@ struct FormatStyle { R.ExperimentalAutoDetectBinPacking && FixNamespaceComments == R.FixNamespaceComments && ForEachMacros == R.ForEachMacros && - IncludeBlocks == R.IncludeBlocks && - IncludeCategories == R.IncludeCategories && + IncludeStyle.IncludeBlocks == R.IncludeStyle.IncludeBlocks && + IncludeStyle.IncludeCategories == R.IncludeStyle.IncludeCategories && IndentCaseLabels == R.IndentCaseLabels && IndentPPDirectives == R.IndentPPDirectives && IndentWidth == R.IndentWidth && Language == R.Language && @@ -1657,11 +1732,11 @@ struct FormatStyle { MacroBlockEnd == R.MacroBlockEnd && MaxEmptyLinesToKeep == R.MaxEmptyLinesToKeep && NamespaceIndentation == R.NamespaceIndentation && + ObjCBinPackProtocolList == R.ObjCBinPackProtocolList && ObjCBlockIndentWidth == R.ObjCBlockIndentWidth && ObjCSpaceAfterProperty == R.ObjCSpaceAfterProperty && ObjCSpaceBeforeProtocolList == R.ObjCSpaceBeforeProtocolList && - PenaltyBreakAssignment == - R.PenaltyBreakAssignment && + PenaltyBreakAssignment == R.PenaltyBreakAssignment && PenaltyBreakBeforeFirstCallParameter == R.PenaltyBreakBeforeFirstCallParameter && PenaltyBreakComment == R.PenaltyBreakComment && @@ -1669,12 +1744,20 @@ struct FormatStyle { PenaltyBreakString == R.PenaltyBreakString && PenaltyExcessCharacter == R.PenaltyExcessCharacter && PenaltyReturnTypeOnItsOwnLine == R.PenaltyReturnTypeOnItsOwnLine && + PenaltyBreakTemplateDeclaration == + R.PenaltyBreakTemplateDeclaration && PointerAlignment == R.PointerAlignment && RawStringFormats == R.RawStringFormats && SpaceAfterCStyleCast == R.SpaceAfterCStyleCast && SpaceAfterTemplateKeyword == R.SpaceAfterTemplateKeyword && SpaceBeforeAssignmentOperators == R.SpaceBeforeAssignmentOperators && + SpaceBeforeCpp11BracedList == R.SpaceBeforeCpp11BracedList && + SpaceBeforeCtorInitializerColon == + R.SpaceBeforeCtorInitializerColon && + SpaceBeforeInheritanceColon == R.SpaceBeforeInheritanceColon && SpaceBeforeParens == R.SpaceBeforeParens && + SpaceBeforeRangeBasedForLoopColon == + R.SpaceBeforeRangeBasedForLoopColon && SpaceInEmptyParentheses == R.SpaceInEmptyParentheses && SpacesBeforeTrailingComments == R.SpacesBeforeTrailingComments && SpacesInAngles == R.SpacesInAngles && @@ -1685,38 +1768,75 @@ struct FormatStyle { Standard == R.Standard && TabWidth == R.TabWidth && UseTab == R.UseTab; } + + llvm::Optional<FormatStyle> GetLanguageStyle(LanguageKind Language) const; + + // Stores per-language styles. A FormatStyle instance inside has an empty + // StyleSet. A FormatStyle instance returned by the Get method has its + // StyleSet set to a copy of the originating StyleSet, effectively keeping the + // internal representation of that StyleSet alive. + // + // The memory management and ownership reminds of a birds nest: chicks + // leaving the nest take photos of the nest with them. + struct FormatStyleSet { + typedef std::map<FormatStyle::LanguageKind, FormatStyle> MapType; + + llvm::Optional<FormatStyle> Get(FormatStyle::LanguageKind Language) const; + + // Adds \p Style to this FormatStyleSet. Style must not have an associated + // FormatStyleSet. + // Style.Language should be different than LK_None. If this FormatStyleSet + // already contains an entry for Style.Language, that gets replaced with the + // passed Style. + void Add(FormatStyle Style); + + // Clears this FormatStyleSet. + void Clear(); + + private: + std::shared_ptr<MapType> Styles; + }; + + static FormatStyleSet BuildStyleSetFromConfiguration( + const FormatStyle &MainStyle, + const std::vector<FormatStyle> &ConfigurationStyles); + +private: + FormatStyleSet StyleSet; + + friend std::error_code parseConfiguration(StringRef Text, FormatStyle *Style); }; -/// \brief Returns a format style complying with the LLVM coding standards: +/// Returns a format style complying with the LLVM coding standards: /// http://llvm.org/docs/CodingStandards.html. FormatStyle getLLVMStyle(); -/// \brief Returns a format style complying with one of Google's style guides: +/// Returns a format style complying with one of Google's style guides: /// http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml. /// http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml. /// https://developers.google.com/protocol-buffers/docs/style. FormatStyle getGoogleStyle(FormatStyle::LanguageKind Language); -/// \brief Returns a format style complying with Chromium's style guide: +/// Returns a format style complying with Chromium's style guide: /// http://www.chromium.org/developers/coding-style. FormatStyle getChromiumStyle(FormatStyle::LanguageKind Language); -/// \brief Returns a format style complying with Mozilla's style guide: +/// Returns a format style complying with Mozilla's style guide: /// https://developer.mozilla.org/en-US/docs/Developer_Guide/Coding_Style. FormatStyle getMozillaStyle(); -/// \brief Returns a format style complying with Webkit's style guide: +/// Returns a format style complying with Webkit's style guide: /// http://www.webkit.org/coding/coding-style.html FormatStyle getWebKitStyle(); -/// \brief Returns a format style complying with GNU Coding Standards: +/// Returns a format style complying with GNU Coding Standards: /// http://www.gnu.org/prep/standards/standards.html FormatStyle getGNUStyle(); -/// \brief Returns style indicating formatting should be not applied at all. +/// Returns style indicating formatting should be not applied at all. FormatStyle getNoStyle(); -/// \brief Gets a predefined style for the specified language by name. +/// Gets a predefined style for the specified language by name. /// /// Currently supported names: LLVM, Google, Chromium, Mozilla. Names are /// compared case-insensitively. @@ -1725,66 +1845,64 @@ FormatStyle getNoStyle(); bool getPredefinedStyle(StringRef Name, FormatStyle::LanguageKind Language, FormatStyle *Style); -/// \brief Parse configuration from YAML-formatted text. +/// Parse configuration from YAML-formatted text. /// /// Style->Language is used to get the base style, if the ``BasedOnStyle`` /// option is present. /// +/// The FormatStyleSet of Style is reset. +/// /// When ``BasedOnStyle`` is not present, options not present in the YAML /// document, are retained in \p Style. std::error_code parseConfiguration(StringRef Text, FormatStyle *Style); -/// \brief Gets configuration in a YAML string. +/// Gets configuration in a YAML string. std::string configurationAsText(const FormatStyle &Style); -/// \brief Returns the replacements necessary to sort all ``#include`` blocks +/// Returns the replacements necessary to sort all ``#include`` blocks /// that are affected by ``Ranges``. tooling::Replacements sortIncludes(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName, unsigned *Cursor = nullptr); -/// \brief Returns the replacements corresponding to applying and formatting +/// Returns the replacements corresponding to applying and formatting /// \p Replaces on success; otheriwse, return an llvm::Error carrying /// llvm::StringError. llvm::Expected<tooling::Replacements> formatReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style); -/// \brief Returns the replacements corresponding to applying \p Replaces and +/// Returns the replacements corresponding to applying \p Replaces and /// cleaning up the code after that on success; otherwise, return an llvm::Error /// carrying llvm::StringError. /// This also supports inserting/deleting C++ #include directives: /// - If a replacement has offset UINT_MAX, length 0, and a replacement text /// that is an #include directive, this will insert the #include into the -/// correct block in the \p Code. When searching for points to insert new -/// header, this ignores #include's after the #include block(s) in the -/// beginning of a file to avoid inserting headers into code sections where -/// new #include's should not be added by default. These code sections -/// include: -/// - raw string literals (containing #include). -/// - #if blocks. -/// - Special #include's among declarations (e.g. functions). +/// correct block in the \p Code. /// - If a replacement has offset UINT_MAX, length 1, and a replacement text /// that is the name of the header to be removed, the header will be removed /// from \p Code if it exists. +/// The include manipulation is done via `tooling::HeaderInclude`, see its +/// documentation for more details on how include insertion points are found and +/// what edits are produced. llvm::Expected<tooling::Replacements> cleanupAroundReplacements(StringRef Code, const tooling::Replacements &Replaces, const FormatStyle &Style); -/// \brief Represents the status of a formatting attempt. +/// Represents the status of a formatting attempt. struct FormattingAttemptStatus { - /// \brief A value of ``false`` means that any of the affected ranges were not + /// A value of ``false`` means that any of the affected ranges were not /// formatted due to a non-recoverable syntax error. bool FormatComplete = true; - /// \brief If ``FormatComplete`` is false, ``Line`` records a one-based + /// If ``FormatComplete`` is false, ``Line`` records a one-based /// original line number at which a syntax error might have occurred. This is /// based on a best-effort analysis and could be imprecise. unsigned Line = 0; }; -/// \brief Reformats the given \p Ranges in \p Code. +/// Reformats the given \p Ranges in \p Code. /// /// 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 @@ -1800,7 +1918,7 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, StringRef FileName = "<stdin>", FormattingAttemptStatus *Status = nullptr); -/// \brief Same as above, except if ``IncompleteFormat`` is non-null, its value +/// Same as above, except if ``IncompleteFormat`` is non-null, its value /// will be set to true if any of the affected ranges were not formatted due to /// a non-recoverable syntax error. tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, @@ -1808,7 +1926,7 @@ tooling::Replacements reformat(const FormatStyle &Style, StringRef Code, StringRef FileName, bool *IncompleteFormat); -/// \brief Clean up any erroneous/redundant code in the given \p Ranges in \p +/// Clean up any erroneous/redundant code in the given \p Ranges in \p /// Code. /// /// Returns the ``Replacements`` that clean up all \p Ranges in \p Code. @@ -1816,7 +1934,7 @@ tooling::Replacements cleanup(const FormatStyle &Style, StringRef Code, ArrayRef<tooling::Range> Ranges, StringRef FileName = "<stdin>"); -/// \brief Fix namespace end comments in the given \p Ranges in \p Code. +/// Fix namespace end comments in the given \p Ranges in \p Code. /// /// Returns the ``Replacements`` that fix the namespace comments in all /// \p Ranges in \p Code. @@ -1825,7 +1943,7 @@ tooling::Replacements fixNamespaceEndComments(const FormatStyle &Style, ArrayRef<tooling::Range> Ranges, StringRef FileName = "<stdin>"); -/// \brief Sort consecutive using declarations in the given \p Ranges in +/// Sort consecutive using declarations in the given \p Ranges in /// \p Code. /// /// Returns the ``Replacements`` that sort the using declarations in all @@ -1835,17 +1953,26 @@ tooling::Replacements sortUsingDeclarations(const FormatStyle &Style, ArrayRef<tooling::Range> Ranges, StringRef FileName = "<stdin>"); -/// \brief Returns the ``LangOpts`` that the formatter expects you to set. +/// Returns the ``LangOpts`` that the formatter expects you to set. /// /// \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 +/// Description to be used for help text for a ``llvm::cl`` option for /// specifying format style. The description is closely related to the operation /// of ``getStyle()``. extern const char *StyleOptionHelpDescription; -/// \brief Construct a FormatStyle based on ``StyleName``. +/// The suggested format style to use by default. This allows tools using +/// `getStyle` to have a consistent default style. +/// Different builds can modify the value to the preferred styles. +extern const char *DefaultFormatStyle; + +/// The suggested predefined style to use as the fallback style in `getStyle`. +/// Different builds can modify the value to the preferred styles. +extern const char *DefaultFallbackStyle; + +/// Construct a FormatStyle based on ``StyleName``. /// /// ``StyleName`` can take several forms: /// * "{<key>: <value>, ...}" - Set specic style parameters. @@ -1874,7 +2001,11 @@ llvm::Expected<FormatStyle> getStyle(StringRef StyleName, StringRef FileName, StringRef Code = "", vfs::FileSystem *FS = nullptr); -// \brief Returns a string representation of ``Language``. +// Guesses the language from the ``FileName`` and ``Code`` to be formatted. +// Defaults to FormatStyle::LK_Cpp. +FormatStyle::LanguageKind guessLanguage(StringRef FileName, StringRef Code); + +// Returns a string representation of ``Language``. inline StringRef getLanguageName(FormatStyle::LanguageKind Language) { switch (Language) { case FormatStyle::LK_Cpp: diff --git a/include/clang/Frontend/ASTConsumers.h b/include/clang/Frontend/ASTConsumers.h index 53975a07ea944..2a13527df1350 100644 --- a/include/clang/Frontend/ASTConsumers.h +++ b/include/clang/Frontend/ASTConsumers.h @@ -34,9 +34,10 @@ class TargetOptions; std::unique_ptr<ASTConsumer> CreateASTPrinter(std::unique_ptr<raw_ostream> OS, StringRef FilterString); -// AST dumper: dumps the raw AST in human-readable form to stderr; this is -// intended for debugging. -std::unique_ptr<ASTConsumer> CreateASTDumper(StringRef FilterString, +// AST dumper: dumps the raw AST in human-readable form to the given output +// stream, or stdout if OS is nullptr. +std::unique_ptr<ASTConsumer> CreateASTDumper(std::unique_ptr<raw_ostream> OS, + StringRef FilterString, bool DumpDecls, bool Deserialize, bool DumpLookups); diff --git a/include/clang/Frontend/ASTUnit.h b/include/clang/Frontend/ASTUnit.h index 5d04dcd19119a..9f529ba0e0e85 100644 --- a/include/clang/Frontend/ASTUnit.h +++ b/include/clang/Frontend/ASTUnit.h @@ -1,4 +1,4 @@ -//===--- ASTUnit.h - ASTUnit utility ----------------------------*- C++ -*-===// +//===- ASTUnit.h - ASTUnit utility ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,8 +16,11 @@ #include "clang-c/Index.h" #include "clang/AST/ASTContext.h" +#include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetOptions.h" #include "clang/Lex/HeaderSearchOptions.h" @@ -26,48 +29,62 @@ #include "clang/Sema/CodeCompleteConsumer.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Frontend/PrecompiledPreamble.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" -#include "llvm/Support/MD5.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" #include <cassert> +#include <cstddef> +#include <cstdint> #include <memory> #include <string> -#include <sys/types.h> #include <utility> #include <vector> namespace llvm { - class MemoryBuffer; -} + +class MemoryBuffer; + +} // namespace llvm namespace clang { -class Sema; + class ASTContext; +class ASTDeserializationListener; +class ASTMutationListener; class ASTReader; -class CompilerInvocation; class CompilerInstance; +class CompilerInvocation; class Decl; -class DiagnosticsEngine; class FileEntry; class FileManager; +class FrontendAction; class HeaderSearch; class InputKind; class MemoryBufferCache; -class Preprocessor; -class PreprocessorOptions; class PCHContainerOperations; class PCHContainerReader; +class Preprocessor; +class PreprocessorOptions; +class Sema; class TargetInfo; -class FrontendAction; -class ASTDeserializationListener; namespace vfs { + class FileSystem; -} -/// \brief Utility class for loading a ASTContext from an AST file. -/// +} // namespace vfs + +/// \brief Enumerates the available scopes for skipping function bodies. +enum class SkipFunctionBodiesScope { None, Preamble, PreambleAndMainFile }; + +/// Utility class for loading a ASTContext from an AST file. class ASTUnit { public: struct StandaloneFixIt { @@ -83,7 +100,7 @@ public: std::string Message; std::string Filename; unsigned LocOffset; - std::vector<std::pair<unsigned, unsigned> > Ranges; + std::vector<std::pair<unsigned, unsigned>> Ranges; std::vector<StandaloneFixIt> FixIts; }; @@ -101,18 +118,18 @@ private: std::shared_ptr<HeaderSearchOptions> HSOpts; std::shared_ptr<PreprocessorOptions> PPOpts; IntrusiveRefCntPtr<ASTReader> Reader; - bool HadModuleLoaderFatalFailure; + bool HadModuleLoaderFatalFailure = false; struct ASTWriterData; std::unique_ptr<ASTWriterData> WriterData; FileSystemOptions FileSystemOpts; - /// \brief The AST consumer that received information about the translation + /// The AST consumer that received information about the translation /// unit as it was parsed or loaded. std::unique_ptr<ASTConsumer> Consumer; - /// \brief The semantic analysis object used to type-check the translation + /// The semantic analysis object used to type-check the translation /// unit. std::unique_ptr<Sema> TheSema; @@ -126,22 +143,22 @@ private: // OnlyLocalDecls - when true, walking this AST should only visit declarations // that come from the AST itself, not from included precompiled headers. // FIXME: This is temporary; eventually, CIndex will always do this. - bool OnlyLocalDecls; + bool OnlyLocalDecls = false; - /// \brief Whether to capture any diagnostics produced. - bool CaptureDiagnostics; + /// Whether to capture any diagnostics produced. + bool CaptureDiagnostics = false; - /// \brief Track whether the main file was loaded from an AST or not. + /// Track whether the main file was loaded from an AST or not. bool MainFileIsAST; - /// \brief What kind of translation unit this AST represents. - TranslationUnitKind TUKind; + /// What kind of translation unit this AST represents. + TranslationUnitKind TUKind = TU_Complete; - /// \brief Whether we should time each operation. + /// Whether we should time each operation. bool WantTiming; - /// \brief Whether the ASTUnit should delete the remapped buffers. - bool OwnsRemappedFileBuffers; + /// Whether the ASTUnit should delete the remapped buffers. + bool OwnsRemappedFileBuffers = true; /// Track the top-level decls which appeared in an ASTUnit which was loaded /// from a source file. @@ -152,36 +169,36 @@ private: // more scalable search mechanisms. std::vector<Decl*> TopLevelDecls; - /// \brief Sorted (by file offset) vector of pairs of file offset/Decl. - typedef SmallVector<std::pair<unsigned, Decl *>, 64> LocDeclsTy; - typedef llvm::DenseMap<FileID, LocDeclsTy *> FileDeclsTy; + /// Sorted (by file offset) vector of pairs of file offset/Decl. + using LocDeclsTy = SmallVector<std::pair<unsigned, Decl *>, 64>; + using FileDeclsTy = llvm::DenseMap<FileID, LocDeclsTy *>; - /// \brief Map from FileID to the file-level declarations that it contains. + /// Map from FileID to the file-level declarations that it contains. /// The files and decls are only local (and non-preamble) ones. FileDeclsTy FileDecls; /// The name of the original source file used to generate this ASTUnit. std::string OriginalSourceFile; - /// \brief The set of diagnostics produced when creating the preamble. + /// The set of diagnostics produced when creating the preamble. SmallVector<StandaloneDiagnostic, 4> PreambleDiagnostics; - /// \brief The set of diagnostics produced when creating this + /// The set of diagnostics produced when creating this /// translation unit. SmallVector<StoredDiagnostic, 4> StoredDiagnostics; - /// \brief The set of diagnostics produced when failing to parse, e.g. due + /// The set of diagnostics produced when failing to parse, e.g. due /// to failure to load the PCH. SmallVector<StoredDiagnostic, 4> FailedParseDiagnostics; - /// \brief The number of stored diagnostics that come from the driver + /// The number of stored diagnostics that come from the driver /// itself. /// /// Diagnostics that come from the driver are retained from one parse to /// the next. - unsigned NumStoredDiagnosticsFromDriver; + unsigned NumStoredDiagnosticsFromDriver = 0; - /// \brief Counter that determines when we want to try building a + /// Counter that determines when we want to try building a /// precompiled preamble. /// /// If zero, we will never build a precompiled preamble. Otherwise, @@ -190,45 +207,44 @@ private: /// we'll attempt to rebuild the precompiled header. This way, if /// building the precompiled preamble fails, we won't try again for /// some number of calls. - unsigned PreambleRebuildCounter; + unsigned PreambleRebuildCounter = 0; - /// \brief Cache pairs "filename - source location" + /// Cache pairs "filename - source location" /// /// Cache contains only source locations from preamble so it is /// guaranteed that they stay valid when the SourceManager is recreated. - /// This cache is used when loading preambule to increase performance + /// This cache is used when loading preamble to increase performance /// of that loading. It must be cleared when preamble is recreated. llvm::StringMap<SourceLocation> PreambleSrcLocCache; -private: /// The contents of the preamble. llvm::Optional<PrecompiledPreamble> Preamble; - /// \brief When non-NULL, this is the buffer used to store the contents of + /// 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. std::unique_ptr<llvm::MemoryBuffer> SavedMainFileBuffer; - /// \brief The number of warnings that occurred while parsing the preamble. + /// The number of warnings that occurred while parsing the preamble. /// /// This value will be used to restore the state of the \c DiagnosticsEngine /// object when re-using the precompiled preamble. Note that only the /// number of warnings matters, since we will not save the preamble /// when any errors are present. - unsigned NumWarningsInPreamble; + unsigned NumWarningsInPreamble = 0; - /// \brief A list of the serialization ID numbers for each of the top-level + /// A list of the serialization ID numbers for each of the top-level /// declarations parsed within the precompiled preamble. std::vector<serialization::DeclID> TopLevelDeclsInPreamble; - /// \brief Whether we should be caching code-completion results. + /// Whether we should be caching code-completion results. bool ShouldCacheCodeCompletionResults : 1; - /// \brief Whether to include brief documentation within the set of code + /// Whether to include brief documentation within the set of code /// completions cached. bool IncludeBriefCommentsInCodeCompletion : 1; - /// \brief True if non-system source files should be treated as volatile + /// True if non-system source files should be treated as volatile /// (likely to change while trying to use them). bool UserFilesAreVolatile : 1; @@ -243,14 +259,14 @@ private: void clearFileLevelDecls(); public: - /// \brief A cached code-completion result, which may be introduced in one of + /// A cached code-completion result, which may be introduced in one of /// many different contexts. struct CachedCodeCompletionResult { - /// \brief The code-completion string corresponding to this completion + /// The code-completion string corresponding to this completion /// result. CodeCompletionString *Completion; - /// \brief A bitmask that indicates which code-completion contexts should + /// A bitmask that indicates which code-completion contexts should /// contain this completion result. /// /// The bits in the bitmask correspond to the values of @@ -259,20 +275,20 @@ public: /// several different contexts. uint64_t ShowInContexts; - /// \brief The priority given to this code-completion result. + /// The priority given to this code-completion result. unsigned Priority; - /// \brief The libclang cursor kind corresponding to this code-completion + /// The libclang cursor kind corresponding to this code-completion /// result. CXCursorKind Kind; - /// \brief The availability of this code-completion result. + /// The availability of this code-completion result. CXAvailabilityKind Availability; - /// \brief The simplified type class for a non-macro completion result. + /// The simplified type class for a non-macro completion result. SimplifiedTypeClass TypeClass; - /// \brief The type of a non-macro completion result, stored as a unique + /// The type of a non-macro completion result, stored as a unique /// integer used by the string map of cached completion types. /// /// This value will be zero if the type is not known, or a unique value @@ -281,13 +297,13 @@ public: unsigned Type; }; - /// \brief Retrieve the mapping from formatted type names to unique type + /// Retrieve the mapping from formatted type names to unique type /// identifiers. - llvm::StringMap<unsigned> &getCachedCompletionTypes() { + llvm::StringMap<unsigned> &getCachedCompletionTypes() { return CachedCompletionTypes; } - /// \brief Retrieve the allocator used to cache global code completions. + /// Retrieve the allocator used to cache global code completions. std::shared_ptr<GlobalCodeCompletionAllocator> getCachedCompletionAllocator() { return CachedCompletionAllocator; @@ -301,50 +317,50 @@ public: } private: - /// \brief Allocator used to store cached code completions. + /// Allocator used to store cached code completions. std::shared_ptr<GlobalCodeCompletionAllocator> CachedCompletionAllocator; std::unique_ptr<CodeCompletionTUInfo> CCTUInfo; - /// \brief The set of cached code-completion results. + /// The set of cached code-completion results. std::vector<CachedCodeCompletionResult> CachedCompletionResults; - /// \brief A mapping from the formatted type name to a unique number for that + /// A mapping from the formatted type name to a unique number for that /// type, which is used for type equality comparisons. llvm::StringMap<unsigned> CachedCompletionTypes; - /// \brief A string hash of the top-level declaration and macro definition + /// A string hash of the top-level declaration and macro definition /// names processed the last time that we reparsed the file. /// /// This hash value is used to determine when we need to refresh the /// global code-completion cache. - unsigned CompletionCacheTopLevelHashValue; + unsigned CompletionCacheTopLevelHashValue = 0; - /// \brief A string hash of the top-level declaration and macro definition + /// A string hash of the top-level declaration and macro definition /// names processed the last time that we reparsed the precompiled preamble. /// /// This hash value is used to determine when we need to refresh the /// global code-completion cache after a rebuild of the precompiled preamble. - unsigned PreambleTopLevelHashValue; + unsigned PreambleTopLevelHashValue = 0; - /// \brief The current hash value for the top-level declaration and macro + /// The current hash value for the top-level declaration and macro /// definition names - unsigned CurrentTopLevelHashValue; + unsigned CurrentTopLevelHashValue = 0; - /// \brief Bit used by CIndex to mark when a translation unit may be in an + /// Bit used by CIndex to mark when a translation unit may be in an /// inconsistent state, and is not safe to free. unsigned UnsafeToFree : 1; - /// \brief Cache any "global" code-completion results, so that we can avoid + /// \brief Enumerator specifying the scope for skipping function bodies. + SkipFunctionBodiesScope SkipFunctionBodies = SkipFunctionBodiesScope::None; + + /// Cache any "global" code-completion results, so that we can avoid /// recomputing them with each completion. void CacheCodeCompletionResults(); - /// \brief Clear out and deallocate + /// Clear out and deallocate void ClearCachedCompletionResults(); - ASTUnit(const ASTUnit &) = delete; - void operator=(const ASTUnit &) = delete; - explicit ASTUnit(bool MainFileIsAST); bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps, @@ -353,16 +369,16 @@ private: std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble( std::shared_ptr<PCHContainerOperations> PCHContainerOps, - const CompilerInvocation &PreambleInvocationIn, + CompilerInvocation &PreambleInvocationIn, IntrusiveRefCntPtr<vfs::FileSystem> VFS, bool AllowRebuild = true, unsigned MaxLines = 0); void RealizeTopLevelDeclsFromPreamble(); - /// \brief Transfers ownership of the objects (like SourceManager) from + /// Transfers ownership of the objects (like SourceManager) from /// \param CI to this ASTUnit. void transferASTDataFromCompilerInstance(CompilerInstance &CI); - /// \brief Allows us to assert that ASTUnit is not being used concurrently, + /// Allows us to assert that ASTUnit is not being used concurrently, /// which is not supported. /// /// Clients should create instances of the ConcurrencyCheck class whenever @@ -382,21 +398,23 @@ private: ConcurrencyState ConcurrencyCheckValue; public: + friend class ConcurrencyCheck; + class ConcurrencyCheck { ASTUnit &Self; public: - explicit ConcurrencyCheck(ASTUnit &Self) - : Self(Self) - { + explicit ConcurrencyCheck(ASTUnit &Self) : Self(Self) { Self.ConcurrencyCheckValue.start(); } + ~ConcurrencyCheck() { Self.ConcurrencyCheckValue.finish(); } }; - friend class ConcurrencyCheck; + ASTUnit(const ASTUnit &) = delete; + ASTUnit &operator=(const ASTUnit &) = delete; ~ASTUnit(); bool isMainFileAST() const { return MainFileIsAST; } @@ -405,22 +423,32 @@ public: void setUnsafeToFree(bool Value) { UnsafeToFree = Value; } const DiagnosticsEngine &getDiagnostics() const { return *Diagnostics; } - DiagnosticsEngine &getDiagnostics() { return *Diagnostics; } + DiagnosticsEngine &getDiagnostics() { return *Diagnostics; } const SourceManager &getSourceManager() const { return *SourceMgr; } - SourceManager &getSourceManager() { return *SourceMgr; } + SourceManager &getSourceManager() { return *SourceMgr; } const Preprocessor &getPreprocessor() const { return *PP; } - Preprocessor &getPreprocessor() { return *PP; } + Preprocessor &getPreprocessor() { return *PP; } std::shared_ptr<Preprocessor> getPreprocessorPtr() const { return PP; } const ASTContext &getASTContext() const { return *Ctx; } - ASTContext &getASTContext() { return *Ctx; } + ASTContext &getASTContext() { return *Ctx; } void setASTContext(ASTContext *ctx) { Ctx = ctx; } void setPreprocessor(std::shared_ptr<Preprocessor> pp); + /// Enable source-range based diagnostic messages. + /// + /// If diagnostic messages with source-range information are to be expected + /// and AST comes not from file (e.g. after LoadFromCompilerInvocation) this + /// function has to be called. + /// The function is to be called only once and the AST should be associated + /// with the same source file afterwards. + void enableSourceFileDiagnostics(); + bool hasSema() const { return (bool)TheSema; } + Sema &getSema() const { assert(TheSema && "ASTUnit does not have a Sema object!"); return *TheSema; @@ -442,7 +470,7 @@ public: } const FileManager &getFileManager() const { return *FileMgr; } - FileManager &getFileManager() { return *FileMgr; } + FileManager &getFileManager() { return *FileMgr; } const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } @@ -462,10 +490,10 @@ public: StringRef getMainFileName() const; - /// \brief If this ASTUnit came from an AST file, returns the filename for it. + /// If this ASTUnit came from an AST file, returns the filename for it. StringRef getASTFileName() const; - typedef std::vector<Decl *>::iterator top_level_iterator; + using top_level_iterator = std::vector<Decl *>::iterator; top_level_iterator top_level_begin() { assert(!isMainFileAST() && "Invalid call for AST based ASTUnit!"); @@ -491,26 +519,26 @@ public: return TopLevelDeclsInPreamble.empty() && TopLevelDecls.empty(); } - /// \brief Add a new top-level declaration. + /// Add a new top-level declaration. void addTopLevelDecl(Decl *D) { TopLevelDecls.push_back(D); } - /// \brief Add a new local file-level declaration. + /// Add a new local file-level declaration. void addFileLevelDecl(Decl *D); - /// \brief Get the decls that are contained in a file in the Offset/Length + /// Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. void findFileRegionDecls(FileID File, unsigned Offset, unsigned Length, SmallVectorImpl<Decl *> &Decls); - /// \brief Retrieve a reference to the current top-level name hash value. + /// Retrieve a reference to the current top-level name hash value. /// /// Note: This is used internally by the top-level tracking action unsigned &getCurrentTopLevelHashValue() { return CurrentTopLevelHashValue; } - /// \brief Get the source location for the given file:line:col triplet. + /// Get the source location for the given file:line:col triplet. /// /// The difference with SourceManager::getLocation is that this method checks /// whether the requested location points inside the precompiled preamble @@ -518,15 +546,15 @@ public: SourceLocation getLocation(const FileEntry *File, unsigned Line, unsigned Col) const; - /// \brief Get the source location for the given file:offset pair. + /// Get the source location for the given file:offset pair. SourceLocation getLocation(const FileEntry *File, unsigned Offset) const; - /// \brief If \p Loc is a loaded location from the preamble, returns + /// If \p Loc is a loaded location from the preamble, returns /// the corresponding local location of the main file, otherwise it returns /// \p Loc. SourceLocation mapLocationFromPreamble(SourceLocation Loc) const; - /// \brief If \p Loc is a local location of the main file but inside the + /// If \p Loc is a local location of the main file but inside the /// preamble chunk, returns the corresponding loaded location from the /// preamble, otherwise it returns \p Loc. SourceLocation mapLocationToPreamble(SourceLocation Loc) const; @@ -549,20 +577,25 @@ public: } // Retrieve the diagnostics associated with this AST - typedef StoredDiagnostic *stored_diag_iterator; - typedef const StoredDiagnostic *stored_diag_const_iterator; + using stored_diag_iterator = StoredDiagnostic *; + using stored_diag_const_iterator = const StoredDiagnostic *; + stored_diag_const_iterator stored_diag_begin() const { return StoredDiagnostics.begin(); } + stored_diag_iterator stored_diag_begin() { return StoredDiagnostics.begin(); } + stored_diag_const_iterator stored_diag_end() const { return StoredDiagnostics.end(); } + stored_diag_iterator stored_diag_end() { return StoredDiagnostics.end(); } + unsigned stored_diag_size() const { return StoredDiagnostics.size(); } stored_diag_iterator stored_diag_afterDriver_begin() { @@ -571,8 +604,8 @@ public: return StoredDiagnostics.begin() + NumStoredDiagnosticsFromDriver; } - typedef std::vector<CachedCodeCompletionResult>::iterator - cached_completion_iterator; + using cached_completion_iterator = + std::vector<CachedCodeCompletionResult>::iterator; cached_completion_iterator cached_completion_begin() { return CachedCompletionResults.begin(); @@ -586,43 +619,43 @@ public: return CachedCompletionResults.size(); } - /// \brief Returns an iterator range for the local preprocessing entities + /// Returns an iterator range for the local preprocessing entities /// of the local Preprocessor, if this is a parsed source file, or the loaded /// preprocessing entities of the primary module if this is an AST file. llvm::iterator_range<PreprocessingRecord::iterator> getLocalPreprocessingEntities() const; - /// \brief Type for a function iterating over a number of declarations. + /// Type for a function iterating over a number of declarations. /// \returns true to continue iteration and false to abort. - typedef bool (*DeclVisitorFn)(void *context, const Decl *D); + using DeclVisitorFn = bool (*)(void *context, const Decl *D); - /// \brief Iterate over local declarations (locally parsed if this is a parsed + /// Iterate over local declarations (locally parsed if this is a parsed /// source file or the loaded declarations of the primary module if this is an /// AST file). /// \returns true if the iteration was complete or false if it was aborted. bool visitLocalTopLevelDecls(void *context, DeclVisitorFn Fn); - /// \brief Get the PCH file if one was included. + /// Get the PCH file if one was included. const FileEntry *getPCHFile(); - /// \brief Returns true if the ASTUnit was constructed from a serialized + /// Returns true if the ASTUnit was constructed from a serialized /// module file. bool isModuleFile() const; std::unique_ptr<llvm::MemoryBuffer> getBufferForFile(StringRef Filename, std::string *ErrorStr = nullptr); - /// \brief Determine what kind of translation unit this AST represents. + /// Determine what kind of translation unit this AST represents. TranslationUnitKind getTranslationUnitKind() const { return TUKind; } - /// \brief Determine the input kind this AST unit represents. + /// Determine the input kind this AST unit represents. InputKind getInputKind() const; - /// \brief A mapping from a file name to the memory buffer that stores the + /// A mapping from a file name to the memory buffer that stores the /// remapped contents of that file. - typedef std::pair<std::string, llvm::MemoryBuffer *> RemappedFile; + using RemappedFile = std::pair<std::string, llvm::MemoryBuffer *>; - /// \brief Create a ASTUnit. Gets ownership of the passed CompilerInvocation. + /// Create a ASTUnit. Gets ownership of the passed CompilerInvocation. static std::unique_ptr<ASTUnit> create(std::shared_ptr<CompilerInvocation> CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags, bool CaptureDiagnostics, @@ -631,13 +664,15 @@ public: enum WhatToLoad { /// Load options and the preprocessor state. LoadPreprocessorOnly, + /// Load the AST, but do not restore Sema state. LoadASTOnly, + /// Load everything, including Sema. LoadEverything }; - /// \brief Create a ASTUnit from an AST file. + /// Create a ASTUnit from an AST file. /// /// \param Filename - The AST file to load. /// @@ -656,7 +691,7 @@ public: bool UserFilesAreVolatile = false); private: - /// \brief Helper function for \c LoadFromCompilerInvocation() and + /// Helper function for \c LoadFromCompilerInvocation() and /// \c LoadFromCommandLine(), which loads an AST from a compiler invocation. /// /// \param PrecompilePreambleAfterNParses After how many parses the preamble @@ -676,8 +711,7 @@ private: IntrusiveRefCntPtr<vfs::FileSystem> VFS); public: - - /// \brief Create an ASTUnit from a source file, via a CompilerInvocation + /// Create an ASTUnit from a source file, via a CompilerInvocation /// object, by invoking the optionally provided ASTFrontendAction. /// /// \param CI - The compiler invocation to use; it must have exactly one input @@ -782,14 +816,16 @@ public: TranslationUnitKind TUKind = TU_Complete, bool CacheCodeCompletionResults = false, bool IncludeBriefCommentsInCodeCompletion = false, - bool AllowPCHWithCompilerErrors = false, bool SkipFunctionBodies = false, - bool SingleFileParse = false, - bool UserFilesAreVolatile = false, bool ForSerialization = false, + bool AllowPCHWithCompilerErrors = false, + SkipFunctionBodiesScope SkipFunctionBodies = + SkipFunctionBodiesScope::None, + bool SingleFileParse = false, bool UserFilesAreVolatile = false, + bool ForSerialization = false, llvm::Optional<StringRef> ModuleFormat = llvm::None, std::unique_ptr<ASTUnit> *ErrAST = nullptr, IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr); - /// \brief Reparse the source files using the same command-line options that + /// Reparse the source files using the same command-line options that /// were originally used to produce this translation unit. /// /// \param VFS - A vfs::FileSystem to be used for all file accesses. Note that @@ -804,12 +840,12 @@ public: ArrayRef<RemappedFile> RemappedFiles = None, IntrusiveRefCntPtr<vfs::FileSystem> VFS = nullptr); - /// \brief Free data that will be re-generated on the next parse. + /// Free data that will be re-generated on the next parse. /// /// Preamble-related data is not affected. void ResetForParse(); - /// \brief Perform code completion at the given file, line, and + /// Perform code completion at the given file, line, and /// column within this translation unit. /// /// \param File The file in which code completion will occur. @@ -839,13 +875,13 @@ public: SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics, SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers); - /// \brief Save this translation unit to a file with the given name. + /// Save this translation unit to a file with the given name. /// /// \returns true if there was a file error or false if the save was /// successful. bool Save(StringRef File); - /// \brief Serialize this translation unit with the given output stream. + /// Serialize this translation unit with the given output stream. /// /// \returns True if an error occurred, false otherwise. bool serialize(raw_ostream &OS); @@ -853,4 +889,4 @@ public: } // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_ASTUNIT_H diff --git a/include/clang/Frontend/ChainedDiagnosticConsumer.h b/include/clang/Frontend/ChainedDiagnosticConsumer.h index eb33273c2fb3f..04c6077dc35e7 100644 --- a/include/clang/Frontend/ChainedDiagnosticConsumer.h +++ b/include/clang/Frontend/ChainedDiagnosticConsumer.h @@ -32,7 +32,7 @@ public: : OwningPrimary(std::move(Primary)), Primary(OwningPrimary.get()), Secondary(std::move(Secondary)) {} - /// \brief Construct without taking ownership of \c Primary. + /// Construct without taking ownership of \c Primary. ChainedDiagnosticConsumer(DiagnosticConsumer *Primary, std::unique_ptr<DiagnosticConsumer> Secondary) : Primary(Primary), Secondary(std::move(Secondary)) {} diff --git a/include/clang/Frontend/CodeGenOptions.def b/include/clang/Frontend/CodeGenOptions.def index bb91cf5f742b7..a7e71f7ac0167 100644 --- a/include/clang/Frontend/CodeGenOptions.def +++ b/include/clang/Frontend/CodeGenOptions.def @@ -38,10 +38,12 @@ CODEGENOPT(AssumeSaneOperatorNew , 1, 1) ///< implicit __attribute__((malloc)) o CODEGENOPT(Autolink , 1, 1) ///< -fno-autolink CODEGENOPT(ObjCAutoRefCountExceptions , 1, 0) ///< Whether ARC should be EH-safe. CODEGENOPT(Backchain , 1, 0) ///< -mbackchain +CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard CODEGENOPT(CoverageExtraChecksum, 1, 0) ///< Whether we need a second checksum for functions in GCNO files. CODEGENOPT(CoverageNoFunctionNamesInData, 1, 0) ///< Do not include function names in GCDA files. CODEGENOPT(CoverageExitBlockBeforeBody, 1, 0) ///< Whether to emit the exit block before the body blocks in GCNO files. CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors. +CODEGENOPT(RegisterGlobalDtorsWithAtExit, 1, 1) ///< Use atexit or __cxa_atexit to register global destructors. CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker ///< aliases to base ctors when possible. CODEGENOPT(DataSections , 1, 0) ///< Set when -fdata-sections is enabled. @@ -61,15 +63,19 @@ CODEGENOPT(DebugPassManager, 1, 0) ///< Prints debug information for the new ///< pass manager. CODEGENOPT(DisableRedZone , 1, 0) ///< Set when -mno-red-zone is enabled. CODEGENOPT(DisableTailCalls , 1, 0) ///< Do not emit tail calls. +CODEGENOPT(NoEscapingBlockTailCalls, 1, 0) ///< Do not emit tail calls from + ///< escaping blocks. CODEGENOPT(EmitDeclMetadata , 1, 0) ///< Emit special metadata indicating what ///< Decl* various IR entities came from. ///< Only useful when running CodeGen as a ///< subroutine. +CODEGENOPT(EmitVersionIdentMetadata , 1, 1) ///< Emit compiler version metadata. CODEGENOPT(EmitGcovArcs , 1, 0) ///< Emit coverage data files, aka. GCDA. CODEGENOPT(EmitGcovNotes , 1, 0) ///< Emit coverage "notes" files, aka GCNO. CODEGENOPT(EmitOpenCLArgMetadata , 1, 0) ///< Emit OpenCL kernel arg metadata. -CODEGENOPT(EmulatedTLS , 1, 0) ///< Set when -femulated-tls is enabled. -/// \brief Embed Bitcode mode (off/all/bitcode/marker). +CODEGENOPT(EmulatedTLS , 1, 0) ///< Set by default or -f[no-]emulated-tls. +CODEGENOPT(ExplicitEmulatedTLS , 1, 0) ///< Set if -f[no-]emulated-tls is used. +/// Embed Bitcode mode (off/all/bitcode/marker). ENUM_CODEGENOPT(EmbedBitcode, EmbedBitcodeKind, 2, Embed_Off) CODEGENOPT(ForbidGuardVariables , 1, 0) ///< Issue errors if C++ guard variables ///< are required. @@ -80,13 +86,20 @@ CODEGENOPT(InstrumentFunctionsAfterInlining , 1, 0) ///< Set when ///< -finstrument-functions-after-inlining is enabled. CODEGENOPT(InstrumentFunctionEntryBare , 1, 0) ///< Set when ///< -finstrument-function-entry-bare is enabled. - +CODEGENOPT(CFProtectionReturn , 1, 0) ///< if -fcf-protection is + ///< set to full or return. +CODEGENOPT(CFProtectionBranch , 1, 0) ///< if -fcf-protection is + ///< set to full or branch. CODEGENOPT(XRayInstrumentFunctions , 1, 0) ///< Set when -fxray-instrument is ///< enabled. +CODEGENOPT(StackSizeSection , 1, 0) ///< Set when -fstack-size-section is enabled. ///< Set when -fxray-always-emit-customevents is enabled. CODEGENOPT(XRayAlwaysEmitCustomEvents , 1, 0) +///< Set when -fxray-always-emit-typedevents is enabled. +CODEGENOPT(XRayAlwaysEmitTypedEvents , 1, 0) + ///< Set the minimum number of instructions in a function to determine selective ///< XRay instrumentation. VALUE_CODEGENOPT(XRayInstructionThreshold , 32, 200) @@ -97,7 +110,7 @@ CODEGENOPT(LessPreciseFPMAD , 1, 0) ///< Enable less precise MAD instructions t ///< be generated. CODEGENOPT(PrepareForLTO , 1, 0) ///< Set when -flto is enabled on the ///< compile step. -CODEGENOPT(EmitSummaryIndex, 1, 0) ///< Set when -flto=thin is enabled on the +CODEGENOPT(PrepareForThinLTO , 1, 0) ///< Set when -flto=thin is enabled on the ///< compile step. CODEGENOPT(LTOUnit, 1, 0) ///< Emit IR to support LTO unit features (CFI, whole ///< program vtable opt). @@ -117,27 +130,32 @@ CODEGENOPT(EnableSegmentedStacks , 1, 0) ///< Set when -fsplit-stack 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(NullPointerIsValid , 1, 0) ///< Assume Null pointer deference is defined. CODEGENOPT(Reassociate , 1, 0) ///< Allow reassociation of FP math ops CODEGENOPT(ReciprocalMath , 1, 0) ///< Allow FP divisions to be reassociated. CODEGENOPT(NoTrappingMath , 1, 0) ///< Set when -fno-trapping-math is enabled. CODEGENOPT(NoNaNsFPMath , 1, 0) ///< Assume FP arguments, results not NaN. CODEGENOPT(FlushDenorm , 1, 0) ///< Allow FP denorm numbers to be flushed to zero CODEGENOPT(CorrectlyRoundedDivSqrt, 1, 0) ///< -cl-fp32-correctly-rounded-divide-sqrt + +/// When false, this attempts to generate code as if the result of an +/// overflowing conversion matches the overflowing behavior of a target's native +/// float-to-int conversion instructions. +CODEGENOPT(StrictFloatCastOverflow, 1, 1) + +CODEGENOPT(UniformWGSize , 1, 0) ///< -cl-uniform-work-group-size CODEGENOPT(NoZeroInitializedInBSS , 1, 0) ///< -fno-zero-initialized-in-bss. -/// \brief Method of Objective-C dispatch to use. +/// Method of Objective-C dispatch to use. ENUM_CODEGENOPT(ObjCDispatchMethod, ObjCDispatchMethodKind, 2, Legacy) CODEGENOPT(OmitLeafFramePointer , 1, 0) ///< Set when -momit-leaf-frame-pointer is ///< enabled. -/// A version of Clang that we should attempt to be ABI-compatible with. -ENUM_CODEGENOPT(ClangABICompat, ClangABI, 4, ClangABI::Latest) - VALUE_CODEGENOPT(OptimizationLevel, 2, 0) ///< The -O[0-3] option specified. VALUE_CODEGENOPT(OptimizeSize, 2, 0) ///< If -Os (==1) or -Oz (==2) is specified. -/// \brief Choose profile instrumenation kind or no instrumentation. +/// Choose profile instrumenation kind or no instrumentation. ENUM_CODEGENOPT(ProfileInstr, ProfileInstrKind, 2, ProfileNone) -/// \brief Choose profile kind for PGO use compilation. +/// Choose profile kind for PGO use compilation. ENUM_CODEGENOPT(ProfileUse, ProfileInstrKind, 2, ProfileNone) CODEGENOPT(CoverageMapping , 1, 0) ///< Generate coverage mapping regions to ///< enable code coverage analysis. @@ -154,6 +172,9 @@ CODEGENOPT(NewStructPathTBAA , 1, 0) ///< Whether or not to use enhanced struct- CODEGENOPT(SaveTempLabels , 1, 0) ///< Save temporary labels. CODEGENOPT(SanitizeAddressUseAfterScope , 1, 0) ///< Enable use-after-scope detection ///< in AddressSanitizer +CODEGENOPT(SanitizeAddressPoisonClassMemberArrayNewCookie, 1, + 0) ///< Enable poisoning operator new[] which is not a replaceable + ///< global allocation function in AddressSanitizer CODEGENOPT(SanitizeAddressGlobalsDeadStripping, 1, 0) ///< Enable linker dead stripping ///< of globals in AddressSanitizer CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in @@ -218,6 +239,7 @@ VALUE_CODEGENOPT(StackAlignment , 32, 0) ///< Overrides default stack ///< alignment, if not 0. VALUE_CODEGENOPT(StackProbeSize , 32, 4096) ///< Overrides default stack ///< probe size, even if 0. +CODEGENOPT(NoStackArgProbe, 1, 0) ///< Set when -mno-stack-arg-probe is used CODEGENOPT(DebugColumnInfo, 1, 0) ///< Whether or not to use column information ///< in debug info. @@ -230,7 +252,7 @@ CODEGENOPT(DebugExplicitImport, 1, 0) ///< Whether or not debug info should CODEGENOPT(EnableSplitDwarf, 1, 0) ///< Whether to enable split DWARF CODEGENOPT(SplitDwarfInlining, 1, 1) ///< Whether to include inlining info in the ///< skeleton CU to allow for symbolication - ///< of inline stack frames without .dwo files. + ///< of inline stack frames without .dwo files. CODEGENOPT(DebugFwdTemplateParams, 1, 0) ///< Whether to emit complete ///< template parameter descriptions in ///< forward declarations (versus just @@ -308,6 +330,16 @@ CODEGENOPT(GnuPubnames, 1, 0) CODEGENOPT(NoPLT, 1, 0) +/// Whether to embed source in DWARF debug line section. +CODEGENOPT(EmbedSource, 1, 0) + +/// Whether to emit all vtables +CODEGENOPT(ForceEmitVTables, 1, 0) + +/// Whether to emit an address-significance table into the object file. +CODEGENOPT(Addrsig, 1, 0) + + #undef CODEGENOPT #undef ENUM_CODEGENOPT #undef VALUE_CODEGENOPT diff --git a/include/clang/Frontend/CodeGenOptions.h b/include/clang/Frontend/CodeGenOptions.h index 6b8d2b935fdd2..a6d061acf0f4a 100644 --- a/include/clang/Frontend/CodeGenOptions.h +++ b/include/clang/Frontend/CodeGenOptions.h @@ -16,6 +16,8 @@ #include "clang/Basic/DebugInfoOptions.h" #include "clang/Basic/Sanitizers.h" +#include "clang/Basic/XRayInstr.h" +#include "llvm/Support/CodeGen.h" #include "llvm/Support/Regex.h" #include "llvm/Target/TargetOptions.h" #include <map> @@ -25,7 +27,7 @@ namespace clang { -/// \brief Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure +/// Bitfields of CodeGenOptions, split out from CodeGenOptions to ensure /// that this large collection of bitfields is a trivial class type. class CodeGenOptionsBase { public: @@ -167,7 +169,7 @@ public: std::string SplitDwarfFile; /// The name of the relocation model to use. - std::string RelocationModel; + llvm::Reloc::Model RelocationModel; /// The thread model to use std::string ThreadModel; @@ -176,9 +178,6 @@ public: /// function instead of to trap instructions. std::string TrapFuncName; - /// A list of command-line options to forward to the LLVM backend. - std::vector<std::string> BackendOptions; - /// A list of dependent libraries. std::vector<std::string> DependentLibraries; @@ -204,10 +203,12 @@ public: /// the summary and module symbol table (and not, e.g. any debug metadata). std::string ThinLinkBitcodeFile; - /// A list of file names passed with -fcuda-include-gpubinary options to - /// forward to CUDA runtime back-end for incorporating them into host-side - /// object file. - std::vector<std::string> CudaGpuBinaryFileNames; + /// Prefix to use for -save-temps output. + std::string SaveTempsFilePrefix; + + /// Name of file passed with -fcuda-include-gpubinary option to forward to + /// CUDA runtime back-end for incorporating them into host-side object file. + std::string CudaGpuBinaryFileName; /// The name of the file to which the backend should save YAML optimization /// records. @@ -248,7 +249,7 @@ public: /// List of backend command-line options for -fembed-bitcode. std::vector<uint8_t> CmdArgs; - /// \brief A list of all -fno-builtin-* function names (e.g., memset). + /// A list of all -fno-builtin-* function names (e.g., memset). std::vector<std::string> NoBuiltinFuncs; std::vector<std::string> Reciprocals; @@ -258,6 +259,9 @@ public: /// registers. std::string PreferVectorWidth; + /// Set of XRay instrumentation kinds to emit. + XRayInstrSet XRayInstrumentationBundle; + public: // Define accessors/mutators for code generation options of enumeration type. #define CODEGENOPT(Name, Bits, Default) @@ -268,7 +272,7 @@ public: CodeGenOptions(); - /// \brief Is this a libc/libm function that is no longer recognized as a + /// Is this a libc/libm function that is no longer recognized as a /// builtin because a -fno-builtin-* option has been specified? bool isNoBuiltinFunc(const char *Name) const; @@ -276,22 +280,22 @@ public: return NoBuiltinFuncs; } - /// \brief Check if Clang profile instrumenation is on. + /// Check if Clang profile instrumenation is on. bool hasProfileClangInstr() const { return getProfileInstr() == ProfileClangInstr; } - /// \brief Check if IR level profile instrumentation is on. + /// Check if IR level profile instrumentation is on. bool hasProfileIRInstr() const { return getProfileInstr() == ProfileIRInstr; } - /// \brief Check if Clang profile use is on. + /// Check if Clang profile use is on. bool hasProfileClangUse() const { return getProfileUse() == ProfileClangInstr; } - /// \brief Check if IR level profile use is on. + /// Check if IR level profile use is on. bool hasProfileIRUse() const { return getProfileUse() == ProfileIRInstr; } diff --git a/include/clang/Frontend/CommandLineSourceLoc.h b/include/clang/Frontend/CommandLineSourceLoc.h index f5c1e1a8a67d0..7ae98e079264f 100644 --- a/include/clang/Frontend/CommandLineSourceLoc.h +++ b/include/clang/Frontend/CommandLineSourceLoc.h @@ -21,7 +21,7 @@ namespace clang { -/// \brief A source location that has been parsed on the command line. +/// A source location that has been parsed on the command line. struct ParsedSourceLocation { std::string FileName; unsigned Line; @@ -101,7 +101,7 @@ struct ParsedSourceRange { namespace llvm { namespace cl { - /// \brief Command-line option parser that parses source locations. + /// Command-line option parser that parses source locations. /// /// Source locations are of the form filename:line:column. template<> diff --git a/include/clang/Frontend/CompilerInstance.h b/include/clang/Frontend/CompilerInstance.h index 90a9501475b52..977d1b2ed65f5 100644 --- a/include/clang/Frontend/CompilerInstance.h +++ b/include/clang/Frontend/CompilerInstance.h @@ -109,59 +109,59 @@ class CompilerInstance : public ModuleLoader { /// The code completion consumer. std::unique_ptr<CodeCompleteConsumer> CompletionConsumer; - /// \brief The semantic analysis object. + /// The semantic analysis object. std::unique_ptr<Sema> TheSema; - /// \brief The frontend timer group. + /// The frontend timer group. std::unique_ptr<llvm::TimerGroup> FrontendTimerGroup; - /// \brief The frontend timer. + /// The frontend timer. std::unique_ptr<llvm::Timer> FrontendTimer; - /// \brief The ASTReader, if one exists. + /// The ASTReader, if one exists. IntrusiveRefCntPtr<ASTReader> ModuleManager; - /// \brief The module dependency collector for crashdumps + /// The module dependency collector for crashdumps std::shared_ptr<ModuleDependencyCollector> ModuleDepCollector; - /// \brief The module provider. + /// The module provider. std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations; - /// \brief The dependency file generator. + /// The dependency file generator. std::unique_ptr<DependencyFileGenerator> TheDependencyFileGenerator; std::vector<std::shared_ptr<DependencyCollector>> DependencyCollectors; - /// \brief The set of top-level modules that has already been loaded, + /// The set of top-level modules that has already been loaded, /// along with the module map llvm::DenseMap<const IdentifierInfo *, Module *> KnownModules; - /// \brief The set of top-level modules that has already been built on the + /// The set of top-level modules that has already been built on the /// fly as part of this overall compilation action. std::map<std::string, std::string> BuiltModules; /// Should we delete the BuiltModules when we're done? bool DeleteBuiltModules = true; - /// \brief The location of the module-import keyword for the last module + /// The location of the module-import keyword for the last module /// import. SourceLocation LastModuleImportLoc; - /// \brief The result of the last module import. + /// The result of the last module import. /// ModuleLoadResult LastModuleImportResult; - /// \brief Whether we should (re)build the global module index once we + /// Whether we should (re)build the global module index once we /// have finished with this translation unit. bool BuildGlobalModuleIndex = false; - /// \brief We have a full global module index, with all modules. + /// We have a full global module index, with all modules. bool HaveFullGlobalModuleIndex = false; - /// \brief One or more modules failed to build. + /// One or more modules failed to build. bool ModuleBuildFailed = false; - /// \brief Holds information about the output file. + /// Holds information about the output file. /// /// If TempFilename is not empty we must rename it to Filename at the end. /// TempFilename may be empty and Filename non-empty if creating the temporary @@ -183,6 +183,9 @@ class CompilerInstance : public ModuleLoader { /// The list of active output files. std::list<OutputFile> OutputFiles; + /// Force an output buffer. + std::unique_ptr<llvm::raw_pwrite_stream> OutputStream; + CompilerInstance(const CompilerInstance &) = delete; void operator=(const CompilerInstance &) = delete; public: @@ -241,10 +244,10 @@ public: /// setInvocation - Replace the current invocation. void setInvocation(std::shared_ptr<CompilerInvocation> Value); - /// \brief Indicates whether we should (re)build the global module index. + /// Indicates whether we should (re)build the global module index. bool shouldBuildGlobalModuleIndex() const; - /// \brief Set the flag indicating whether we should (re)build the global + /// Set the flag indicating whether we should (re)build the global /// module index. void setBuildGlobalModuleIndex(bool Build) { BuildGlobalModuleIndex = Build; @@ -387,7 +390,7 @@ public: return *VirtualFileSystem; } - /// \brief Replace the current virtual file system. + /// Replace the current virtual file system. /// /// \note Most clients should use setFileManager, which will implicitly reset /// the virtual file system to the one contained in the file manager. @@ -412,7 +415,7 @@ public: FileMgr.resetWithoutRelease(); } - /// \brief Replace the current file manager and virtual file system. + /// Replace the current file manager and virtual file system. void setFileManager(FileManager *Value); /// } @@ -475,7 +478,7 @@ public: /// setASTContext - Replace the current AST context. void setASTContext(ASTContext *Value); - /// \brief Replace the current Sema; the compiler instance takes ownership + /// Replace the current Sema; the compiler instance takes ownership /// of S. void setSema(Sema *S); @@ -687,7 +690,7 @@ public: Preprocessor &PP, StringRef Filename, unsigned Line, unsigned Column, const CodeCompleteOptions &Opts, raw_ostream &OS); - /// \brief Create the Sema object to be used for parsing. + /// Create the Sema object to be used for parsing. void createSema(TranslationUnitKind TUKind, CodeCompleteConsumer *CompletionConsumer); @@ -773,6 +776,14 @@ public: /// } + void setOutputStream(std::unique_ptr<llvm::raw_pwrite_stream> OutStream) { + OutputStream = std::move(OutStream); + } + + std::unique_ptr<llvm::raw_pwrite_stream> takeOutputStream() { + return std::move(OutputStream); + } + // Create module manager. void createModuleManager(); diff --git a/include/clang/Frontend/CompilerInvocation.h b/include/clang/Frontend/CompilerInvocation.h index 8c4c932190bc3..3d302051d2988 100644 --- a/include/clang/Frontend/CompilerInvocation.h +++ b/include/clang/Frontend/CompilerInvocation.h @@ -1,4 +1,4 @@ -//===-- CompilerInvocation.h - Compiler Invocation Helper Data --*- C++ -*-===// +//===- CompilerInvocation.h - Compiler Invocation Helper Data ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,11 +7,12 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ -#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H_ +#ifndef LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H +#define LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H #include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/FileSystemOptions.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" #include "clang/Frontend/CodeGenOptions.h" #include "clang/Frontend/DependencyOutputOptions.h" @@ -21,25 +22,29 @@ #include "clang/Frontend/PreprocessorOutputOptions.h" #include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include <memory> #include <string> namespace llvm { + class Triple; namespace opt { + class ArgList; -} -} + +} // namespace opt + +} // namespace llvm namespace clang { -class PreprocessorOptions; + +class DiagnosticsEngine; class HeaderSearchOptions; +class PreprocessorOptions; class TargetOptions; -class LangOptions; -class CompilerInvocation; -class DiagnosticsEngine; -/// \brief Fill out Opts based on the options given in Args. +/// Fill out Opts based on the options given in Args. /// /// Args must have been created from the OptTable returned by /// createCC1OptTable(). @@ -52,8 +57,6 @@ bool ParseDiagnosticArgs(DiagnosticOptions &Opts, llvm::opt::ArgList &Args, bool DefaultShowOpt = true); class CompilerInvocationBase { - void operator=(const CompilerInvocationBase &) = delete; - public: /// Options controlling the language variant. std::shared_ptr<LangOptions> LangOpts; @@ -71,24 +74,24 @@ public: std::shared_ptr<PreprocessorOptions> PreprocessorOpts; CompilerInvocationBase(); - ~CompilerInvocationBase(); - CompilerInvocationBase(const CompilerInvocationBase &X); + CompilerInvocationBase &operator=(const CompilerInvocationBase &) = delete; + ~CompilerInvocationBase(); LangOptions *getLangOpts() { return LangOpts.get(); } const LangOptions *getLangOpts() const { return LangOpts.get(); } TargetOptions &getTargetOpts() { return *TargetOpts.get(); } - const TargetOptions &getTargetOpts() const { - return *TargetOpts.get(); - } + const TargetOptions &getTargetOpts() const { return *TargetOpts.get(); } DiagnosticOptions &getDiagnosticOpts() const { return *DiagnosticOpts; } HeaderSearchOptions &getHeaderSearchOpts() { return *HeaderSearchOpts; } + const HeaderSearchOptions &getHeaderSearchOpts() const { return *HeaderSearchOpts; } + std::shared_ptr<HeaderSearchOptions> getHeaderSearchOptsPtr() const { return HeaderSearchOpts; } @@ -96,13 +99,15 @@ public: std::shared_ptr<PreprocessorOptions> getPreprocessorOptsPtr() { return PreprocessorOpts; } + PreprocessorOptions &getPreprocessorOpts() { return *PreprocessorOpts; } + const PreprocessorOptions &getPreprocessorOpts() const { return *PreprocessorOpts; } }; -/// \brief Helper class for holding the data necessary to invoke the compiler. +/// Helper class for holding the data necessary to invoke the compiler. /// /// This class is designed to represent an abstract "invocation" of the /// compiler, including data such as the include paths, the code generation @@ -134,7 +139,7 @@ public: /// @name Utility Methods /// @{ - /// \brief Create a compiler invocation from a list of input options. + /// Create a compiler invocation from a list of input options. /// \returns true on success. /// /// \param [out] Res - The resulting invocation. @@ -146,7 +151,7 @@ public: const char* const *ArgEnd, DiagnosticsEngine &Diags); - /// \brief Get the directory where the compiler headers + /// Get the directory where the compiler headers /// reside, relative to the compiler binary (found by the passed in /// arguments). /// @@ -156,7 +161,7 @@ public: /// executable), for finding the builtin compiler path. static std::string GetResourcesPath(const char *Argv0, void *MainAddr); - /// \brief Set language defaults for the given input language and + /// Set language defaults for the given input language and /// language standard in the given LangOptions object. /// /// \param Opts - The LangOptions object to set up. @@ -168,7 +173,7 @@ public: const llvm::Triple &T, PreprocessorOptions &PPOpts, LangStandard::Kind LangStd = LangStandard::lang_unspecified); - /// \brief Retrieve a module hash string that is suitable for uniquely + /// Retrieve a module hash string that is suitable for uniquely /// identifying the conditions under which the module was built. std::string getModuleHash() const; @@ -176,40 +181,35 @@ public: /// @name Option Subgroups /// @{ - AnalyzerOptionsRef getAnalyzerOpts() const { - return AnalyzerOpts; - } + AnalyzerOptionsRef getAnalyzerOpts() const { return AnalyzerOpts; } MigratorOptions &getMigratorOpts() { return MigratorOpts; } - const MigratorOptions &getMigratorOpts() const { - return MigratorOpts; - } + const MigratorOptions &getMigratorOpts() const { return MigratorOpts; } CodeGenOptions &getCodeGenOpts() { return CodeGenOpts; } - const CodeGenOptions &getCodeGenOpts() const { - return CodeGenOpts; - } + const CodeGenOptions &getCodeGenOpts() const { return CodeGenOpts; } DependencyOutputOptions &getDependencyOutputOpts() { return DependencyOutputOpts; } + const DependencyOutputOptions &getDependencyOutputOpts() const { return DependencyOutputOpts; } FileSystemOptions &getFileSystemOpts() { return FileSystemOpts; } + const FileSystemOptions &getFileSystemOpts() const { return FileSystemOpts; } FrontendOptions &getFrontendOpts() { return FrontendOpts; } - const FrontendOptions &getFrontendOpts() const { - return FrontendOpts; - } + const FrontendOptions &getFrontendOpts() const { return FrontendOpts; } PreprocessorOutputOptions &getPreprocessorOutputOpts() { return PreprocessorOutputOpts; } + const PreprocessorOutputOptions &getPreprocessorOutputOpts() const { return PreprocessorOutputOpts; } @@ -218,8 +218,10 @@ public: }; namespace vfs { - class FileSystem; -} + +class FileSystem; + +} // namespace vfs IntrusiveRefCntPtr<vfs::FileSystem> createVFSFromCompilerInvocation(const CompilerInvocation &CI, @@ -230,6 +232,6 @@ createVFSFromCompilerInvocation(const CompilerInvocation &CI, DiagnosticsEngine &Diags, IntrusiveRefCntPtr<vfs::FileSystem> BaseFS); -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_COMPILERINVOCATION_H diff --git a/include/clang/Frontend/DependencyOutputOptions.h b/include/clang/Frontend/DependencyOutputOptions.h index 0be36cd9aa6ea..f419d2643649d 100644 --- a/include/clang/Frontend/DependencyOutputOptions.h +++ b/include/clang/Frontend/DependencyOutputOptions.h @@ -15,6 +15,9 @@ namespace clang { +/// ShowIncludesDestination - Destination for /showIncludes output. +enum class ShowIncludesDestination { None, Stdout, Stderr }; + /// DependencyOutputFormat - Format for the compiler dependency file. enum class DependencyOutputFormat { Make, NMake }; @@ -28,11 +31,13 @@ public: /// dependency, which can avoid some 'make' /// problems. unsigned AddMissingHeaderDeps : 1; ///< Add missing headers to dependency list - unsigned PrintShowIncludes : 1; ///< Print cl.exe style /showIncludes info. unsigned IncludeModuleFiles : 1; ///< Include module file dependencies. + /// Destination of cl.exe style /showIncludes info. + ShowIncludesDestination ShowIncludesDest = ShowIncludesDestination::None; + /// The format for the dependency file. - DependencyOutputFormat OutputFormat; + DependencyOutputFormat OutputFormat = DependencyOutputFormat::Make; /// The file to write dependency output to. std::string OutputFile; @@ -53,22 +58,16 @@ public: /// In /showIncludes mode, pretend the main TU is a header with this name. std::string ShowIncludesPretendHeader; - /// \brief The file to write GraphViz-formatted header dependencies to. + /// The file to write GraphViz-formatted header dependencies to. std::string DOTOutputFile; - /// \brief The directory to copy module dependencies to when collecting them. + /// The directory to copy module dependencies to when collecting them. std::string ModuleDependencyOutputDir; public: - DependencyOutputOptions() { - IncludeSystemHeaders = 0; - ShowHeaderIncludes = 0; - UsePhonyTargets = 0; - AddMissingHeaderDeps = 0; - PrintShowIncludes = 0; - IncludeModuleFiles = 0; - OutputFormat = DependencyOutputFormat::Make; - } + DependencyOutputOptions() + : IncludeSystemHeaders(0), ShowHeaderIncludes(0), UsePhonyTargets(0), + AddMissingHeaderDeps(0), IncludeModuleFiles(0) {} }; } // end namespace clang diff --git a/include/clang/Frontend/DiagnosticRenderer.h b/include/clang/Frontend/DiagnosticRenderer.h index e453d7db624c2..191d32accf2ff 100644 --- a/include/clang/Frontend/DiagnosticRenderer.h +++ b/include/clang/Frontend/DiagnosticRenderer.h @@ -1,4 +1,4 @@ -//===--- DiagnosticRenderer.h - Diagnostic Pretty-Printing ------*- C++ -*-===// +//===- DiagnosticRenderer.h - Diagnostic Pretty-Printing --------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,20 +17,23 @@ #define LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/DiagnosticOptions.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/StringRef.h" namespace clang { -class DiagnosticOptions; class LangOptions; class SourceManager; -typedef llvm::PointerUnion<const Diagnostic *, - const StoredDiagnostic *> DiagOrStoredDiag; +using DiagOrStoredDiag = + llvm::PointerUnion<const Diagnostic *, const StoredDiagnostic *>; -/// \brief Class to encapsulate the logic for formatting a diagnostic message. +/// Class to encapsulate the logic for formatting a diagnostic message. /// /// Actual "printing" logic is implemented by subclasses. /// @@ -47,24 +50,24 @@ protected: const LangOptions &LangOpts; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; - /// \brief The location of the previous diagnostic if known. + /// The location of the previous diagnostic if known. /// /// This will be invalid in cases where there is no (known) previous /// diagnostic location, or that location itself is invalid or comes from /// a different source manager than SM. SourceLocation LastLoc; - /// \brief The location of the last include whose stack was printed if known. + /// The location of the last include whose stack was printed if known. /// /// Same restriction as LastLoc essentially, but tracking include stack /// root locations rather than diagnostic locations. SourceLocation LastIncludeLoc; - /// \brief The level of the last diagnostic emitted. + /// The level of the last diagnostic emitted. /// /// The level of the last diagnostic emitted. Used to detect level changes /// which change the amount of information displayed. - DiagnosticsEngine::Level LastLevel; + DiagnosticsEngine::Level LastLevel = DiagnosticsEngine::Ignored; DiagnosticRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts); @@ -97,7 +100,6 @@ protected: virtual void endDiagnostic(DiagOrStoredDiag D, DiagnosticsEngine::Level Level) {} - private: void emitBasicNote(StringRef Message); void emitIncludeStack(FullSourceLoc Loc, PresumedLoc PLoc, @@ -116,7 +118,7 @@ private: ArrayRef<FixItHint> Hints); public: - /// \brief Emit a diagnostic. + /// Emit a diagnostic. /// /// This is the primary entry point for emitting diagnostic messages. /// It handles formatting and rendering the message as well as any ancillary @@ -142,7 +144,7 @@ class DiagnosticNoteRenderer : public DiagnosticRenderer { public: DiagnosticNoteRenderer(const LangOptions &LangOpts, DiagnosticOptions *DiagOpts) - : DiagnosticRenderer(LangOpts, DiagOpts) {} + : DiagnosticRenderer(LangOpts, DiagOpts) {} ~DiagnosticNoteRenderer() override; @@ -156,5 +158,7 @@ public: virtual void emitNote(FullSourceLoc Loc, StringRef Message) = 0; }; -} // end clang namespace -#endif + +} // namespace clang + +#endif // LLVM_CLANG_FRONTEND_DIAGNOSTICRENDERER_H diff --git a/include/clang/Frontend/FrontendAction.h b/include/clang/Frontend/FrontendAction.h index 7ae6173512a68..2a4077d34391e 100644 --- a/include/clang/Frontend/FrontendAction.h +++ b/include/clang/Frontend/FrontendAction.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the clang::FrontendAction interface and various convenience +/// Defines the clang::FrontendAction interface and various convenience /// abstract classes (clang::ASTFrontendAction, clang::PluginASTAction, /// clang::PreprocessorFrontendAction, and clang::WrapperFrontendAction) /// derived from it. @@ -48,7 +48,7 @@ protected: /// @name Implementation Action Interface /// @{ - /// \brief Create the AST consumer object for this action, if supported. + /// Create the AST consumer object for this action, if supported. /// /// This routine is called as part of BeginSourceFile(), which will /// fail if the AST consumer cannot be created. This will not be called if the @@ -64,7 +64,7 @@ protected: virtual std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) = 0; - /// \brief Callback before starting processing a single input, giving the + /// Callback before starting processing a single input, giving the /// opportunity to modify the CompilerInvocation or do some other action /// before BeginSourceFileAction is called. /// @@ -72,7 +72,7 @@ protected: /// ExecuteAction() and EndSourceFileAction() will not be called. virtual bool BeginInvocation(CompilerInstance &CI) { return true; } - /// \brief Callback at the start of processing a single input. + /// Callback at the start of processing a single input. /// /// \return True on success; on failure ExecutionAction() and /// EndSourceFileAction() will not be called. @@ -80,20 +80,20 @@ protected: return true; } - /// \brief Callback to run the program action, using the initialized + /// Callback to run the program action, using the initialized /// compiler instance. /// /// This is guaranteed to only be called between BeginSourceFileAction() /// and EndSourceFileAction(). virtual void ExecuteAction() = 0; - /// \brief Callback at the end of processing a single input. + /// Callback at the end of processing a single input. /// /// This is guaranteed to only be called following a successful call to /// BeginSourceFileAction (and BeginSourceFile). virtual void EndSourceFileAction() {} - /// \brief Callback at the end of processing a single input, to determine + /// Callback at the end of processing a single input, to determine /// if the output files should be erased or not. /// /// By default it returns true if a compiler error occurred. @@ -158,39 +158,39 @@ public: /// @name Supported Modes /// @{ - /// \brief Is this action invoked on a model file? + /// 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? + /// Does this action only use the preprocessor? /// /// If so no AST context will be created and this action will be invalid /// with AST file inputs. virtual bool usesPreprocessorOnly() const = 0; - /// \brief For AST-based actions, the kind of translation unit we're handling. + /// For AST-based actions, the kind of translation unit we're handling. virtual TranslationUnitKind getTranslationUnitKind() { return TU_Complete; } - /// \brief Does this action support use with PCH? + /// Does this action support use with PCH? virtual bool hasPCHSupport() const { return true; } - /// \brief Does this action support use with AST files? + /// Does this action support use with AST files? virtual bool hasASTFileSupport() const { return true; } - /// \brief Does this action support use with IR files? + /// Does this action support use with IR files? virtual bool hasIRSupport() const { return false; } - /// \brief Does this action support use with code completion? + /// Does this action support use with code completion? virtual bool hasCodeCompletionSupport() const { return false; } /// @} /// @name Public Action Interface /// @{ - /// \brief Prepare the action for processing the input file \p Input. + /// Prepare the action for processing the input file \p Input. /// /// This is run after the options and frontend have been initialized, /// but prior to executing any per-file processing. @@ -211,20 +211,20 @@ public: /// be aborted and neither Execute() nor EndSourceFile() should be called. bool BeginSourceFile(CompilerInstance &CI, const FrontendInputFile &Input); - /// \brief Set the source manager's main input file, and run the action. + /// Set the source manager's main input file, and run the action. bool Execute(); - /// \brief Perform any per-file post processing, deallocate per-file + /// Perform any per-file post processing, deallocate per-file /// objects, and run statistics and output file cleanup code. void EndSourceFile(); /// @} }; -/// \brief Abstract base class to use for AST consumer-based frontend actions. +/// Abstract base class to use for AST consumer-based frontend actions. class ASTFrontendAction : public FrontendAction { protected: - /// \brief Implement the ExecuteAction interface by running Sema on + /// Implement the ExecuteAction interface by running Sema on /// the already-initialized AST consumer. /// /// This will also take care of instantiating a code completion consumer if @@ -242,7 +242,7 @@ public: std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override = 0; - /// \brief Parse the given plugin command line arguments. + /// Parse the given plugin command line arguments. /// /// \param CI - The compiler instance, for use in reporting diagnostics. /// \return True if the parsing succeeded; otherwise the plugin will be @@ -257,7 +257,7 @@ public: AddBeforeMainAction, ///< Execute the action before the main action AddAfterMainAction ///< Execute the action after the main action }; - /// \brief Get the action type for this plugin + /// Get the action type for this plugin /// /// \return The action type. If the type is Cmdline then by default the /// plugin does nothing and what it does is determined by the cc1 @@ -265,10 +265,10 @@ public: virtual ActionType getActionType() { return Cmdline; } }; -/// \brief Abstract base class to use for preprocessor-based frontend actions. +/// Abstract base class to use for preprocessor-based frontend actions. class PreprocessorFrontendAction : public FrontendAction { protected: - /// \brief Provide a default implementation which returns aborts; + /// Provide a default implementation which returns aborts; /// this method should never be called by FrontendAction clients. std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, StringRef InFile) override; @@ -277,7 +277,7 @@ public: bool usesPreprocessorOnly() const override { return true; } }; -/// \brief A frontend action which simply wraps some other runtime-specified +/// A frontend action which simply wraps some other runtime-specified /// frontend action. /// /// Deriving from this class allows an action to inject custom logic around diff --git a/include/clang/Frontend/FrontendActions.h b/include/clang/Frontend/FrontendActions.h index fa1529a3d65dc..20f1b3e11bdb7 100644 --- a/include/clang/Frontend/FrontendActions.h +++ b/include/clang/Frontend/FrontendActions.h @@ -35,6 +35,18 @@ public: bool usesPreprocessorOnly() const override { return false; } }; +class DumpCompilerOptionsAction : public FrontendAction { + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override { + return nullptr; + } + + void ExecuteAction() override; + +public: + bool usesPreprocessorOnly() const override { return true; } +}; + //===----------------------------------------------------------------------===// // AST Consumer Actions //===----------------------------------------------------------------------===// @@ -83,14 +95,14 @@ protected: bool shouldEraseOutputFiles() override; public: - /// \brief Compute the AST consumer arguments that will be used to + /// Compute the AST consumer arguments that will be used to /// create the PCHGenerator instance returned by CreateASTConsumer. /// /// \returns false if an error occurred, true otherwise. static bool ComputeASTConsumerArguments(CompilerInstance &CI, std::string &Sysroot); - /// \brief Creates file to write the PCH into and returns a stream to write it + /// Creates file to write the PCH into and returns a stream to write it /// into. On error, returns null. static std::unique_ptr<llvm::raw_pwrite_stream> CreateOutputFile(CompilerInstance &CI, StringRef InFile, @@ -140,7 +152,7 @@ public: bool hasCodeCompletionSupport() const override { return true; } }; -/// \brief Dump information about the given module file, to be used for +/// Dump information about the given module file, to be used for /// basic debugging and discovery. class DumpModuleInfoAction : public ASTFrontendAction { protected: @@ -167,8 +179,16 @@ public: bool hasCodeCompletionSupport() const override { return false; } }; +class TemplightDumpAction : public ASTFrontendAction { +protected: + std::unique_ptr<ASTConsumer> CreateASTConsumer(CompilerInstance &CI, + StringRef InFile) override; + + void ExecuteAction() override; +}; + /** - * \brief Frontend action adaptor that merges ASTs together. + * Frontend action adaptor that merges ASTs together. * * This action takes an existing AST file and "merges" it into the AST * context, producing a merged context. This action is an action @@ -176,10 +196,10 @@ public: * will consume the merged context. */ class ASTMergeAction : public FrontendAction { - /// \brief The action that the merge action adapts. + /// The action that the merge action adapts. std::unique_ptr<FrontendAction> AdaptedAction; - /// \brief The set of AST files to merge. + /// The set of AST files to merge. std::vector<std::string> ASTFiles; protected: diff --git a/include/clang/Frontend/FrontendOptions.h b/include/clang/Frontend/FrontendOptions.h index 5192a3774cc1d..668df83274eb5 100644 --- a/include/clang/Frontend/FrontendOptions.h +++ b/include/clang/Frontend/FrontendOptions.h @@ -1,4 +1,4 @@ -//===--- FrontendOptions.h --------------------------------------*- C++ -*-===// +//===- FrontendOptions.h ----------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,54 +14,127 @@ #include "clang/Serialization/ModuleFileExtension.h" #include "clang/Sema/CodeCompleteOptions.h" #include "llvm/ADT/StringRef.h" +#include <cassert> +#include <memory> #include <string> #include <vector> #include <unordered_map> namespace llvm { + class MemoryBuffer; -} + +} // namespace llvm namespace clang { -class FileEntry; namespace frontend { - enum ActionKind { - ASTDeclList, ///< Parse ASTs and list Decl nodes. - ASTDump, ///< Parse ASTs and dump them. - ASTPrint, ///< Parse ASTs and print them. - ASTView, ///< Parse ASTs and view them in Graphviz. - DumpRawTokens, ///< Dump out raw tokens. - DumpTokens, ///< Dump out preprocessed tokens. - EmitAssembly, ///< Emit a .s file. - EmitBC, ///< Emit a .bc file. - EmitHTML, ///< Translate input source into HTML. - EmitLLVM, ///< Emit a .ll file. - EmitLLVMOnly, ///< Generate LLVM IR, but do not emit anything. - EmitCodeGenOnly, ///< Generate machine code, but don't emit anything. - EmitObj, ///< Emit a .o file. - FixIt, ///< Parse and apply any fixits to the source. - GenerateModule, ///< Generate pre-compiled module from a module map. - GenerateModuleInterface,///< Generate pre-compiled module from a C++ module - ///< interface file. - GeneratePCH, ///< Generate pre-compiled header. - GeneratePTH, ///< Generate pre-tokenized header. - InitOnly, ///< Only execute frontend initialization. - ModuleFileInfo, ///< Dump information about a module file. - VerifyPCH, ///< Load and verify that a PCH file is usable. - ParseSyntaxOnly, ///< Parse and perform semantic analysis. - PluginAction, ///< Run a plugin action, \see ActionName. - PrintDeclContext, ///< Print DeclContext and their Decls. - PrintPreamble, ///< Print the "preamble" of the input file - PrintPreprocessedInput, ///< -E mode. - RewriteMacros, ///< Expand macros but not \#includes. - RewriteObjC, ///< ObjC->C Rewriter. - RewriteTest, ///< Rewriter playground - RunAnalysis, ///< Run one or more source code analyses. - MigrateSource, ///< Run migrator. - RunPreprocessorOnly ///< Just lex, no output. - }; -} + +enum ActionKind { + /// Parse ASTs and list Decl nodes. + ASTDeclList, + + /// Parse ASTs and dump them. + ASTDump, + + /// Parse ASTs and print them. + ASTPrint, + + /// Parse ASTs and view them in Graphviz. + ASTView, + + /// Dump the compiler configuration. + DumpCompilerOptions, + + /// Dump out raw tokens. + DumpRawTokens, + + /// Dump out preprocessed tokens. + DumpTokens, + + /// Emit a .s file. + EmitAssembly, + + /// Emit a .bc file. + EmitBC, + + /// Translate input source into HTML. + EmitHTML, + + /// Emit a .ll file. + EmitLLVM, + + /// Generate LLVM IR, but do not emit anything. + EmitLLVMOnly, + + /// Generate machine code, but don't emit anything. + EmitCodeGenOnly, + + /// Emit a .o file. + EmitObj, + + /// Parse and apply any fixits to the source. + FixIt, + + /// Generate pre-compiled module from a module map. + GenerateModule, + + /// Generate pre-compiled module from a C++ module interface file. + GenerateModuleInterface, + + /// Generate pre-compiled header. + GeneratePCH, + + /// Generate pre-tokenized header. + GeneratePTH, + + /// Only execute frontend initialization. + InitOnly, + + /// Dump information about a module file. + ModuleFileInfo, + + /// Load and verify that a PCH file is usable. + VerifyPCH, + + /// Parse and perform semantic analysis. + ParseSyntaxOnly, + + /// Run a plugin action, \see ActionName. + PluginAction, + + /// Print DeclContext and their Decls. + PrintDeclContext, + + /// Print the "preamble" of the input file + PrintPreamble, + + /// -E mode. + PrintPreprocessedInput, + + /// Expand macros but not \#includes. + RewriteMacros, + + /// ObjC->C Rewriter. + RewriteObjC, + + /// Rewriter playground + RewriteTest, + + /// Run one or more source code analyses. + RunAnalysis, + + /// Dump template instantiations + TemplightDump, + + /// Run migrator. + MigrateSource, + + /// Just lex, no output. + RunPreprocessorOnly +}; + +} // namespace frontend /// The kind of a file that we've been handed as an input. class InputKind { @@ -91,6 +164,7 @@ public: OpenCL, CUDA, RenderScript, + HIP, ///@} }; @@ -118,14 +192,15 @@ public: InputKind getPreprocessed() const { return InputKind(getLanguage(), getFormat(), true); } + InputKind withFormat(Format F) const { return InputKind(getLanguage(), F, isPreprocessed()); } }; -/// \brief An input file for the front end. +/// An input file for the front end. class FrontendInputFile { - /// \brief The file name, or "-" to read from standard input. + /// The file name, or "-" to read from standard input. std::string File; /// The input, if it comes from a buffer rather than a file. This object @@ -133,19 +208,19 @@ class FrontendInputFile { /// that it outlives any users. llvm::MemoryBuffer *Buffer = nullptr; - /// \brief The kind of input, e.g., C source, AST file, LLVM IR. + /// The kind of input, e.g., C source, AST file, LLVM IR. InputKind Kind; - /// \brief Whether we're dealing with a 'system' input (vs. a 'user' input). + /// Whether we're dealing with a 'system' input (vs. a 'user' input). bool IsSystem = false; public: - FrontendInputFile() { } + FrontendInputFile() = default; FrontendInputFile(StringRef File, InputKind Kind, bool IsSystem = false) - : File(File.str()), Kind(Kind), IsSystem(IsSystem) { } + : File(File.str()), Kind(Kind), IsSystem(IsSystem) {} FrontendInputFile(llvm::MemoryBuffer *Buffer, InputKind Kind, bool IsSystem = false) - : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) { } + : Buffer(Buffer), Kind(Kind), IsSystem(IsSystem) {} InputKind getKind() const { return Kind; } bool isSystem() const { return IsSystem; } @@ -159,6 +234,7 @@ public: assert(isFile()); return File; } + llvm::MemoryBuffer *getBuffer() const { assert(isBuffer()); return Buffer; @@ -168,43 +244,67 @@ public: /// FrontendOptions - Options for controlling the behavior of the frontend. class FrontendOptions { public: - unsigned DisableFree : 1; ///< Disable memory freeing on exit. - unsigned RelocatablePCH : 1; ///< When generating PCH files, - /// instruct the AST writer to create - /// relocatable PCH files. - unsigned ShowHelp : 1; ///< Show the -help text. - unsigned ShowStats : 1; ///< Show frontend performance - /// metrics and statistics. - unsigned ShowTimers : 1; ///< Show timers for individual - /// actions. - unsigned ShowVersion : 1; ///< Show the -version text. - unsigned FixWhatYouCan : 1; ///< Apply fixes even if there are - /// unfixable errors. - unsigned FixOnlyWarnings : 1; ///< Apply fixes only for warnings. - unsigned FixAndRecompile : 1; ///< Apply fixes and recompile. - unsigned FixToTemporaries : 1; ///< Apply fixes to temporary files. - unsigned ARCMTMigrateEmitARCErrors : 1; /// Emit ARC errors even if the - /// migrator can fix them - unsigned SkipFunctionBodies : 1; ///< Skip over function bodies to - /// speed up parsing in cases you do - /// not need them (e.g. with code - /// completion). - unsigned UseGlobalModuleIndex : 1; ///< Whether we can use the - ///< 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 ASTDumpAll : 1; ///< Whether we deserialize all decls - ///< when forming AST dumps. - unsigned ASTDumpLookups : 1; ///< Whether we include lookup table - ///< dumps in AST dumps. - unsigned BuildingImplicitModule : 1; ///< Whether we are performing an - ///< implicit module build. - unsigned ModulesEmbedAllFiles : 1; ///< Whether we should embed all used - ///< files into the PCM file. - unsigned IncludeTimestamps : 1; ///< Whether timestamps should be - ///< written to the produced PCH file. + /// Disable memory freeing on exit. + unsigned DisableFree : 1; + + /// When generating PCH files, instruct the AST writer to create relocatable + /// PCH files. + unsigned RelocatablePCH : 1; + + /// Show the -help text. + unsigned ShowHelp : 1; + + /// Show frontend performance metrics and statistics. + unsigned ShowStats : 1; + + /// Show timers for individual actions. + unsigned ShowTimers : 1; + + /// Show the -version text. + unsigned ShowVersion : 1; + + /// Apply fixes even if there are unfixable errors. + unsigned FixWhatYouCan : 1; + + /// Apply fixes only for warnings. + unsigned FixOnlyWarnings : 1; + + /// Apply fixes and recompile. + unsigned FixAndRecompile : 1; + + /// Apply fixes to temporary files. + unsigned FixToTemporaries : 1; + + /// Emit ARC errors even if the migrator can fix them. + unsigned ARCMTMigrateEmitARCErrors : 1; + + /// Skip over function bodies to speed up parsing in cases you do not need + /// them (e.g. with code completion). + unsigned SkipFunctionBodies : 1; + + /// Whether we can use the global module index if available. + unsigned UseGlobalModuleIndex : 1; + + /// Whether we can generate the global module index if needed. + unsigned GenerateGlobalModuleIndex : 1; + + /// Whether we include declaration dumps in AST dumps. + unsigned ASTDumpDecls : 1; + + /// Whether we deserialize all decls when forming AST dumps. + unsigned ASTDumpAll : 1; + + /// Whether we include lookup table dumps in AST dumps. + unsigned ASTDumpLookups : 1; + + /// Whether we are performing an implicit module build. + unsigned BuildingImplicitModule : 1; + + /// Whether we should embed all used files into the PCM file. + unsigned ModulesEmbedAllFiles : 1; + + /// Whether timestamps should be written to the produced PCH file. + unsigned IncludeTimestamps : 1; CodeCompleteOptions CodeCompleteOpts; @@ -213,38 +313,53 @@ public: ARCMT_Check, ARCMT_Modify, ARCMT_Migrate - } ARCMTAction; + } ARCMTAction = ARCMT_None; enum { ObjCMT_None = 0, - /// \brief Enable migration to modern ObjC literals. + + /// Enable migration to modern ObjC literals. ObjCMT_Literals = 0x1, - /// \brief Enable migration to modern ObjC subscripting. + + /// Enable migration to modern ObjC subscripting. ObjCMT_Subscripting = 0x2, - /// \brief Enable migration to modern ObjC readonly property. + + /// Enable migration to modern ObjC readonly property. ObjCMT_ReadonlyProperty = 0x4, - /// \brief Enable migration to modern ObjC readwrite property. + + /// Enable migration to modern ObjC readwrite property. ObjCMT_ReadwriteProperty = 0x8, - /// \brief Enable migration to modern ObjC property. + + /// Enable migration to modern ObjC property. ObjCMT_Property = (ObjCMT_ReadonlyProperty | ObjCMT_ReadwriteProperty), - /// \brief Enable annotation of ObjCMethods of all kinds. + + /// Enable annotation of ObjCMethods of all kinds. ObjCMT_Annotation = 0x10, - /// \brief Enable migration of ObjC methods to 'instancetype'. + + /// Enable migration of ObjC methods to 'instancetype'. ObjCMT_Instancetype = 0x20, - /// \brief Enable migration to NS_ENUM/NS_OPTIONS macros. + + /// Enable migration to NS_ENUM/NS_OPTIONS macros. ObjCMT_NsMacros = 0x40, - /// \brief Enable migration to add conforming protocols. + + /// Enable migration to add conforming protocols. ObjCMT_ProtocolConformance = 0x80, - /// \brief prefer 'atomic' property over 'nonatomic'. + + /// prefer 'atomic' property over 'nonatomic'. ObjCMT_AtomicProperty = 0x100, - /// \brief annotate property with NS_RETURNS_INNER_POINTER + + /// annotate property with NS_RETURNS_INNER_POINTER ObjCMT_ReturnsInnerPointerProperty = 0x200, - /// \brief use NS_NONATOMIC_IOSONLY for property 'atomic' attribute + + /// use NS_NONATOMIC_IOSONLY for property 'atomic' attribute ObjCMT_NsAtomicIOSOnlyProperty = 0x400, - /// \brief Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods. + + /// Enable inferring NS_DESIGNATED_INITIALIZER for ObjC methods. ObjCMT_DesignatedInitializer = 0x800, - /// \brief Enable converting setter/getter expressions to property-dot syntx. + + /// 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 | @@ -253,7 +368,7 @@ public: ObjCMT_MigrateAll = (ObjCMT_Literals | ObjCMT_Subscripting | ObjCMT_MigrateDecls | ObjCMT_PropertyDotSyntax) }; - unsigned ObjCMTAction; + unsigned ObjCMTAction = ObjCMT_None; std::string ObjCMTWhiteListPath; std::string MTMigrateDir; @@ -279,7 +394,7 @@ public: ParsedSourceLocation CodeCompletionAt; /// The frontend action to perform. - frontend::ActionKind ProgramAction; + frontend::ActionKind ProgramAction = frontend::ParseSyntaxOnly; /// The name of the action to run when using a plugin action. std::string ActionName; @@ -296,49 +411,43 @@ public: /// The list of module file extensions. std::vector<std::shared_ptr<ModuleFileExtension>> ModuleFileExtensions; - /// \brief The list of module map files to load before processing the input. + /// 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 + /// The list of additional prebuilt module files to load before /// processing the input. std::vector<std::string> ModuleFiles; - /// \brief The list of files to embed into the compiled module file. + /// The list of files to embed into the compiled module file. std::vector<std::string> ModulesEmbedFiles; - /// \brief The list of AST files to merge. + /// The list of AST files to merge. std::vector<std::string> ASTMergeFiles; - /// \brief A list of arguments to forward to LLVM's option processing; this + /// A list of arguments to forward to LLVM's option processing; this /// should only be used for debugging and experimental features. std::vector<std::string> LLVMArgs; - /// \brief File name of the file that will provide record layouts + /// File name of the file that will provide record layouts /// (in the format produced by -fdump-record-layouts). std::string OverrideRecordLayoutsFile; - /// \brief Auxiliary triple for CUDA compilation. + /// Auxiliary triple for CUDA compilation. std::string AuxTriple; - /// \brief If non-empty, search the pch input file as if it was a header - /// included by this file. - std::string FindPchSource; - /// Filename to write statistics to. std::string StatsFile; public: - FrontendOptions() : - DisableFree(false), RelocatablePCH(false), ShowHelp(false), - ShowStats(false), ShowTimers(false), ShowVersion(false), - FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), - FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), - SkipFunctionBodies(false), UseGlobalModuleIndex(true), - GenerateGlobalModuleIndex(true), ASTDumpDecls(false), ASTDumpLookups(false), - BuildingImplicitModule(false), ModulesEmbedAllFiles(false), - IncludeTimestamps(true), ARCMTAction(ARCMT_None), - ObjCMTAction(ObjCMT_None), ProgramAction(frontend::ParseSyntaxOnly) - {} + FrontendOptions() + : DisableFree(false), RelocatablePCH(false), ShowHelp(false), + ShowStats(false), ShowTimers(false), ShowVersion(false), + FixWhatYouCan(false), FixOnlyWarnings(false), FixAndRecompile(false), + FixToTemporaries(false), ARCMTMigrateEmitARCErrors(false), + SkipFunctionBodies(false), UseGlobalModuleIndex(true), + GenerateGlobalModuleIndex(true), ASTDumpDecls(false), + ASTDumpLookups(false), BuildingImplicitModule(false), + ModulesEmbedAllFiles(false), IncludeTimestamps(true) {} /// getInputKindForExtension - Return the appropriate input kind for a file /// extension. For example, "c" would return InputKind::C. @@ -348,6 +457,6 @@ public: static InputKind getInputKindForExtension(StringRef Extension); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_FRONTENDOPTIONS_H diff --git a/include/clang/Frontend/FrontendPluginRegistry.h b/include/clang/Frontend/FrontendPluginRegistry.h index 9d7ee08d95d4b..9a85e89d905d8 100644 --- a/include/clang/Frontend/FrontendPluginRegistry.h +++ b/include/clang/Frontend/FrontendPluginRegistry.h @@ -1,4 +1,4 @@ -//===-- FrontendAction.h - Pluggable Frontend Action Interface --*- C++ -*-===// +//===- FrontendPluginRegistry.h ---------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,6 +6,10 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// +// +// Pluggable Frontend Action Interface +// +//===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H #define LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H @@ -16,8 +20,8 @@ namespace clang { /// The frontend plugin registry. -typedef llvm::Registry<PluginASTAction> FrontendPluginRegistry; +using FrontendPluginRegistry = llvm::Registry<PluginASTAction>; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_FRONTENDPLUGINREGISTRY_H diff --git a/include/clang/Frontend/LangStandards.def b/include/clang/Frontend/LangStandards.def index e7a081dc2aa76..1e895d785d15c 100644 --- a/include/clang/Frontend/LangStandards.def +++ b/include/clang/Frontend/LangStandards.def @@ -155,6 +155,9 @@ LANGSTANDARD(opencl12, "cl1.2", LANGSTANDARD(opencl20, "cl2.0", OpenCL, "OpenCL 2.0", LineComment | C99 | Digraphs | HexFloat | OpenCL) +LANGSTANDARD(openclcpp, "c++", + OpenCL, "OpenCL C++ 1.0", + LineComment | CPlusPlus | CPlusPlus11 | CPlusPlus14 | Digraphs | OpenCL) LANGSTANDARD_ALIAS_DEPR(opencl10, "CL") LANGSTANDARD_ALIAS_DEPR(opencl11, "CL1.1") @@ -165,6 +168,10 @@ LANGSTANDARD_ALIAS_DEPR(opencl20, "CL2.0") LANGSTANDARD(cuda, "cuda", CUDA, "NVIDIA CUDA(tm)", LineComment | CPlusPlus | Digraphs) +// HIP +LANGSTANDARD(hip, "hip", HIP, "HIP", + LineComment | CPlusPlus | Digraphs) + #undef LANGSTANDARD #undef LANGSTANDARD_ALIAS #undef LANGSTANDARD_ALIAS_DEPR diff --git a/include/clang/Frontend/LayoutOverrideSource.h b/include/clang/Frontend/LayoutOverrideSource.h index 16d032b7dd72c..0b7f7dc7a7d67 100644 --- a/include/clang/Frontend/LayoutOverrideSource.h +++ b/include/clang/Frontend/LayoutOverrideSource.h @@ -1,4 +1,4 @@ -//===--- LayoutOverrideSource.h --Override Record Layouts -----------------===// +//===--- LayoutOverrideSource.h --Override Record Layouts -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,36 +16,36 @@ #include "llvm/ADT/StringRef.h" namespace clang { - /// \brief An external AST source that overrides the layout of + /// An external AST source that overrides the layout of /// a specified set of record types. /// /// This class is used only for testing the ability of external AST sources /// to override the layout of record types. Its input is the output format /// of the command-line argument -fdump-record-layouts. class LayoutOverrideSource : public ExternalASTSource { - /// \brief The layout of a given record. + /// The layout of a given record. struct Layout { - /// \brief The size of the record. + /// The size of the record. uint64_t Size; - /// \brief The alignment of the record. + /// The alignment of the record. uint64_t Align; - /// \brief The offsets of the fields, in source order. + /// The offsets of the fields, in source order. SmallVector<uint64_t, 8> FieldOffsets; }; - /// \brief The set of layouts that will be overridden. + /// The set of layouts that will be overridden. llvm::StringMap<Layout> Layouts; public: - /// \brief Create a new AST source that overrides the layout of some + /// Create a new AST source that overrides the layout of some /// set of record types. /// /// The file is the result of passing -fdump-record-layouts to a file. explicit LayoutOverrideSource(StringRef Filename); - /// \brief If this particular record type has an overridden layout, + /// If this particular record type has an overridden layout, /// return that layout. bool layoutRecordType(const RecordDecl *Record, @@ -55,7 +55,7 @@ namespace clang { llvm::DenseMap<const CXXRecordDecl *, CharUnits> &VirtualBaseOffsets) override; - /// \brief Dump the overridden layouts. + /// Dump the overridden layouts. void dump(); }; } diff --git a/include/clang/Frontend/MultiplexConsumer.h b/include/clang/Frontend/MultiplexConsumer.h index d13565c27bc33..214fefb219cde 100644 --- a/include/clang/Frontend/MultiplexConsumer.h +++ b/include/clang/Frontend/MultiplexConsumer.h @@ -17,13 +17,34 @@ #include "clang/Basic/LLVM.h" #include "clang/Sema/SemaConsumer.h" +#include "clang/Serialization/ASTDeserializationListener.h" #include <memory> #include <vector> namespace clang { class MultiplexASTMutationListener; -class MultiplexASTDeserializationListener; + +// This ASTDeserializationListener forwards its notifications to a set of +// child listeners. +class MultiplexASTDeserializationListener : public ASTDeserializationListener { +public: + // Does NOT take ownership of the elements in L. + MultiplexASTDeserializationListener( + const std::vector<ASTDeserializationListener *> &L); + void ReaderInitialized(ASTReader *Reader) override; + void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) override; + void MacroRead(serialization::MacroID ID, MacroInfo *MI) override; + void TypeRead(serialization::TypeIdx Idx, QualType T) override; + void DeclRead(serialization::DeclID ID, const Decl *D) override; + void SelectorRead(serialization::SelectorID iD, Selector Sel) override; + void MacroDefinitionRead(serialization::PreprocessedEntityID, + MacroDefinitionRecord *MD) override; + void ModuleRead(serialization::SubmoduleID ID, Module *Mod) override; + +private: + std::vector<ASTDeserializationListener *> Listeners; +}; // Has a list of ASTConsumers and calls each of them. Owns its children. class MultiplexConsumer : public SemaConsumer { diff --git a/include/clang/Frontend/PrecompiledPreamble.h b/include/clang/Frontend/PrecompiledPreamble.h index 130fe60704a74..6abdbe3a1e1b1 100644 --- a/include/clang/Frontend/PrecompiledPreamble.h +++ b/include/clang/Frontend/PrecompiledPreamble.h @@ -38,7 +38,7 @@ class CompilerInvocation; class DeclGroupRef; class PCHContainerOperations; -/// \brief Runs lexer to compute suggested preamble bounds. +/// Runs lexer to compute suggested preamble bounds. PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, llvm::MemoryBuffer *Buffer, unsigned MaxLines); @@ -53,7 +53,7 @@ class PrecompiledPreamble { struct PreambleFileHash; public: - /// \brief Try to build PrecompiledPreamble for \p Invocation. See + /// Try to build PrecompiledPreamble for \p Invocation. See /// BuildPreambleError for possible error codes. /// /// \param Invocation Original CompilerInvocation with options to compile the @@ -104,14 +104,22 @@ public: /// Changes options inside \p CI to use PCH from this preamble. Also remaps /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble /// is accessible. - /// For in-memory preambles, PrecompiledPreamble instance continues to own - /// the MemoryBuffer with the Preamble after this method returns. The caller - /// is reponsible for making sure the PrecompiledPreamble instance outlives - /// the compiler run and the AST that will be using the PCH. + /// Requires that CanReuse() is true. + /// For in-memory preambles, PrecompiledPreamble instance continues to own the + /// MemoryBuffer with the Preamble after this method returns. The caller is + /// responsible for making sure the PrecompiledPreamble instance outlives the + /// compiler run and the AST that will be using the PCH. void AddImplicitPreamble(CompilerInvocation &CI, IntrusiveRefCntPtr<vfs::FileSystem> &VFS, llvm::MemoryBuffer *MainFileBuffer) const; + /// Configure \p CI to use this preamble. + /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true. + /// If this preamble does not match the file, it may parse differently. + void OverridePreamble(CompilerInvocation &CI, + IntrusiveRefCntPtr<vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const; + private: PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes, bool PreambleEndsAtStartOfLine, @@ -222,6 +230,12 @@ private: } }; + /// Helper function to set up PCH for the preamble into \p CI and \p VFS to + /// with the specified \p Bounds. + void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI, + IntrusiveRefCntPtr<vfs::FileSystem> &VFS, + llvm::MemoryBuffer *MainFileBuffer) const; + /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p /// Storage is accessible to clang. This method is an implementation detail of /// AddImplicitPreamble. @@ -275,7 +289,6 @@ enum class BuildPreambleError { PreambleIsEmpty = 1, CouldntCreateTempFile, CouldntCreateTargetInfo, - CouldntCreateVFSOverlay, BeginSourceFileFailed, CouldntEmitPCH }; diff --git a/include/clang/Frontend/SerializedDiagnosticPrinter.h b/include/clang/Frontend/SerializedDiagnosticPrinter.h index 4c57e9d404f0f..dc68c32fb15ae 100644 --- a/include/clang/Frontend/SerializedDiagnosticPrinter.h +++ b/include/clang/Frontend/SerializedDiagnosticPrinter.h @@ -1,4 +1,4 @@ -//===--- SerializedDiagnosticPrinter.h - Serializer for diagnostics -------===// +//===--- SerializedDiagnosticPrinter.h - Diagnostics serializer -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,11 +25,11 @@ class DiagnosticOptions; namespace serialized_diags { -/// \brief Returns a DiagnosticConsumer that serializes diagnostics to +/// Returns a DiagnosticConsumer that serializes diagnostics to /// a bitcode file. /// /// The created DiagnosticConsumer is designed for quick and lightweight -/// transfer of of diagnostics to the enclosing build system (e.g., an IDE). +/// transfer of diagnostics to the enclosing build system (e.g., an IDE). /// This allows wrapper tools for Clang to get diagnostics from Clang /// (via libclang) without needing to parse Clang's command line output. /// diff --git a/include/clang/Frontend/SerializedDiagnosticReader.h b/include/clang/Frontend/SerializedDiagnosticReader.h index 07479844d4654..595bdf1f4d7ab 100644 --- a/include/clang/Frontend/SerializedDiagnosticReader.h +++ b/include/clang/Frontend/SerializedDiagnosticReader.h @@ -1,4 +1,4 @@ -//===--- SerializedDiagnosticReader.h - Reads diagnostics -------*- C++ -*-===// +//===- SerializedDiagnosticReader.h - Reads diagnostics ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,12 +7,14 @@ // //===----------------------------------------------------------------------===// -#ifndef LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_ -#define LLVM_CLANG_FRONTEND_SERIALIZED_DIAGNOSTIC_READER_H_ +#ifndef LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H +#define LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H #include "clang/Basic/LLVM.h" #include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/ErrorOr.h" +#include <system_error> namespace clang { namespace serialized_diags { @@ -41,90 +43,97 @@ 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. +/// 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. +/// 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() {} + SerializedDiagnosticReader() = default; + virtual ~SerializedDiagnosticReader() = default; - /// \brief Read the diagnostics in \c File + /// 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. + /// 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. + /// Read a metadata block from \c Stream. std::error_code readMetaBlock(llvm::BitstreamCursor &Stream); - /// \brief Read a diagnostic block from \c Stream. + /// 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. + /// Visit the start of a diagnostic block. + virtual std::error_code visitStartOfDiagnostic() { return {}; } + + /// Visit the end of a diagnostic block. + virtual std::error_code visitEndOfDiagnostic() { return {}; } + + /// 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(); + return {}; } - /// \brief Visit a flag. This associates the flag's \c ID to a \c Name. + + /// 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(); + return {}; } - /// \brief Visit a diagnostic. + + /// Visit a diagnostic. virtual std::error_code visitDiagnosticRecord(unsigned Severity, const Location &Location, unsigned Category, unsigned Flag, StringRef Message) { - return std::error_code(); + return {}; } - /// \brief Visit a filename. This associates the file's \c ID to a \c Name. + + /// 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(); + return {}; } - /// \brief Visit a fixit hint. + + /// Visit a fixit hint. virtual std::error_code visitFixitRecord(const Location &Start, const Location &End, StringRef Text) { - return std::error_code(); + return {}; } - /// \brief Visit a source range. + + /// 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(); + return {}; } + + /// Visit the version of the set of diagnostics. + virtual std::error_code visitVersionRecord(unsigned Version) { return {}; } }; -} // end serialized_diags namespace -} // end clang namespace +} // namespace serialized_diags +} // namespace clang namespace std { + template <> struct is_error_code_enum<clang::serialized_diags::SDError> : std::true_type {}; -} -#endif +} // namespace std + +#endif // LLVM_CLANG_FRONTEND_SERIALIZEDDIAGNOSTICREADER_H diff --git a/include/clang/Frontend/SerializedDiagnostics.h b/include/clang/Frontend/SerializedDiagnostics.h index 2032cd3988dbf..dacbc678b7006 100644 --- a/include/clang/Frontend/SerializedDiagnostics.h +++ b/include/clang/Frontend/SerializedDiagnostics.h @@ -16,11 +16,11 @@ namespace clang { namespace serialized_diags { enum BlockIDs { - /// \brief A top-level block which represents any meta data associated + /// 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 + /// The this block acts as a container for all the information /// for a specific diagnostic. BLOCK_DIAG }; @@ -37,7 +37,7 @@ enum RecordIDs { RECORD_LAST = RECORD_FIXIT }; -/// \brief A stable version of DiagnosticIDs::Level. +/// 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. @@ -50,7 +50,7 @@ enum Level { Remark }; -/// \brief The serialized diagnostics version number. +/// The serialized diagnostics version number. enum { VersionNumber = 2 }; } // end serialized_diags namespace diff --git a/include/clang/Frontend/TextDiagnostic.h b/include/clang/Frontend/TextDiagnostic.h index 1bbfe9fa02e32..9f33b866a1ebe 100644 --- a/include/clang/Frontend/TextDiagnostic.h +++ b/include/clang/Frontend/TextDiagnostic.h @@ -20,7 +20,7 @@ namespace clang { -/// \brief Class to encapsulate the logic for formatting and printing a textual +/// Class to encapsulate the logic for formatting and printing a textual /// diagnostic message. /// /// This class provides an interface for building and emitting a textual @@ -42,7 +42,7 @@ public: ~TextDiagnostic() override; - /// \brief Print the diagonstic level to a raw_ostream. + /// Print the diagonstic level to a raw_ostream. /// /// This is a static helper that handles colorizing the level and formatting /// it into an arbitrary output stream. This is used internally by the @@ -54,7 +54,7 @@ public: bool ShowColors, bool CLFallbackMode = false); - /// \brief Pretty-print a diagnostic message to a raw_ostream. + /// Pretty-print a diagnostic message to a raw_ostream. /// /// This is a static helper to handle the line wrapping, colorizing, and /// rendering of a diagnostic message to a particular ostream. It is diff --git a/include/clang/Frontend/TextDiagnosticBuffer.h b/include/clang/Frontend/TextDiagnosticBuffer.h index 23f168e2232df..2295f9dbf3bfb 100644 --- a/include/clang/Frontend/TextDiagnosticBuffer.h +++ b/include/clang/Frontend/TextDiagnosticBuffer.h @@ -1,4 +1,4 @@ -//===--- TextDiagnosticBuffer.h - Buffer Text Diagnostics -------*- C++ -*-===// +//===- TextDiagnosticBuffer.h - Buffer Text Diagnostics ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,37 +15,41 @@ #define LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include <cstddef> +#include <string> +#include <utility> #include <vector> namespace clang { -class Preprocessor; -class SourceManager; - class TextDiagnosticBuffer : public DiagnosticConsumer { public: - typedef std::vector<std::pair<SourceLocation, std::string> > DiagList; - typedef DiagList::iterator iterator; - typedef DiagList::const_iterator const_iterator; + using DiagList = std::vector<std::pair<SourceLocation, std::string>>; + using iterator = DiagList::iterator; + using const_iterator = DiagList::const_iterator; + private: DiagList Errors, Warnings, Remarks, Notes; + /// All - All diagnostics in the order in which they were generated. That /// order likely doesn't correspond to user input order, but it at least /// keeps notes in the right places. Each pair in the vector is a diagnostic /// level and an index into the corresponding DiagList above. std::vector<std::pair<DiagnosticsEngine::Level, size_t>> All; + public: - const_iterator err_begin() const { return Errors.begin(); } - const_iterator err_end() const { return Errors.end(); } + const_iterator err_begin() const { return Errors.begin(); } + const_iterator err_end() const { return Errors.end(); } const_iterator warn_begin() const { return Warnings.begin(); } - const_iterator warn_end() const { return Warnings.end(); } + const_iterator warn_end() const { return Warnings.end(); } const_iterator remark_begin() const { return Remarks.begin(); } - const_iterator remark_end() const { return Remarks.end(); } + const_iterator remark_end() const { return Remarks.end(); } const_iterator note_begin() const { return Notes.begin(); } - const_iterator note_end() const { return Notes.end(); } + const_iterator note_end() const { return Notes.end(); } void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override; @@ -55,6 +59,6 @@ public: void FlushDiagnostics(DiagnosticsEngine &Diags) const; }; -} // end namspace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_TEXTDIAGNOSTICBUFFER_H diff --git a/include/clang/Frontend/TextDiagnosticPrinter.h b/include/clang/Frontend/TextDiagnosticPrinter.h index 07cee9f8ad8aa..3cb4e02edf0d0 100644 --- a/include/clang/Frontend/TextDiagnosticPrinter.h +++ b/include/clang/Frontend/TextDiagnosticPrinter.h @@ -29,7 +29,7 @@ class TextDiagnosticPrinter : public DiagnosticConsumer { raw_ostream &OS; IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts; - /// \brief Handle to the currently active text diagnostic emitter. + /// Handle to the currently active text diagnostic emitter. std::unique_ptr<TextDiagnostic> TextDiag; /// A string to prefix to error messages. diff --git a/include/clang/Frontend/Utils.h b/include/clang/Frontend/Utils.h index 8ccc31982dabd..67912a8dfcdde 100644 --- a/include/clang/Frontend/Utils.h +++ b/include/clang/Frontend/Utils.h @@ -1,4 +1,4 @@ -//===--- Utils.h - Misc utilities for the front-end -------------*- C++ -*-===// +//===- Utils.h - Misc utilities for the front-end ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,45 +15,49 @@ #define LLVM_CLANG_FRONTEND_UTILS_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/VirtualFileSystem.h" #include "llvm/ADT/IntrusiveRefCntPtr.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/Option/OptSpecifier.h" +#include <cstdint> +#include <memory> +#include <string> +#include <system_error> #include <utility> +#include <vector> namespace llvm { -class raw_fd_ostream; + class Triple; namespace opt { + class ArgList; -} -} + +} // namespace opt + +} // namespace llvm namespace clang { -class ASTConsumer; + class ASTReader; class CompilerInstance; class CompilerInvocation; -class Decl; class DependencyOutputOptions; class DiagnosticsEngine; -class DiagnosticOptions; class ExternalSemaSource; -class FileManager; +class FrontendOptions; class HeaderSearch; class HeaderSearchOptions; -class IdentifierTable; class LangOptions; class PCHContainerReader; class Preprocessor; class PreprocessorOptions; class PreprocessorOutputOptions; -class SourceManager; -class Stmt; -class TargetInfo; -class FrontendOptions; /// Apply the header search options to get given HeaderSearch object. void ApplyHeaderSearchOptions(HeaderSearch &HS, @@ -68,7 +72,7 @@ void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, const FrontendOptions &FEOpts); /// DoPrintPreprocessedInput - Implement -E mode. -void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS, +void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream *OS, const PreprocessorOutputOptions &Opts); /// An interface for collecting the dependencies of a compilation. Users should @@ -78,9 +82,11 @@ void DoPrintPreprocessedInput(Preprocessor &PP, raw_ostream* OS, /// interface. class DependencyCollector { public: + virtual ~DependencyCollector(); + virtual void attachToPreprocessor(Preprocessor &PP); virtual void attachToASTReader(ASTReader &R); - llvm::ArrayRef<std::string> getDependencies() const { return Dependencies; } + ArrayRef<std::string> getDependencies() const { return Dependencies; } /// Called when a new file is seen. Return true if \p Filename should be added /// to the list of dependencies. @@ -88,17 +94,19 @@ public: /// The default implementation ignores <built-in> and system files. virtual bool sawDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing); + /// Called when the end of the main file is reached. - virtual void finishedMainFile() { } + virtual void finishedMainFile() {} + /// Return true if system files should be passed to sawDependency(). virtual bool needSystemDependencies() { return false; } - virtual ~DependencyCollector(); -public: // implementation detail + // implementation detail /// Add a dependency \p Filename if it has not been seen before and /// sawDependency() returns true. void maybeAddDependency(StringRef Filename, bool FromModule, bool IsSystem, bool IsModuleFile, bool IsMissing); + private: llvm::StringSet<> Seen; std::vector<std::string> Dependencies; @@ -110,10 +118,13 @@ private: /// loaded. class DependencyFileGenerator { void *Impl; // Opaque implementation + DependencyFileGenerator(void *Impl); + public: static DependencyFileGenerator *CreateAndAttachToPreprocessor( Preprocessor &PP, const DependencyOutputOptions &Opts); + void AttachToASTReader(ASTReader &R); }; @@ -124,15 +135,20 @@ class ModuleDependencyCollector : public DependencyCollector { bool HasErrors = false; llvm::StringSet<> Seen; vfs::YAMLVFSWriter VFSWriter; - llvm::StringMap<std::string> SymLinkMap; bool getRealPath(StringRef SrcPath, SmallVectorImpl<char> &Result); - std::error_code copyToRoot(StringRef Src, StringRef Dst = ""); + std::error_code copyToRoot(StringRef Src, StringRef Dst = {}); + public: + ModuleDependencyCollector(std::string DestDir) + : DestDir(std::move(DestDir)) {} + ~ModuleDependencyCollector() override { writeFileMap(); } + StringRef getDest() { return DestDir; } bool insertSeen(StringRef Filename) { return Seen.insert(Filename).second; } - void addFile(StringRef Filename, StringRef FileDst = ""); + void addFile(StringRef Filename, StringRef FileDst = {}); + void addFileMapping(StringRef VPath, StringRef RPath) { VFSWriter.addFileMapping(VPath, RPath); } @@ -142,9 +158,6 @@ public: void writeFileMap(); bool hasErrors() { return HasErrors; } - ModuleDependencyCollector(std::string DestDir) - : DestDir(std::move(DestDir)) {} - ~ModuleDependencyCollector() { writeFileMap(); } }; /// AttachDependencyGraphGen - Create a dependency graph generator, and attach @@ -167,7 +180,7 @@ void AttachDependencyGraphGen(Preprocessor &PP, StringRef OutputFile, void AttachHeaderIncludeGen(Preprocessor &PP, const DependencyOutputOptions &DepOpts, bool ShowAllHeaders = false, - StringRef OutputPath = "", + StringRef OutputPath = {}, bool ShowDepth = true, bool MSStyle = false); /// Cache tokens for use with PCH. Note that this requires a seekable stream. @@ -221,6 +234,12 @@ template <typename T> void BuryPointer(std::unique_ptr<T> Ptr) { BuryPointer(Ptr.release()); } -} // end namespace clang +// Frontend timing utils + +/// If the user specifies the -ftime-report argument on an Clang command line +/// then the value of this boolean will be true, otherwise false. +extern bool FrontendTimesIsEnabled; + +} // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_UTILS_H diff --git a/include/clang/Frontend/VerifyDiagnosticConsumer.h b/include/clang/Frontend/VerifyDiagnosticConsumer.h index 8d71fb98b0bb1..9d985bc4955f8 100644 --- a/include/clang/Frontend/VerifyDiagnosticConsumer.h +++ b/include/clang/Frontend/VerifyDiagnosticConsumer.h @@ -11,18 +11,24 @@ #define LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Lex/Preprocessor.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" -#include "llvm/ADT/STLExtras.h" -#include <climits> +#include "llvm/ADT/StringRef.h" +#include <cassert> +#include <limits> #include <memory> +#include <string> +#include <vector> namespace clang { -class DiagnosticsEngine; -class TextDiagnosticBuffer; class FileEntry; +class LangOptions; +class SourceManager; +class TextDiagnosticBuffer; /// VerifyDiagnosticConsumer - Create a diagnostic client which will use /// markers in the input source to check that all the emitted diagnostics match @@ -153,7 +159,7 @@ public: public: /// Constant representing n or more matches. - static const unsigned MaxCount = UINT_MAX; + static const unsigned MaxCount = std::numeric_limits<unsigned>::max(); SourceLocation DirectiveLoc; SourceLocation DiagnosticLoc; @@ -161,7 +167,9 @@ public: unsigned Min, Max; bool MatchAnyLine; - virtual ~Directive() { } + Directive(const Directive &) = delete; + Directive &operator=(const Directive &) = delete; + virtual ~Directive() = default; // Returns true if directive text is valid. // Otherwise returns false and populates E. @@ -173,22 +181,17 @@ public: protected: Directive(SourceLocation DirectiveLoc, SourceLocation DiagnosticLoc, bool MatchAnyLine, StringRef Text, unsigned Min, unsigned Max) - : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), - Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) { - assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!"); - assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) && - "DiagnosticLoc is invalid!"); + : DirectiveLoc(DirectiveLoc), DiagnosticLoc(DiagnosticLoc), + Text(Text), Min(Min), Max(Max), MatchAnyLine(MatchAnyLine) { + assert(!DirectiveLoc.isInvalid() && "DirectiveLoc is invalid!"); + assert((!DiagnosticLoc.isInvalid() || MatchAnyLine) && + "DiagnosticLoc is invalid!"); } - - private: - Directive(const Directive &) = delete; - void operator=(const Directive &) = delete; }; - typedef std::vector<std::unique_ptr<Directive>> DirectiveList; + using DirectiveList = std::vector<std::unique_ptr<Directive>>; /// ExpectedData - owns directive objects and deletes on destructor. - /// struct ExpectedData { DirectiveList Errors; DirectiveList Warnings; @@ -215,14 +218,15 @@ private: DiagnosticConsumer *PrimaryClient; std::unique_ptr<DiagnosticConsumer> PrimaryClientOwner; std::unique_ptr<TextDiagnosticBuffer> Buffer; - const Preprocessor *CurrentPreprocessor; - const LangOptions *LangOpts; - SourceManager *SrcManager; - unsigned ActiveSourceFiles; + const Preprocessor *CurrentPreprocessor = nullptr; + const LangOptions *LangOpts = nullptr; + SourceManager *SrcManager = nullptr; + unsigned ActiveSourceFiles = 0; DirectiveStatus Status; ExpectedData ED; void CheckDiagnostics(); + void setSourceManager(SourceManager &SM) { assert((!SrcManager || SrcManager == &SM) && "SourceManager changed!"); SrcManager = &SM; @@ -231,14 +235,18 @@ private: // These facilities are used for validation in debug builds. class UnparsedFileStatus { llvm::PointerIntPair<const FileEntry *, 1, bool> Data; + public: UnparsedFileStatus(const FileEntry *File, bool FoundDirectives) - : Data(File, FoundDirectives) {} + : Data(File, FoundDirectives) {} + const FileEntry *getFile() const { return Data.getPointer(); } bool foundDirectives() const { return Data.getInt(); } }; - typedef llvm::DenseMap<FileID, const FileEntry *> ParsedFilesMap; - typedef llvm::DenseMap<FileID, UnparsedFileStatus> UnparsedFilesMap; + + using ParsedFilesMap = llvm::DenseMap<FileID, const FileEntry *>; + using UnparsedFilesMap = llvm::DenseMap<FileID, UnparsedFileStatus>; + ParsedFilesMap ParsedFiles; UnparsedFilesMap UnparsedFiles; @@ -265,7 +273,7 @@ public: IsUnparsedNoDirectives }; - /// \brief Update lists of parsed and unparsed files. + /// Update lists of parsed and unparsed files. void UpdateParsedFileStatus(SourceManager &SM, FileID FID, ParsedStatus PS); bool HandleComment(Preprocessor &PP, SourceRange Comment) override; @@ -274,6 +282,6 @@ public: const Diagnostic &Info) override; }; -} // end namspace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_FRONTEND_VERIFYDIAGNOSTICCONSUMER_H diff --git a/include/clang/FrontendTool/Utils.h b/include/clang/FrontendTool/Utils.h index 031ee7df70aed..2e6b7b5076bb6 100644 --- a/include/clang/FrontendTool/Utils.h +++ b/include/clang/FrontendTool/Utils.h @@ -15,9 +15,18 @@ #ifndef LLVM_CLANG_FRONTENDTOOL_UTILS_H #define LLVM_CLANG_FRONTENDTOOL_UTILS_H +#include <memory> + namespace clang { class CompilerInstance; +class FrontendAction; + +/// Construct the FrontendAction of a compiler invocation based on the +/// options specified for the compiler invocation. +/// +/// \return - The created FrontendAction object +std::unique_ptr<FrontendAction> CreateFrontendAction(CompilerInstance &CI); /// ExecuteCompilerInvocation - Execute the given actions described by the /// compiler invocation object in the given compiler instance. diff --git a/include/clang/Index/IndexDataConsumer.h b/include/clang/Index/IndexDataConsumer.h index 080f4cb4d0978..6e11455661a09 100644 --- a/include/clang/Index/IndexDataConsumer.h +++ b/include/clang/Index/IndexDataConsumer.h @@ -1,4 +1,4 @@ -//===--- IndexDataConsumer.h - Abstract index data consumer ---------------===// +//===--- IndexDataConsumer.h - Abstract index data consumer -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -42,23 +42,18 @@ public: /// \returns true to continue indexing, or false to abort. virtual bool handleDeclOccurence(const Decl *D, SymbolRoleSet Roles, ArrayRef<SymbolRelation> Relations, - FileID FID, unsigned Offset, - ASTNodeInfo ASTNode); + SourceLocation Loc, ASTNodeInfo ASTNode); /// \returns true to continue indexing, or false to abort. virtual bool handleMacroOccurence(const IdentifierInfo *Name, const MacroInfo *MI, SymbolRoleSet Roles, - FileID FID, unsigned Offset); + SourceLocation Loc); /// \returns true to continue indexing, or false to abort. virtual bool handleModuleOccurence(const ImportDecl *ImportD, - SymbolRoleSet Roles, - FileID FID, unsigned Offset); + SymbolRoleSet Roles, SourceLocation Loc); virtual void finish() {} - -private: - virtual void _anchor(); }; } // namespace index diff --git a/include/clang/Index/IndexSymbol.h b/include/clang/Index/IndexSymbol.h index 08f2839f37e85..068796141df8b 100644 --- a/include/clang/Index/IndexSymbol.h +++ b/include/clang/Index/IndexSymbol.h @@ -1,4 +1,4 @@ -//===--- IndexSymbol.h - Types and functions for indexing symbols ---------===// +//===- IndexSymbol.h - Types and functions for indexing symbols -*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,6 +11,7 @@ #define LLVM_CLANG_INDEX_INDEXSYMBOL_H #include "clang/Basic/LLVM.h" +#include "clang/Lex/MacroInfo.h" #include "llvm/ADT/STLExtras.h" #include "llvm/Support/DataTypes.h" @@ -89,30 +90,35 @@ enum class SymbolProperty : SymbolPropertySet { static const unsigned SymbolPropertyBitNum = 8; /// Set of roles that are attributed to symbol occurrences. +/// +/// Low 9 bits of clang-c/include/Index.h CXSymbolRole mirrors this enum. enum class SymbolRole : uint32_t { Declaration = 1 << 0, - Definition = 1 << 1, - Reference = 1 << 2, - Read = 1 << 3, - Write = 1 << 4, - Call = 1 << 5, - Dynamic = 1 << 6, - AddressOf = 1 << 7, - Implicit = 1 << 8, + Definition = 1 << 1, + Reference = 1 << 2, + Read = 1 << 3, + Write = 1 << 4, + Call = 1 << 5, + Dynamic = 1 << 6, + AddressOf = 1 << 7, + Implicit = 1 << 8, + // FIXME: this is not mirrored in CXSymbolRole. + // Note that macro occurrences aren't currently supported in libclang. + Undefinition = 1 << 9, // macro #undef // Relation roles. - RelationChildOf = 1 << 9, - RelationBaseOf = 1 << 10, - RelationOverrideOf = 1 << 11, - RelationReceivedBy = 1 << 12, - RelationCalledBy = 1 << 13, - RelationExtendedBy = 1 << 14, - RelationAccessorOf = 1 << 15, - RelationContainedBy = 1 << 16, - RelationIBTypeOf = 1 << 17, - RelationSpecializationOf = 1 << 18, + RelationChildOf = 1 << 10, + RelationBaseOf = 1 << 11, + RelationOverrideOf = 1 << 12, + RelationReceivedBy = 1 << 13, + RelationCalledBy = 1 << 14, + RelationExtendedBy = 1 << 15, + RelationAccessorOf = 1 << 16, + RelationContainedBy = 1 << 17, + RelationIBTypeOf = 1 << 18, + RelationSpecializationOf = 1 << 19, }; -static const unsigned SymbolRoleBitNum = 19; +static const unsigned SymbolRoleBitNum = 20; typedef unsigned SymbolRoleSet; /// Represents a relation to another symbol for a symbol occurrence. @@ -133,6 +139,8 @@ struct SymbolInfo { SymbolInfo getSymbolInfo(const Decl *D); +SymbolInfo getSymbolInfoForMacro(const MacroInfo &MI); + bool isFunctionLocalSymbol(const Decl *D); void applyForEachSymbolRole(SymbolRoleSet Roles, diff --git a/include/clang/Index/IndexingAction.h b/include/clang/Index/IndexingAction.h index fb703be4e5f53..0d09c403483d9 100644 --- a/include/clang/Index/IndexingAction.h +++ b/include/clang/Index/IndexingAction.h @@ -1,4 +1,4 @@ -//===--- IndexingAction.h - Frontend index action -------------------------===// +//===--- IndexingAction.h - Frontend index action ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,6 +11,7 @@ #define LLVM_CLANG_INDEX_INDEXINGACTION_H #include "clang/Basic/LLVM.h" +#include "clang/Lex/PPCallbacks.h" #include "llvm/ADT/ArrayRef.h" #include <memory> @@ -38,25 +39,35 @@ struct IndexingOptions { SystemSymbolFilterKind SystemSymbolFilter = SystemSymbolFilterKind::DeclarationsOnly; bool IndexFunctionLocals = false; + bool IndexImplicitInstantiation = false; }; +/// Creates a frontend action that indexes all symbols (macros and AST decls). /// \param WrappedAction another frontend action to wrap over or null. std::unique_ptr<FrontendAction> createIndexingAction(std::shared_ptr<IndexDataConsumer> DataConsumer, IndexingOptions Opts, std::unique_ptr<FrontendAction> WrappedAction); -void indexASTUnit(ASTUnit &Unit, - std::shared_ptr<IndexDataConsumer> DataConsumer, +/// Recursively indexes all decls in the AST. +/// Note that this does not index macros. +void indexASTUnit(ASTUnit &Unit, IndexDataConsumer &DataConsumer, IndexingOptions Opts); +/// Recursively indexes \p Decls. +/// Note that this does not index macros. void indexTopLevelDecls(ASTContext &Ctx, ArrayRef<const Decl *> Decls, - std::shared_ptr<IndexDataConsumer> DataConsumer, - IndexingOptions Opts); + IndexDataConsumer &DataConsumer, IndexingOptions Opts); +/// Creates a PPCallbacks that indexes macros and feeds macros to \p Consumer. +/// The caller is responsible for calling `Consumer.setPreprocessor()`. +std::unique_ptr<PPCallbacks> indexMacrosCallback(IndexDataConsumer &Consumer, + IndexingOptions Opts); + +/// Recursively indexes all top-level decls in the module. +/// FIXME: make this index macros as well. void indexModuleFile(serialization::ModuleFile &Mod, ASTReader &Reader, - std::shared_ptr<IndexDataConsumer> DataConsumer, - IndexingOptions Opts); + IndexDataConsumer &DataConsumer, IndexingOptions Opts); } // namespace index } // namespace clang diff --git a/include/clang/Index/USRGeneration.h b/include/clang/Index/USRGeneration.h index 8c661bd63cd8a..1ece321746a60 100644 --- a/include/clang/Index/USRGeneration.h +++ b/include/clang/Index/USRGeneration.h @@ -1,4 +1,4 @@ -//===- USRGeneration.h - Routines for USR generation ----------------------===// +//===- USRGeneration.h - Routines for USR generation ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -25,33 +25,33 @@ static inline StringRef getUSRSpacePrefix() { return "c:"; } -/// \brief Generate a USR for a Decl, including the USR prefix. +/// Generate a USR for a Decl, including the USR prefix. /// \returns true if the results should be ignored, false otherwise. bool generateUSRForDecl(const Decl *D, SmallVectorImpl<char> &Buf); -/// \brief Generate a USR fragment for an Objective-C class. +/// Generate a USR fragment for an Objective-C class. void generateUSRForObjCClass(StringRef Cls, raw_ostream &OS, StringRef ExtSymbolDefinedIn = "", StringRef CategoryContextExtSymbolDefinedIn = ""); -/// \brief Generate a USR fragment for an Objective-C class category. +/// Generate a USR fragment for an Objective-C class category. void generateUSRForObjCCategory(StringRef Cls, StringRef Cat, raw_ostream &OS, StringRef ClsExtSymbolDefinedIn = "", StringRef CatExtSymbolDefinedIn = ""); -/// \brief Generate a USR fragment for an Objective-C instance variable. The +/// Generate a USR fragment for an Objective-C instance variable. The /// complete USR can be created by concatenating the USR for the /// encompassing class with this USR fragment. void generateUSRForObjCIvar(StringRef Ivar, raw_ostream &OS); -/// \brief Generate a USR fragment for an Objective-C method. +/// Generate a USR fragment for an Objective-C method. void generateUSRForObjCMethod(StringRef Sel, bool IsInstanceMethod, raw_ostream &OS); -/// \brief Generate a USR fragment for an Objective-C property. +/// Generate a USR fragment for an Objective-C property. void generateUSRForObjCProperty(StringRef Prop, bool isClassProp, raw_ostream &OS); -/// \brief Generate a USR fragment for an Objective-C protocol. +/// Generate a USR fragment for an Objective-C protocol. void generateUSRForObjCProtocol(StringRef Prot, raw_ostream &OS, StringRef ExtSymbolDefinedIn = ""); @@ -62,7 +62,7 @@ void generateUSRForGlobalEnum(StringRef EnumName, raw_ostream &OS, /// Generate a USR fragment for an enum constant. void generateUSRForEnumConstant(StringRef EnumConstantName, raw_ostream &OS); -/// \brief Generate a USR for a macro, including the USR prefix. +/// Generate a USR for a macro, including the USR prefix. /// /// \returns true on error, false on success. bool generateUSRForMacro(const MacroDefinitionRecord *MD, diff --git a/include/clang/Lex/CodeCompletionHandler.h b/include/clang/Lex/CodeCompletionHandler.h index 91c3b7811f079..be153cc1ad508 100644 --- a/include/clang/Lex/CodeCompletionHandler.h +++ b/include/clang/Lex/CodeCompletionHandler.h @@ -19,13 +19,13 @@ namespace clang { class IdentifierInfo; class MacroInfo; -/// \brief Callback handler that receives notifications when performing code +/// Callback handler that receives notifications when performing code /// completion within the preprocessor. class CodeCompletionHandler { public: virtual ~CodeCompletionHandler(); - /// \brief Callback invoked when performing code completion for a preprocessor + /// Callback invoked when performing code completion for a preprocessor /// directive. /// /// This callback will be invoked when the preprocessor processes a '#' at the @@ -35,22 +35,22 @@ public: /// already. virtual void CodeCompleteDirective(bool InConditional) { } - /// \brief Callback invoked when performing code completion within a block of + /// Callback invoked when performing code completion within a block of /// code that was excluded due to preprocessor conditionals. virtual void CodeCompleteInConditionalExclusion() { } - /// \brief Callback invoked when performing code completion in a context + /// Callback invoked when performing code completion in a context /// where the name of a macro is expected. /// /// \param IsDefinition Whether this is the definition of a macro, e.g., /// in a \#define. virtual void CodeCompleteMacroName(bool IsDefinition) { } - /// \brief Callback invoked when performing code completion in a preprocessor + /// Callback invoked when performing code completion in a preprocessor /// expression, such as the condition of an \#if or \#elif directive. virtual void CodeCompletePreprocessorExpression() { } - /// \brief Callback invoked when performing code completion inside a + /// Callback invoked when performing code completion inside a /// function-like macro argument. /// /// There will be another callback invocation after the macro arguments are @@ -60,7 +60,7 @@ public: MacroInfo *MacroInfo, unsigned ArgumentIndex) { } - /// \brief Callback invoked when performing code completion in a part of the + /// Callback invoked when performing code completion in a part of the /// file where we expect natural language, e.g., a comment, string, or /// \#error directive. virtual void CodeCompleteNaturalLanguage() { } diff --git a/include/clang/Lex/DirectoryLookup.h b/include/clang/Lex/DirectoryLookup.h index dcd58f434fa24..222ebf025ac04 100644 --- a/include/clang/Lex/DirectoryLookup.h +++ b/include/clang/Lex/DirectoryLookup.h @@ -55,10 +55,10 @@ private: /// normal directory, a framework, or a headermap. unsigned LookupType : 2; - /// \brief Whether this is a header map used when building a framework. + /// Whether this is a header map used when building a framework. unsigned IsIndexHeaderMap : 1; - /// \brief Whether we've performed an exhaustive search for module maps + /// Whether we've performed an exhaustive search for module maps /// within the subdirectories of this directory. unsigned SearchedAllModuleMaps : 1; @@ -118,11 +118,11 @@ public: /// isHeaderMap - Return true if this is a header map, not a normal directory. bool isHeaderMap() const { return getLookupType() == LT_HeaderMap; } - /// \brief Determine whether we have already searched this entire + /// Determine whether we have already searched this entire /// directory for module maps. bool haveSearchedAllModuleMaps() const { return SearchedAllModuleMaps; } - /// \brief Specify whether we have already searched all of the subdirectories + /// Specify whether we have already searched all of the subdirectories /// for module maps. void setSearchedAllModuleMaps(bool SAMM) { SearchedAllModuleMaps = SAMM; @@ -134,12 +134,12 @@ public: return (SrcMgr::CharacteristicKind)DirCharacteristic; } - /// \brief Whether this describes a system header directory. + /// Whether this describes a system header directory. bool isSystemHeaderDirectory() const { return getDirCharacteristic() != SrcMgr::C_User; } - /// \brief Whether this header map is building a framework or not. + /// Whether this header map is building a framework or not. bool isIndexHeaderMap() const { return isHeaderMap() && IsIndexHeaderMap; } diff --git a/include/clang/Lex/ExternalPreprocessorSource.h b/include/clang/Lex/ExternalPreprocessorSource.h index adf8e713e99e6..f34be682617cd 100644 --- a/include/clang/Lex/ExternalPreprocessorSource.h +++ b/include/clang/Lex/ExternalPreprocessorSource.h @@ -19,7 +19,7 @@ namespace clang { class IdentifierInfo; class Module; -/// \brief Abstract interface for external sources of preprocessor +/// Abstract interface for external sources of preprocessor /// information. /// /// This abstract class allows an external sources (such as the \c ASTReader) @@ -28,18 +28,18 @@ class ExternalPreprocessorSource { public: virtual ~ExternalPreprocessorSource(); - /// \brief Read the set of macros defined by this external macro source. + /// Read the set of macros defined by this external macro source. virtual void ReadDefinedMacros() = 0; - /// \brief Update an out-of-date identifier. + /// Update an out-of-date identifier. virtual void updateOutOfDateIdentifier(IdentifierInfo &II) = 0; - /// \brief Return the identifier associated with the given ID number. + /// Return the identifier associated with the given ID number. /// /// The ID 0 is associated with the NULL identifier. virtual IdentifierInfo *GetIdentifier(unsigned ID) = 0; - /// \brief Map a module ID to a module. + /// Map a module ID to a module. virtual Module *getModule(unsigned ModuleID) = 0; }; diff --git a/include/clang/Lex/HeaderSearch.h b/include/clang/Lex/HeaderSearch.h index 6b9dbfcd1e934..b7147c54faacd 100644 --- a/include/clang/Lex/HeaderSearch.h +++ b/include/clang/Lex/HeaderSearch.h @@ -46,13 +46,13 @@ class Module; class Preprocessor; class TargetInfo; -/// \brief The preprocessor keeps track of this information for each +/// The preprocessor keeps track of this information for each /// file that is \#included. struct HeaderFileInfo { - /// \brief True if this is a \#import'd or \#pragma once file. + /// True if this is a \#import'd or \#pragma once file. unsigned isImport : 1; - /// \brief True if this is a \#pragma once file. + /// True if this is a \#pragma once file. unsigned isPragmaOnce : 1; /// DirInfo - Keep track of whether this is a system header, and if so, @@ -61,21 +61,21 @@ struct HeaderFileInfo { /// SrcMgr::CharacteristicKind. unsigned DirInfo : 3; - /// \brief Whether this header file info was supplied by an external source, + /// Whether this header file info was supplied by an external source, /// and has not changed since. unsigned External : 1; - /// \brief Whether this header is part of a module. + /// Whether this header is part of a module. unsigned isModuleHeader : 1; - /// \brief Whether this header is part of the module that we are building. + /// Whether this header is part of the module that we are building. unsigned isCompilingModuleHeader : 1; - /// \brief Whether this structure is considered to already have been + /// Whether this structure is considered to already have been /// "resolved", meaning that it was loaded from the external source. unsigned Resolved : 1; - /// \brief Whether this is a header inside a framework that is currently + /// Whether this is a header inside a framework that is currently /// being built. /// /// When a framework is being built, the headers have not yet been placed @@ -84,13 +84,13 @@ struct HeaderFileInfo { /// those framework headers. unsigned IndexHeaderMapHeader : 1; - /// \brief Whether this file has been looked up as a header. + /// Whether this file has been looked up as a header. unsigned IsValid : 1; - /// \brief The number of times the file has been included already. + /// The number of times the file has been included already. unsigned short NumIncludes = 0; - /// \brief The ID number of the controlling macro. + /// The ID number of the controlling macro. /// /// This ID number will be non-zero when there is a controlling /// macro whose IdentifierInfo may not yet have been loaded from @@ -107,7 +107,7 @@ struct HeaderFileInfo { /// external storage. const IdentifierInfo *ControllingMacro = nullptr; - /// \brief If this header came from a framework include, this is the name + /// If this header came from a framework include, this is the name /// of the framework. StringRef Framework; @@ -116,12 +116,12 @@ struct HeaderFileInfo { External(false), isModuleHeader(false), isCompilingModuleHeader(false), Resolved(false), IndexHeaderMapHeader(false), IsValid(false) {} - /// \brief Retrieve the controlling macro for this header file, if + /// Retrieve the controlling macro for this header file, if /// any. const IdentifierInfo * getControllingMacro(ExternalPreprocessorSource *External); - /// \brief Determine whether this is a non-default header file info, e.g., + /// Determine whether this is a non-default header file info, e.g., /// it corresponds to an actual header we've included or tried to include. bool isNonDefault() const { return isImport || isPragmaOnce || NumIncludes || ControllingMacro || @@ -129,13 +129,13 @@ struct HeaderFileInfo { } }; -/// \brief An external source of header file information, which may supply +/// An external source of header file information, which may supply /// information about header files already included. class ExternalHeaderFileInfoSource { public: virtual ~ExternalHeaderFileInfoSource(); - /// \brief Retrieve the header file information for the given file entry. + /// Retrieve the header file information for the given file entry. /// /// \returns Header file information for the given file entry, with the /// \c External bit set. If the file entry is not known, return a @@ -143,7 +143,7 @@ public: virtual HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) = 0; }; -/// \brief Encapsulates the information needed to find the file referenced +/// Encapsulates the information needed to find the file referenced /// by a \#include or \#include_next, (sub-)framework lookup, etc. class HeaderSearch { friend class DirectoryLookup; @@ -159,7 +159,7 @@ class HeaderSearch { bool IsUserSpecifiedSystemFramework; }; - /// \brief Header-search options used to initialize this header search. + /// Header-search options used to initialize this header search. std::shared_ptr<HeaderSearchOptions> HSOpts; DiagnosticsEngine &Diags; @@ -176,7 +176,7 @@ class HeaderSearch { unsigned SystemDirIdx = 0; bool NoCurDirSearch = false; - /// \brief \#include prefixes for which the 'system header' property is + /// \#include prefixes for which the 'system header' property is /// overridden. /// /// For a \#include "x" or \#include \<x> directive, the last string in this @@ -184,10 +184,10 @@ class HeaderSearch { /// a system header. std::vector<std::pair<std::string, bool>> SystemHeaderPrefixes; - /// \brief The path to the module cache. + /// The path to the module cache. std::string ModuleCachePath; - /// \brief All of the preprocessor-specific data about files that are + /// All of the preprocessor-specific data about files that are /// included, indexed by the FileEntry's UID. mutable std::vector<HeaderFileInfo> FileInfo; @@ -215,7 +215,7 @@ class HeaderSearch { }; llvm::StringMap<LookupFileCacheInfo, llvm::BumpPtrAllocator> LookupFileCache; - /// \brief Collection mapping a framework or subframework + /// Collection mapping a framework or subframework /// name like "Carbon" to the Carbon.framework directory. llvm::StringMap<FrameworkCacheEntry, llvm::BumpPtrAllocator> FrameworkMap; @@ -230,26 +230,26 @@ class HeaderSearch { /// headermaps. This vector owns the headermap. std::vector<std::pair<const FileEntry *, const HeaderMap *>> HeaderMaps; - /// \brief The mapping between modules and headers. + /// The mapping between modules and headers. mutable ModuleMap ModMap; - /// \brief Describes whether a given directory has a module map in it. + /// 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 + /// 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 + /// Uniqued set of framework names, which is used to track which /// headers were included as framework headers. llvm::StringSet<llvm::BumpPtrAllocator> FrameworkNames; - /// \brief Entity used to resolve the identifier IDs of controlling + /// Entity used to resolve the identifier IDs of controlling /// macros into IdentifierInfo pointers, and keep the identifire up to date, /// as needed. ExternalPreprocessorSource *ExternalLookup = nullptr; - /// \brief Entity used to look up stored header file information. + /// Entity used to look up stored header file information. ExternalHeaderFileInfoSource *ExternalSource = nullptr; // Various statistics we track for performance analysis. @@ -266,18 +266,20 @@ public: HeaderSearch &operator=(const HeaderSearch &) = delete; ~HeaderSearch(); - /// \brief Retrieve the header-search options with which this header search + /// Retrieve the header-search options with which this header search /// was initialized. HeaderSearchOptions &getHeaderSearchOpts() const { return *HSOpts; } FileManager &getFileMgr() const { return FileMgr; } - /// \brief Interface for setting the file search paths. + DiagnosticsEngine &getDiags() const { return Diags; } + + /// Interface for setting the file search paths. void SetSearchPaths(const std::vector<DirectoryLookup> &dirs, unsigned angledDirIdx, unsigned systemDirIdx, bool noCurDirSearch) { assert(angledDirIdx <= systemDirIdx && systemDirIdx <= dirs.size() && - "Directory indicies are unordered"); + "Directory indices are unordered"); SearchDirs = dirs; AngledDirIdx = angledDirIdx; SystemDirIdx = systemDirIdx; @@ -285,7 +287,7 @@ public: //LookupFileCache.clear(); } - /// \brief Add an additional search path. + /// Add an additional search path. void AddSearchPath(const DirectoryLookup &dir, bool isAngled) { unsigned idx = isAngled ? SystemDirIdx : AngledDirIdx; SearchDirs.insert(SearchDirs.begin() + idx, dir); @@ -294,15 +296,15 @@ public: SystemDirIdx++; } - /// \brief Set the list of system header prefixes. + /// Set the list of system header prefixes. void SetSystemHeaderPrefixes(ArrayRef<std::pair<std::string, bool>> P) { SystemHeaderPrefixes.assign(P.begin(), P.end()); } - /// \brief Checks whether the map exists or not. + /// Checks whether the map exists or not. bool HasIncludeAliasMap() const { return (bool)IncludeAliases; } - /// \brief Map the source include name to the dest include name. + /// Map the source include name to the dest include name. /// /// The Source should include the angle brackets or quotes, the dest /// should not. This allows for distinction between <> and "" headers. @@ -326,20 +328,20 @@ public: return {}; } - /// \brief Set the path to the module cache. + /// Set the path to the module cache. void setModuleCachePath(StringRef CachePath) { ModuleCachePath = CachePath; } - /// \brief Retrieve the path to the module cache. + /// Retrieve the path to the module cache. StringRef getModuleCachePath() const { return ModuleCachePath; } - /// \brief Consider modules when including files from this directory. + /// Consider modules when including files from this directory. void setDirectoryHasModuleMap(const DirectoryEntry* Dir) { DirectoryHasModuleMap[Dir] = true; } - /// \brief Forget everything we know about headers so far. + /// Forget everything we know about headers so far. void ClearFileInfo() { FileInfo.clear(); } @@ -352,16 +354,16 @@ public: return ExternalLookup; } - /// \brief Set the external source of header information. + /// Set the external source of header information. void SetExternalSource(ExternalHeaderFileInfoSource *ES) { ExternalSource = ES; } - /// \brief Set the target information for the header search, if not + /// Set the target information for the header search, if not /// already known. void setTarget(const TargetInfo &Target); - /// \brief Given a "foo" or \<foo> reference, look up the indicated file, + /// Given a "foo" or \<foo> reference, look up the indicated file, /// return null on failure. /// /// \returns If successful, this returns 'UsedDir', the DirectoryLookup member @@ -399,7 +401,7 @@ public: Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool SkipCache = false, bool BuildSystemModule = false); - /// \brief Look up a subframework for the specified \#include file. + /// Look up a subframework for the specified \#include file. /// /// For example, if \#include'ing <HIToolbox/HIToolbox.h> from /// within ".../Carbon.framework/Headers/Carbon.h", check to see if @@ -410,13 +412,13 @@ public: SmallVectorImpl<char> *SearchPath, SmallVectorImpl<char> *RelativePath, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule); - /// \brief Look up the specified framework name in our framework cache. + /// 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[FWName]; } - /// \brief Mark the specified file as a target of of a \#include, + /// Mark the specified file as a target of a \#include, /// \#include_next, or \#import directive. /// /// \return false if \#including the file will have no effect or true @@ -425,13 +427,13 @@ public: bool isImport, bool ModulesEnabled, Module *CorrespondingModule); - /// \brief Return whether the specified file is a normal header, + /// Return whether the specified file is a normal header, /// a system header, or a C++ friendly system header. SrcMgr::CharacteristicKind getFileDirFlavor(const FileEntry *File) { return (SrcMgr::CharacteristicKind)getFileInfo(File).DirInfo; } - /// \brief Mark the specified file as a "once only" file, e.g. due to + /// Mark the specified file as a "once only" file, e.g. due to /// \#pragma once. void MarkFileIncludeOnce(const FileEntry *File) { HeaderFileInfo &FI = getFileInfo(File); @@ -439,24 +441,24 @@ public: FI.isPragmaOnce = true; } - /// \brief Mark the specified file as a system header, e.g. due to + /// Mark the specified file as a system header, e.g. due to /// \#pragma GCC system_header. void MarkFileSystemHeader(const FileEntry *File) { getFileInfo(File).DirInfo = SrcMgr::C_System; } - /// \brief Mark the specified file as part of a module. + /// Mark the specified file as part of a module. void MarkFileModuleHeader(const FileEntry *File, ModuleMap::ModuleHeaderRole Role, bool IsCompiledModuleHeader); - /// \brief Increment the count for the number of times the specified + /// Increment the count for the number of times the specified /// FileEntry has been entered. void IncrementIncludeCount(const FileEntry *File) { ++getFileInfo(File).NumIncludes; } - /// \brief Mark the specified file as having a controlling macro. + /// Mark the specified file as having a controlling macro. /// /// This is used by the multiple-include optimization to eliminate /// no-op \#includes. @@ -465,12 +467,12 @@ public: getFileInfo(File).ControllingMacro = ControllingMacro; } - /// \brief Return true if this is the first time encountering this header. + /// Return true if this is the first time encountering this header. bool FirstTimeLexingFile(const FileEntry *File) { return getFileInfo(File).NumIncludes == 1; } - /// \brief Determine whether this file is intended to be safe from + /// Determine whether this file is intended to be safe from /// multiple inclusions, e.g., it has \#pragma once or a controlling /// macro. /// @@ -481,10 +483,10 @@ public: /// FileEntry, uniquing them through the 'HeaderMaps' datastructure. const HeaderMap *CreateHeaderMap(const FileEntry *FE); - /// \brief Get filenames for all registered header maps. + /// Get filenames for all registered header maps. void getHeaderMapFileNames(SmallVectorImpl<std::string> &Names) const; - /// \brief Retrieve the name of the cached module file that should be used + /// Retrieve the name of the cached module file that should be used /// to load the given module. /// /// \param Module The module whose module file name will be returned. @@ -493,7 +495,7 @@ public: /// or an empty string if this module does not correspond to any module file. std::string getCachedModuleFileName(Module *Module); - /// \brief Retrieve the name of the prebuilt module file that should be used + /// Retrieve the name of the prebuilt module file that should be used /// to load a module with the given name. /// /// \param ModuleName The module whose module file name will be returned. @@ -506,7 +508,7 @@ public: std::string getPrebuiltModuleFileName(StringRef ModuleName, bool FileMapOnly = false); - /// \brief Retrieve the name of the (to-be-)cached module file that should + /// Retrieve the name of the (to-be-)cached module file that should /// be used to load a module with the given name. /// /// \param ModuleName The module whose module file name will be returned. @@ -519,7 +521,7 @@ public: std::string getCachedModuleFileName(StringRef ModuleName, StringRef ModuleMapPath); - /// \brief Lookup a module Search for a module with the given name. + /// Lookup a module Search for a module with the given name. /// /// \param ModuleName The name of the module we're looking for. /// @@ -527,17 +529,21 @@ public: /// search directories to produce a module definition. If not, this lookup /// will only return an already-known module. /// + /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps + /// in subdirectories. + /// /// \returns The module with the given name. - Module *lookupModule(StringRef ModuleName, bool AllowSearch = true); + Module *lookupModule(StringRef ModuleName, bool AllowSearch = true, + bool AllowExtraModuleMapSearch = false); - /// \brief Try to find a module map file in the given directory, returning + /// Try to find a module map file in the given directory, returning /// \c nullptr if none is found. const FileEntry *lookupModuleMapFile(const DirectoryEntry *Dir, bool IsFramework); void IncrementFrameworkLookupCount() { ++NumFrameworkLookups; } - /// \brief Determine whether there is a module map that may map the header + /// Determine whether there is a module map that may map the header /// with the given file name to a (sub)module. /// Always returns false if modules are disabled. /// @@ -551,14 +557,14 @@ public: bool hasModuleMap(StringRef Filename, const DirectoryEntry *Root, bool IsSystem); - /// \brief Retrieve the module that corresponds to the given file, if any. + /// Retrieve the module that corresponds to the given file, if any. /// /// \param File The header that we wish to map to a module. /// \param AllowTextual Whether we want to find textual headers too. ModuleMap::KnownHeader findModuleForHeader(const FileEntry *File, bool AllowTextual = false) const; - /// \brief Read the contents of the given module map file. + /// Read the contents of the given module map file. /// /// \param File The module map file. /// \param IsSystem Whether this file is in a system header directory. @@ -575,16 +581,16 @@ public: FileID ID = FileID(), unsigned *Offset = nullptr, StringRef OriginalModuleMapFile = StringRef()); - /// \brief Collect the set of all known, top-level modules. + /// Collect the set of all known, top-level modules. /// /// \param Modules Will be filled with the set of known, top-level modules. void collectAllModules(SmallVectorImpl<Module *> &Modules); - /// \brief Load all known, top-level system modules. + /// Load all known, top-level system modules. void loadTopLevelSystemModules(); private: - /// \brief Lookup a module with the given module name and search-name. + /// Lookup a module with the given module name and search-name. /// /// \param ModuleName The name of the module we're looking for. /// @@ -593,10 +599,14 @@ private: /// but for compatibility with some buggy frameworks, additional attempts /// may be made to find the module under a related-but-different search-name. /// + /// \param AllowExtraModuleMapSearch Whether we allow to search modulemaps + /// in subdirectories. + /// /// \returns The module named ModuleName. - Module *lookupModule(StringRef ModuleName, StringRef SearchName); + Module *lookupModule(StringRef ModuleName, StringRef SearchName, + bool AllowExtraModuleMapSearch = false); - /// \brief Retrieve a module with the given name, which may be part of the + /// Retrieve a module with the given name, which may be part of the /// given framework. /// /// \param Name The name of the module to retrieve. @@ -611,11 +621,11 @@ private: const DirectoryEntry *Dir, bool IsSystem); - /// \brief Load all of the module maps within the immediate subdirectories + /// Load all of the module maps within the immediate subdirectories /// of the given search directory. void loadSubdirectoryModuleMaps(DirectoryLookup &SearchDir); - /// \brief Find and suggest a usable module for the given file. + /// Find and suggest a usable module for the given file. /// /// \return \c true if the file can be used, \c false if we are not permitted to /// find this file due to requirements from \p RequestingModule. @@ -625,7 +635,7 @@ private: ModuleMap::KnownHeader *SuggestedModule, bool IsSystemHeaderDir); - /// \brief Find and suggest a usable module for the given file, which is part of + /// Find and suggest a usable module for the given file, which is part of /// the specified framework. /// /// \return \c true if the file can be used, \c false if we are not permitted to @@ -634,7 +644,7 @@ private: const FileEntry *File, StringRef FrameworkDir, Module *RequestingModule, ModuleMap::KnownHeader *SuggestedModule, bool IsSystemFramework); - /// \brief Look up the file with the specified name and determine its owning + /// Look up the file with the specified name and determine its owning /// module. const FileEntry * getFileAndSuggestModule(StringRef FileName, SourceLocation IncludeLoc, @@ -643,19 +653,19 @@ private: ModuleMap::KnownHeader *SuggestedModule); public: - /// \brief Retrieve the module map. + /// Retrieve the module map. ModuleMap &getModuleMap() { return ModMap; } - /// \brief Retrieve the module map. + /// Retrieve the module map. const ModuleMap &getModuleMap() const { return ModMap; } unsigned header_file_size() const { return FileInfo.size(); } - /// \brief Return the HeaderFileInfo structure for the specified FileEntry, + /// Return the HeaderFileInfo structure for the specified FileEntry, /// in preparation for updating it in some way. HeaderFileInfo &getFileInfo(const FileEntry *FE); - /// \brief Return the HeaderFileInfo structure for the specified FileEntry, + /// Return the HeaderFileInfo structure for the specified FileEntry, /// if it has ever been filled in. /// \param WantExternal Whether the caller wants purely-external header file /// info (where \p External is true). @@ -691,10 +701,10 @@ public: search_dir_iterator system_dir_end() const { return SearchDirs.end(); } - /// \brief Retrieve a uniqued framework name. + /// Retrieve a uniqued framework name. StringRef getUniqueFrameworkName(StringRef Framework); - - /// \brief Suggest a path by which the specified file could be found, for + + /// Suggest a path by which the specified file could be found, for /// use in diagnostics to suggest a #include. /// /// \param IsSystem If non-null, filled in to indicate whether the suggested @@ -702,23 +712,32 @@ public: std::string suggestPathToFileForDiagnostics(const FileEntry *File, bool *IsSystem = nullptr); + /// Suggest a path by which the specified file could be found, for + /// use in diagnostics to suggest a #include. + /// + /// \param WorkingDir If non-empty, this will be prepended to search directory + /// paths that are relative. + std::string suggestPathToFileForDiagnostics(llvm::StringRef File, + llvm::StringRef WorkingDir, + bool *IsSystem = nullptr); + void PrintStats(); size_t getTotalMemory() const; private: - /// \brief Describes what happened when we tried to load a module map file. + /// Describes what happened when we tried to load a module map file. enum LoadModuleMapResult { - /// \brief The module map file had already been loaded. + /// The module map file had already been loaded. LMM_AlreadyLoaded, - /// \brief The module map file was loaded by this invocation. + /// The module map file was loaded by this invocation. LMM_NewlyLoaded, - /// \brief There is was directory with the given name. + /// There is was directory with the given name. LMM_NoDirectory, - /// \brief There was either no module map file or the module map file was + /// There was either no module map file or the module map file was /// invalid. LMM_InvalidModuleMap }; @@ -729,7 +748,7 @@ private: FileID ID = FileID(), unsigned *Offset = nullptr); - /// \brief Try to load the module map file in the given directory. + /// Try to load the module map file in the given directory. /// /// \param DirName The name of the directory where we will look for a module /// map file. @@ -741,7 +760,7 @@ private: LoadModuleMapResult loadModuleMapFile(StringRef DirName, bool IsSystem, bool IsFramework); - /// \brief Try to load the module map file in the given directory. + /// Try to load the module map file in the given directory. /// /// \param Dir The directory where we will look for a module map file. /// \param IsSystem Whether this is a system header directory. diff --git a/include/clang/Lex/HeaderSearchOptions.h b/include/clang/Lex/HeaderSearchOptions.h index 937ad9863db37..298179e91a6fd 100644 --- a/include/clang/Lex/HeaderSearchOptions.h +++ b/include/clang/Lex/HeaderSearchOptions.h @@ -108,32 +108,32 @@ public: /// etc.). std::string ResourceDir; - /// \brief The directory used for the module cache. + /// The directory used for the module cache. std::string ModuleCachePath; - /// \brief The directory used for a user build. + /// The directory used for a user build. std::string ModuleUserBuildPath; - /// \brief The mapping of module names to prebuilt module files. + /// The mapping of module names to prebuilt module files. std::map<std::string, std::string> PrebuiltModuleFiles; - /// \brief The directories used to load prebuilt module files. + /// The directories used to load prebuilt module files. std::vector<std::string> PrebuiltModulePaths; /// The module/pch container format. std::string ModuleFormat; - /// \brief Whether we should disable the use of the hash string within the + /// Whether we should disable the use of the hash string within the /// module cache. /// /// Note: Only used for testing! unsigned DisableModuleHash : 1; - /// \brief Implicit module maps. This option is enabld by default when + /// Implicit module maps. This option is enabld by default when /// modules is enabled. unsigned ImplicitModuleMaps : 1; - /// \brief Set the 'home directory' of a module map file to the current + /// 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. @@ -142,7 +142,7 @@ public: /// file. unsigned ModuleMapFileHomeIsCwd : 1; - /// \brief The interval (in seconds) between pruning operations. + /// The interval (in seconds) between pruning operations. /// /// This operation is expensive, because it requires Clang to walk through /// the directory structure of the module cache, stat()'ing and removing @@ -151,7 +151,7 @@ public: /// The default value is large, e.g., the operation runs once a week. unsigned ModuleCachePruneInterval = 7 * 24 * 60 * 60; - /// \brief The time (in seconds) after which an unused module file will be + /// The time (in seconds) after which an unused module file will be /// considered unused and will, therefore, be pruned. /// /// When the module cache is pruned, any module file that has not been @@ -160,17 +160,17 @@ public: /// regenerated often. unsigned ModuleCachePruneAfter = 31 * 24 * 60 * 60; - /// \brief The time in seconds when the build session started. + /// The time in seconds when the build session started. /// /// This time is used by other optimizations in header search and module /// loading. uint64_t BuildSessionTimestamp = 0; - /// \brief The set of macro names that should be ignored for the purposes + /// The set of macro names that should be ignored for the purposes /// of computing the module hash. llvm::SmallSetVector<llvm::CachedHashString, 16> ModulesIgnoreMacros; - /// \brief The set of user-provided virtual filesystem overlay files. + /// The set of user-provided virtual filesystem overlay files. std::vector<std::string> VFSOverlayFiles; /// Include the compiler builtin includes. @@ -188,12 +188,12 @@ public: /// Whether header search information should be output as for -v. unsigned Verbose : 1; - /// \brief If true, skip verifying input files used by modules if the + /// If true, skip verifying input files used by modules if the /// module was already verified during this build session (see /// \c BuildSessionTimestamp). unsigned ModulesValidateOncePerBuildSession : 1; - /// \brief Whether to validate system input files when a module is loaded. + /// Whether to validate system input files when a module is loaded. unsigned ModulesValidateSystemHeaders : 1; /// Whether the module includes debug information (-gmodules). diff --git a/include/clang/Lex/Lexer.h b/include/clang/Lex/Lexer.h index d58849654cb83..624151ef877b0 100644 --- a/include/clang/Lex/Lexer.h +++ b/include/clang/Lex/Lexer.h @@ -57,10 +57,10 @@ enum ConflictMarkerKind { /// PreprocessorOptions::PrecompiledPreambleBytes. /// The preamble includes the BOM, if any. struct PreambleBounds { - /// \brief Size of the preamble in bytes. + /// Size of the preamble in bytes. unsigned Size; - /// \brief Whether the preamble ends at the start of a new line. + /// Whether the preamble ends at the start of a new line. /// /// Used to inform the lexer as to whether it's starting at the beginning of /// a line after skipping the preamble. @@ -263,7 +263,7 @@ public: return getSourceLocation(BufferPtr); } - /// \brief Return the current location in the buffer. + /// Return the current location in the buffer. const char *getBufferLocation() const { return BufferPtr; } /// Stringify - Convert the specified string into a C string by i) escaping @@ -322,29 +322,39 @@ public: const SourceManager &SM, const LangOptions &LangOpts); - /// \brief Relex the token at the specified location. + /// Relex the token at the specified location. /// \returns true if there was a failure, false on success. static bool getRawToken(SourceLocation Loc, Token &Result, const SourceManager &SM, const LangOptions &LangOpts, bool IgnoreWhiteSpace = false); - /// \brief Given a location any where in a source buffer, find the location + /// Given a location any where in a source buffer, find the location /// that corresponds to the beginning of the token in which the original /// source location lands. static SourceLocation GetBeginningOfToken(SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts); + /// Get the physical length (including trigraphs and escaped newlines) of the + /// first \p Characters characters of the token starting at TokStart. + static unsigned getTokenPrefixLength(SourceLocation TokStart, + unsigned Characters, + const SourceManager &SM, + const LangOptions &LangOpts); + /// AdvanceToTokenCharacter - If the current SourceLocation specifies a /// location at the start of a token, return a new location that specifies a /// character within the token. This handles trigraphs and escaped newlines. static SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, - unsigned Character, + unsigned Characters, const SourceManager &SM, - const LangOptions &LangOpts); + const LangOptions &LangOpts) { + return TokStart.getLocWithOffset( + getTokenPrefixLength(TokStart, Characters, SM, LangOpts)); + } - /// \brief Computes the source location just past the end of the + /// Computes the source location just past the end of the /// token at this source location. /// /// This routine can be used to produce a source location that @@ -363,7 +373,7 @@ public: const SourceManager &SM, const LangOptions &LangOpts); - /// \brief Given a token range, produce a corresponding CharSourceRange that + /// Given a token range, produce a corresponding CharSourceRange that /// is not a token range. This allows the source range to be used by /// components that don't have access to the lexer and thus can't find the /// end of the range for themselves. @@ -383,7 +393,7 @@ public: : Range; } - /// \brief Returns true if the given MacroID location points at the first + /// Returns true if the given MacroID location points at the first /// token of the macro expansion. /// /// \param MacroBegin If non-null and function returns true, it is set to @@ -393,7 +403,7 @@ public: const LangOptions &LangOpts, SourceLocation *MacroBegin = nullptr); - /// \brief Returns true if the given MacroID location points at the last + /// Returns true if the given MacroID location points at the last /// token of the macro expansion. /// /// \param MacroEnd If non-null and function returns true, it is set to @@ -403,7 +413,7 @@ public: const LangOptions &LangOpts, SourceLocation *MacroEnd = nullptr); - /// \brief Accepts a range and returns a character range with file locations. + /// Accepts a range and returns a character range with file locations. /// /// Returns a null range if a part of the range resides inside a macro /// expansion or the range does not reside on the same FileID. @@ -433,13 +443,13 @@ public: const SourceManager &SM, const LangOptions &LangOpts); - /// \brief Returns a string for the source that the range encompasses. + /// Returns a string for the source that the range encompasses. static StringRef getSourceText(CharSourceRange Range, const SourceManager &SM, const LangOptions &LangOpts, bool *Invalid = nullptr); - /// \brief Retrieve the name of the immediate macro expansion. + /// Retrieve the name of the immediate macro expansion. /// /// This routine starts from a source location, and finds the name of the macro /// responsible for its immediate expansion. It looks through any intervening @@ -450,7 +460,7 @@ public: const SourceManager &SM, const LangOptions &LangOpts); - /// \brief Retrieve the name of the immediate macro expansion. + /// Retrieve the name of the immediate macro expansion. /// /// This routine starts from a source location, and finds the name of the /// macro responsible for its immediate expansion. It looks through any @@ -470,7 +480,7 @@ public: static StringRef getImmediateMacroNameForDiagnostics( SourceLocation Loc, const SourceManager &SM, const LangOptions &LangOpts); - /// \brief Compute the preamble of the given file. + /// Compute the preamble of the given file. /// /// The preamble of a file contains the initial comments, include directives, /// and other preprocessor directives that occur before the code in this @@ -496,7 +506,7 @@ public: const SourceManager &SM, const LangOptions &LangOpts); - /// \brief Checks that the given token is the first token that occurs after + /// Checks that the given token is the first token that occurs after /// the given location (this excludes comments and whitespace). Returns the /// location immediately after the specified token. If the token is not found /// or the location is inside a macro, the returned source location will be @@ -507,10 +517,10 @@ public: const LangOptions &LangOpts, bool SkipTrailingWhitespaceAndNewLine); - /// \brief Returns true if the given character could appear in an identifier. + /// Returns true if the given character could appear in an identifier. static bool isIdentifierBodyChar(char c, const LangOptions &LangOpts); - /// \brief Checks whether new line pointed by Str is preceded by escape + /// Checks whether new line pointed by Str is preceded by escape /// sequence. static bool isNewLineEscaped(const char *BufferStart, const char *Str); @@ -716,7 +726,7 @@ private: /// invalid. uint32_t tryReadUCN(const char *&CurPtr, const char *SlashLoc, Token *Tok); - /// \brief Try to consume a UCN as part of an identifier at the current + /// Try to consume a UCN as part of an identifier at the current /// location. /// \param CurPtr Initially points to the range of characters in the source /// buffer containing the '\'. Updated to point past the end of @@ -730,7 +740,7 @@ private: bool tryConsumeIdentifierUCN(const char *&CurPtr, unsigned Size, Token &Result); - /// \brief Try to consume an identifier character encoded in UTF-8. + /// Try to consume an identifier character encoded in UTF-8. /// \param CurPtr Points to the start of the (potential) UTF-8 code unit /// sequence. On success, updated to point past the end of it. /// \return \c true if a UTF-8 sequence mapping to an acceptable identifier diff --git a/include/clang/Lex/LiteralSupport.h b/include/clang/Lex/LiteralSupport.h index cc9223eb7dbb3..1b6bf6bcffb0e 100644 --- a/include/clang/Lex/LiteralSupport.h +++ b/include/clang/Lex/LiteralSupport.h @@ -50,7 +50,7 @@ class NumericLiteralParser { unsigned radix; - bool saw_exponent, saw_period, saw_ud_suffix; + bool saw_exponent, saw_period, saw_ud_suffix, saw_fixed_point_suffix; SmallString<32> UDSuffixBuf; @@ -69,11 +69,16 @@ public: bool isFloat128 : 1; // 1.0q uint8_t MicrosoftInteger; // Microsoft suffix extension i8, i16, i32, or i64. + bool isFract : 1; // 1.0hr/r/lr/uhr/ur/ulr + bool isAccum : 1; // 1.0hk/k/lk/uhk/uk/ulk + + bool isFixedPointLiteral() const { return saw_fixed_point_suffix; } + bool isIntegerLiteral() const { - return !saw_period && !saw_exponent; + return !saw_period && !saw_exponent && !isFixedPointLiteral(); } bool isFloatingLiteral() const { - return saw_period || saw_exponent; + return (saw_period || saw_exponent) && !isFixedPointLiteral(); } bool hasUDSuffix() const { @@ -105,6 +110,12 @@ public: /// literal exactly, and false otherwise. llvm::APFloat::opStatus GetFloatValue(llvm::APFloat &Result); + /// GetFixedPointValue - Convert this numeric literal value into a + /// scaled integer that represents this value. Returns true if an overflow + /// occurred when calculating the integral part of the scaled integer or + /// calculating the digit sequence of the exponent. + bool GetFixedPointValue(llvm::APInt &StoreVal, unsigned Scale); + private: void ParseNumberStartingWithZero(SourceLocation TokLoc); @@ -112,7 +123,7 @@ private: static bool isDigitSeparator(char C) { return C == '\''; } - /// \brief Determine whether the sequence of characters [Start, End) contains + /// Determine whether the sequence of characters [Start, End) contains /// any real digits (not digit separators). bool containsDigits(const char *Start, const char *End) { return Start != End && (Start + 1 != End || !isDigitSeparator(Start[0])); @@ -120,7 +131,7 @@ private: enum CheckSeparatorKind { CSK_BeforeDigits, CSK_AfterDigits }; - /// \brief Ensure that we don't have a digit separator here. + /// Ensure that we don't have a digit separator here. void checkSeparator(SourceLocation TokLoc, const char *Pos, CheckSeparatorKind IsAfterDigits); diff --git a/include/clang/Lex/MacroInfo.h b/include/clang/Lex/MacroInfo.h index 3029294209ec5..13e5313a9c301 100644 --- a/include/clang/Lex/MacroInfo.h +++ b/include/clang/Lex/MacroInfo.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::MacroInfo and clang::MacroDirective classes. +/// Defines the clang::MacroInfo and clang::MacroDirective classes. // //===----------------------------------------------------------------------===// @@ -34,20 +34,20 @@ class Module; class Preprocessor; class SourceManager; -/// \brief Encapsulates the data about a macro definition (e.g. its tokens). +/// Encapsulates the data about a macro definition (e.g. its tokens). /// /// There's an instance of this class for every #define. class MacroInfo { //===--------------------------------------------------------------------===// // State set when the macro is defined. - /// \brief The location the macro is defined. + /// The location the macro is defined. SourceLocation Location; - /// \brief The location of the last token in the macro. + /// The location of the last token in the macro. SourceLocation EndLocation; - /// \brief The list of arguments for a function-like macro. + /// The list of arguments for a function-like macro. /// /// ParameterList points to the first of NumParameters pointers. /// @@ -58,61 +58,61 @@ class MacroInfo { /// \see ParameterList unsigned NumParameters = 0; - /// \brief This is the list of tokens that the macro is defined to. + /// This is the list of tokens that the macro is defined to. SmallVector<Token, 8> ReplacementTokens; - /// \brief Length in characters of the macro definition. + /// Length in characters of the macro definition. mutable unsigned DefinitionLength; mutable bool IsDefinitionLengthCached : 1; - /// \brief True if this macro is function-like, false if it is object-like. + /// True if this macro is function-like, false if it is object-like. bool IsFunctionLike : 1; - /// \brief True if this macro is of the form "#define X(...)" or + /// True if this macro is of the form "#define X(...)" or /// "#define X(Y,Z,...)". /// /// The __VA_ARGS__ token should be replaced with the contents of "..." in an /// invocation. bool IsC99Varargs : 1; - /// \brief True if this macro is of the form "#define X(a...)". + /// True if this macro is of the form "#define X(a...)". /// /// The "a" identifier in the replacement list will be replaced with all /// arguments of the macro starting with the specified one. bool IsGNUVarargs : 1; - /// \brief True if this macro requires processing before expansion. + /// True if this macro requires processing before expansion. /// /// This is the case for builtin macros such as __LINE__, so long as they have /// not been redefined, but not for regular predefined macros from the /// "<built-in>" memory buffer (see Preprocessing::getPredefinesFileID). bool IsBuiltinMacro : 1; - /// \brief Whether this macro contains the sequence ", ## __VA_ARGS__" + /// Whether this macro contains the sequence ", ## __VA_ARGS__" bool HasCommaPasting : 1; //===--------------------------------------------------------------------===// // State that changes as the macro is used. - /// \brief True if we have started an expansion of this macro already. + /// True if we have started an expansion of this macro already. /// /// This disables recursive expansion, which would be quite bad for things /// like \#define A A. bool IsDisabled : 1; - /// \brief True if this macro is either defined in the main file and has + /// True if this macro is either defined in the main file and has /// been used, or if it is not defined in the main file. /// /// This is used to emit -Wunused-macros diagnostics. bool IsUsed : 1; - /// \brief True if this macro can be redefined without emitting a warning. + /// True if this macro can be redefined without emitting a warning. bool IsAllowRedefinitionsWithoutWarning : 1; - /// \brief Must warn if the macro is unused at the end of translation unit. + /// Must warn if the macro is unused at the end of translation unit. bool IsWarnIfUnused : 1; - /// \brief Whether this macro was used as header guard. + /// Whether this macro was used as header guard. bool UsedForHeaderGuard : 1; // Only the Preprocessor gets to create and destroy these. @@ -120,23 +120,23 @@ class MacroInfo { ~MacroInfo() = default; public: - /// \brief Return the location that the macro was defined at. + /// Return the location that the macro was defined at. SourceLocation getDefinitionLoc() const { return Location; } - /// \brief Set the location of the last token in the macro. + /// Set the location of the last token in the macro. void setDefinitionEndLoc(SourceLocation EndLoc) { EndLocation = EndLoc; } - /// \brief Return the location of the last token in the macro. + /// Return the location of the last token in the macro. SourceLocation getDefinitionEndLoc() const { return EndLocation; } - /// \brief Get length in characters of the macro definition. + /// Get length in characters of the macro definition. unsigned getDefinitionLength(const SourceManager &SM) const { if (IsDefinitionLengthCached) return DefinitionLength; return getDefinitionLengthSlow(SM); } - /// \brief Return true if the specified macro definition is equal to + /// Return true if the specified macro definition is equal to /// this macro in spelling, arguments, and whitespace. /// /// \param Syntactically if true, the macro definitions can be identical even @@ -146,21 +146,21 @@ public: bool isIdenticalTo(const MacroInfo &Other, Preprocessor &PP, bool Syntactically) const; - /// \brief Set or clear the isBuiltinMacro flag. + /// Set or clear the isBuiltinMacro flag. void setIsBuiltinMacro(bool Val = true) { IsBuiltinMacro = Val; } - /// \brief Set the value of the IsUsed flag. + /// Set the value of the IsUsed flag. void setIsUsed(bool Val) { IsUsed = Val; } - /// \brief Set the value of the IsAllowRedefinitionsWithoutWarning flag. + /// Set the value of the IsAllowRedefinitionsWithoutWarning flag. void setIsAllowRedefinitionsWithoutWarning(bool Val) { IsAllowRedefinitionsWithoutWarning = Val; } - /// \brief Set the value of the IsWarnIfUnused flag. + /// Set the value of the IsWarnIfUnused flag. void setIsWarnIfUnused(bool val) { IsWarnIfUnused = val; } - /// \brief Set the specified list of identifiers as the parameter list for + /// Set the specified list of identifiers as the parameter list for /// this macro. void setParameterList(ArrayRef<IdentifierInfo *> List, llvm::BumpPtrAllocator &PPAllocator) { @@ -185,7 +185,7 @@ public: return ArrayRef<const IdentifierInfo *>(ParameterList, NumParameters); } - /// \brief Return the parameter number of the specified identifier, + /// Return the parameter number of the specified identifier, /// or -1 if the identifier is not a formal parameter identifier. int getParameterNum(const IdentifierInfo *Arg) const { for (param_iterator I = param_begin(), E = param_end(); I != E; ++I) @@ -207,7 +207,7 @@ public: bool isGNUVarargs() const { return IsGNUVarargs; } bool isVariadic() const { return IsC99Varargs | IsGNUVarargs; } - /// \brief Return true if this macro requires processing before expansion. + /// Return true if this macro requires processing before expansion. /// /// This is true only for builtin macro, such as \__LINE__, whose values /// are not given by fixed textual expansions. Regular predefined macros @@ -218,19 +218,19 @@ public: bool hasCommaPasting() const { return HasCommaPasting; } void setHasCommaPasting() { HasCommaPasting = true; } - /// \brief Return false if this macro is defined in the main file and has + /// Return false if this macro is defined in the main file and has /// not yet been used. bool isUsed() const { return IsUsed; } - /// \brief Return true if this macro can be redefined without warning. + /// Return true if this macro can be redefined without warning. bool isAllowRedefinitionsWithoutWarning() const { return IsAllowRedefinitionsWithoutWarning; } - /// \brief Return true if we should emit a warning if the macro is unused. + /// Return true if we should emit a warning if the macro is unused. bool isWarnIfUnused() const { return IsWarnIfUnused; } - /// \brief Return the number of tokens that this macro expands to. + /// Return the number of tokens that this macro expands to. unsigned getNumTokens() const { return ReplacementTokens.size(); } const Token &getReplacementToken(unsigned Tok) const { @@ -245,7 +245,7 @@ public: bool tokens_empty() const { return ReplacementTokens.empty(); } ArrayRef<Token> tokens() const { return ReplacementTokens; } - /// \brief Add the specified token to the replacement text for the macro. + /// Add the specified token to the replacement text for the macro. void AddTokenToBody(const Token &Tok) { assert( !IsDefinitionLengthCached && @@ -253,7 +253,7 @@ public: ReplacementTokens.push_back(Tok); } - /// \brief Return true if this macro is enabled. + /// Return true if this macro is enabled. /// /// In other words, that we are not currently in an expansion of this macro. bool isEnabled() const { return !IsDisabled; } @@ -268,7 +268,7 @@ public: IsDisabled = true; } - /// \brief Determine whether this macro was used for a header guard. + /// Determine whether this macro was used for a header guard. bool isUsedForHeaderGuard() const { return UsedForHeaderGuard; } void setUsedForHeaderGuard(bool Val) { UsedForHeaderGuard = Val; } @@ -281,7 +281,7 @@ private: unsigned getDefinitionLengthSlow(const SourceManager &SM) const; }; -/// \brief Encapsulates changes to the "macros namespace" (the location where +/// Encapsulates changes to the "macros namespace" (the location where /// the macro name became active, the location where it was undefined, etc.). /// /// MacroDirectives, associated with an identifier, are used to model the macro @@ -297,20 +297,20 @@ public: }; protected: - /// \brief Previous macro directive for the same identifier, or nullptr. + /// Previous macro directive for the same identifier, or nullptr. MacroDirective *Previous = nullptr; SourceLocation Loc; - /// \brief MacroDirective kind. + /// MacroDirective kind. unsigned MDKind : 2; - /// \brief True if the macro directive was loaded from a PCH file. + /// True if the macro directive was loaded from a PCH file. unsigned IsFromPCH : 1; // Used by VisibilityMacroDirective ----------------------------------------// - /// \brief Whether the macro has public visibility (when described in a + /// Whether the macro has public visibility (when described in a /// module). unsigned IsPublic : 1; @@ -322,16 +322,16 @@ public: SourceLocation getLocation() const { return Loc; } - /// \brief Set previous definition of the macro with the same name. + /// Set previous definition of the macro with the same name. void setPrevious(MacroDirective *Prev) { Previous = Prev; } - /// \brief Get previous definition of the macro with the same name. + /// Get previous definition of the macro with the same name. const MacroDirective *getPrevious() const { return Previous; } - /// \brief Get previous definition of the macro with the same name. + /// Get previous definition of the macro with the same name. MacroDirective *getPrevious() { return Previous; } - /// \brief Return true if the macro directive was loaded from a PCH file. + /// Return true if the macro directive was loaded from a PCH file. bool isFromPCH() const { return IsFromPCH; } void setIsFromPCH() { IsFromPCH = true; } @@ -374,7 +374,7 @@ public: } }; - /// \brief Traverses the macro directives history and returns the next + /// Traverses the macro directives history and returns the next /// macro definition directive along with info about its undefined location /// (if there is one) and if it is public or private. DefInfo getDefinition(); @@ -393,7 +393,7 @@ public: } MacroInfo *getMacroInfo() { return getDefinition().getMacroInfo(); } - /// \brief Find macro definition active in the specified source location. If + /// Find macro definition active in the specified source location. If /// this macro was not defined there, return NULL. const DefInfo findDirectiveAtLoc(SourceLocation L, SourceManager &SM) const; @@ -402,7 +402,7 @@ public: static bool classof(const MacroDirective *) { return true; } }; -/// \brief A directive for a defined macro or a macro imported from a module. +/// A directive for a defined macro or a macro imported from a module. class DefMacroDirective : public MacroDirective { MacroInfo *Info; @@ -414,7 +414,7 @@ public: explicit DefMacroDirective(MacroInfo *MI) : DefMacroDirective(MI, MI->getDefinitionLoc()) {} - /// \brief The data for the macro definition. + /// The data for the macro definition. const MacroInfo *getInfo() const { return Info; } MacroInfo *getInfo() { return Info; } @@ -425,7 +425,7 @@ public: static bool classof(const DefMacroDirective *) { return true; } }; -/// \brief A directive for an undefined macro. +/// A directive for an undefined macro. class UndefMacroDirective : public MacroDirective { public: explicit UndefMacroDirective(SourceLocation UndefLoc) @@ -440,7 +440,7 @@ public: static bool classof(const UndefMacroDirective *) { return true; } }; -/// \brief A directive for setting the module visibility of a macro. +/// A directive for setting the module visibility of a macro. class VisibilityMacroDirective : public MacroDirective { public: explicit VisibilityMacroDirective(SourceLocation Loc, bool Public) @@ -448,7 +448,7 @@ public: IsPublic = Public; } - /// \brief Determine whether this macro is part of the public API of its + /// Determine whether this macro is part of the public API of its /// module. bool isPublic() const { return IsPublic; } @@ -478,7 +478,7 @@ MacroDirective::DefInfo::getPreviousDefinition() { return DefDirective->getPrevious()->getDefinition(); } -/// \brief Represents a macro directive exported by a module. +/// Represents a macro directive exported by a module. /// /// There's an instance of this class for every macro #define or #undef that is /// the final directive for a macro name within a module. These entities also @@ -557,7 +557,7 @@ public: unsigned getNumOverridingMacros() const { return NumOverriddenBy; } }; -/// \brief A description of the current definition of a macro. +/// A description of the current definition of a macro. /// /// The definition of a macro comprises a set of (at least one) defining /// entities, which are either local MacroDirectives or imported ModuleMacros. @@ -571,12 +571,12 @@ public: bool IsAmbiguous) : LatestLocalAndAmbiguous(MD, IsAmbiguous), ModuleMacros(MMs) {} - /// \brief Determine whether there is a definition of this macro. + /// Determine whether there is a definition of this macro. explicit operator bool() const { return getLocalDirective() || !ModuleMacros.empty(); } - /// \brief Get the MacroInfo that should be used for this definition. + /// Get the MacroInfo that should be used for this definition. MacroInfo *getMacroInfo() const { if (!ModuleMacros.empty()) return ModuleMacros.back()->getMacroInfo(); @@ -585,16 +585,16 @@ public: return nullptr; } - /// \brief \c true if the definition is ambiguous, \c false otherwise. + /// \c true if the definition is ambiguous, \c false otherwise. bool isAmbiguous() const { return LatestLocalAndAmbiguous.getInt(); } - /// \brief Get the latest non-imported, non-\#undef'd macro definition + /// Get the latest non-imported, non-\#undef'd macro definition /// for this macro. DefMacroDirective *getLocalDirective() const { return LatestLocalAndAmbiguous.getPointer(); } - /// \brief Get the active module macros for this macro. + /// Get the active module macros for this macro. ArrayRef<ModuleMacro *> getModuleMacros() const { return ModuleMacros; } template <typename Fn> void forAllDefinitions(Fn F) const { diff --git a/include/clang/Lex/ModuleLoader.h b/include/clang/Lex/ModuleLoader.h index 30ea583b71e0b..a2766fa35984f 100644 --- a/include/clang/Lex/ModuleLoader.h +++ b/include/clang/Lex/ModuleLoader.h @@ -28,11 +28,11 @@ namespace clang { class GlobalModuleIndex; class IdentifierInfo; -/// \brief A sequence of identifier/location pairs used to describe a particular +/// A sequence of identifier/location pairs used to describe a particular /// module or submodule, e.g., std.vector. using ModuleIdPath = ArrayRef<std::pair<IdentifierInfo *, SourceLocation>>; -/// \brief Describes the result of attempting to load a module. +/// Describes the result of attempting to load a module. class ModuleLoadResult { public: enum LoadResultKind { @@ -55,18 +55,18 @@ public: operator Module *() const { return Storage.getPointer(); } - /// \brief Determines whether the module, which failed to load, was + /// Determines whether the module, which failed to load, was /// actually a submodule that we expected to see (based on implying the /// submodule from header structure), but didn't materialize in the actual /// module. bool isMissingExpected() const { return Storage.getInt() == MissingExpected; } - /// \brief Determines whether the module failed to load due to a configuration + /// Determines whether the module failed to load due to a configuration /// mismatch with an explicitly-named .pcm file from the command line. bool isConfigMismatch() const { return Storage.getInt() == ConfigMismatch; } }; -/// \brief Abstract interface for a module loader. +/// Abstract interface for a module loader. /// /// This abstract interface describes a module loader, which is responsible /// for resolving a module name (e.g., "std") to an actual module file, and @@ -81,17 +81,17 @@ public: virtual ~ModuleLoader(); - /// \brief Returns true if this instance is building a module. + /// Returns true if this instance is building a module. bool buildingModule() const { return BuildingModule; } - /// \brief Flag indicating whether this instance is building a module. + /// Flag indicating whether this instance is building a module. void setBuildingModule(bool BuildingModuleFlag) { BuildingModule = BuildingModuleFlag; } - /// \brief Attempt to load the given module. + /// Attempt to load the given module. /// /// This routine attempts to load the module described by the given /// parameters. @@ -125,12 +125,12 @@ public: virtual void loadModuleFromSource(SourceLocation Loc, StringRef ModuleName, StringRef Source) = 0; - /// \brief Make the given module visible. + /// Make the given module visible. virtual void makeModuleVisible(Module *Mod, Module::NameVisibilityKind Visibility, SourceLocation ImportLoc) = 0; - /// \brief Load, create, or return global module. + /// Load, create, or return global module. /// This function returns an existing global module index, if one /// had already been loaded or created, or loads one if it /// exists, or creates one if it doesn't exist. diff --git a/include/clang/Lex/ModuleMap.h b/include/clang/Lex/ModuleMap.h index 41ed8e49b6c1d..577f4008978ea 100644 --- a/include/clang/Lex/ModuleMap.h +++ b/include/clang/Lex/ModuleMap.h @@ -21,6 +21,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" @@ -41,13 +42,13 @@ class FileManager; class HeaderSearch; class SourceManager; -/// \brief A mechanism to observe the actions of the module map parser as it +/// A mechanism to observe the actions of the module map parser as it /// reads module map files. class ModuleMapCallbacks { public: virtual ~ModuleMapCallbacks() = default; - /// \brief Called when a module map file has been read. + /// Called when a module map file has been read. /// /// \param FileStart A SourceLocation referring to the start of the file's /// contents. @@ -56,12 +57,12 @@ public: virtual void moduleMapFileRead(SourceLocation FileStart, const FileEntry &File, bool IsSystem) {} - /// \brief Called when a header is added during module map parsing. + /// Called when a header is added during module map parsing. /// /// \param Filename The header file itself. virtual void moduleMapAddHeader(StringRef Filename) {} - /// \brief Called when an umbrella header is added during module map parsing. + /// Called when an umbrella header is added during module map parsing. /// /// \param FileMgr FileManager instance /// \param Header The umbrella header to collect. @@ -78,11 +79,11 @@ class ModuleMap { llvm::SmallVector<std::unique_ptr<ModuleMapCallbacks>, 1> Callbacks; - /// \brief The directory used for Clang-supplied, builtin include headers, + /// The directory used for Clang-supplied, builtin include headers, /// such as "stdint.h". const DirectoryEntry *BuiltinIncludeDir = nullptr; - /// \brief Language options used to parse the module map itself. + /// Language options used to parse the module map itself. /// /// These are always simple C language options. LangOptions MMapLangOpts; @@ -95,22 +96,37 @@ class ModuleMap { /// transferred if/when we create an enclosing module. std::unique_ptr<Module> PendingGlobalModule; - /// \brief The top-level modules that are known. + /// The top-level modules that are known. llvm::StringMap<Module *> Modules; - /// \brief The number of modules we have created in total. + /// Shadow modules created while building this module map. + llvm::SmallVector<Module*, 2> ShadowModules; + + /// The number of modules we have created in total. unsigned NumCreatedModules = 0; + /// In case a module has a export_as entry, it might have a pending link + /// name to be determined if that module is imported. + llvm::StringMap<llvm::StringSet<>> PendingLinkAsModule; + public: - /// \brief Flags describing the role of a module header. + /// Use PendingLinkAsModule information to mark top level link names that + /// are going to be replaced by export_as aliases. + void resolveLinkAsDependencies(Module *Mod); + + /// Make module to use export_as as the link dependency name if enough + /// information is available or add it to a pending list otherwise. + void addLinkAsDependency(Module *Mod); + + /// Flags describing the role of a module header. enum ModuleHeaderRole { - /// \brief This header is normally included in the module. + /// This header is normally included in the module. NormalHeader = 0x0, - /// \brief This header is included but private. + /// This header is included but private. PrivateHeader = 0x1, - /// \brief This header is part of the module (for layering purposes) but + /// This header is part of the module (for layering purposes) but /// should be textually included. TextualHeader = 0x2, @@ -128,7 +144,7 @@ public: /// Convert a header role to a kind. static Module::HeaderKind headerRoleToKind(ModuleHeaderRole Role); - /// \brief A header that is known to reside within a given module, + /// A header that is known to reside within a given module, /// whether it was included or excluded. class KnownHeader { llvm::PointerIntPair<Module *, 2, ModuleHeaderRole> Storage; @@ -144,24 +160,24 @@ public: return A.Storage != B.Storage; } - /// \brief Retrieve the module the header is stored in. + /// Retrieve the module the header is stored in. Module *getModule() const { return Storage.getPointer(); } - /// \brief The role of this header within the module. + /// The role of this header within the module. ModuleHeaderRole getRole() const { return Storage.getInt(); } - /// \brief Whether this header is available in the module. + /// Whether this header is available in the module. bool isAvailable() const { return getModule()->isAvailable(); } - /// \brief Whether this header is accessible from the specified module. + /// Whether this header is accessible from the specified module. bool isAccessibleFrom(Module *M) const { return !(getRole() & PrivateHeader) || (M && M->getTopLevelModule() == getModule()->getTopLevelModule()); } - // \brief Whether this known header is valid (i.e., it has an + // Whether this known header is valid (i.e., it has an // associated module). explicit operator bool() const { return Storage.getPointer() != nullptr; @@ -176,7 +192,7 @@ private: using HeadersMap = llvm::DenseMap<const FileEntry *, SmallVector<KnownHeader, 1>>; - /// \brief Mapping from each header to the module that owns the contents of + /// Mapping from each header to the module that owns the contents of /// that header. HeadersMap Headers; @@ -187,7 +203,7 @@ private: mutable llvm::DenseMap<time_t, llvm::TinyPtrVector<Module*>> LazyHeadersByModTime; - /// \brief Mapping from directories with umbrella headers to the module + /// Mapping from directories with umbrella headers to the module /// that is generated from the umbrella header. /// /// This mapping is used to map headers that haven't explicitly been named @@ -195,18 +211,27 @@ private: /// header. llvm::DenseMap<const DirectoryEntry *, Module *> UmbrellaDirs; - /// \brief The set of attributes that can be attached to a module. + /// A generation counter that is used to test whether modules of the + /// same name may shadow or are illegal redefinitions. + /// + /// Modules from earlier scopes may shadow modules from later ones. + /// Modules from the same scope may not have the same name. + unsigned CurrentModuleScopeID = 0; + + llvm::DenseMap<Module *, unsigned> ModuleScopeIDs; + + /// The set of attributes that can be attached to a module. struct Attributes { - /// \brief Whether this is a system module. + /// Whether this is a system module. unsigned IsSystem : 1; - /// \brief Whether this is an extern "C" module. + /// Whether this is an extern "C" module. unsigned IsExternC : 1; - /// \brief Whether this is an exhaustive set of configuration macros. + /// Whether this is an exhaustive set of configuration macros. unsigned IsExhaustive : 1; - /// \brief Whether files in this module can only include non-modular headers + /// Whether files in this module can only include non-modular headers /// and headers from used modules. unsigned NoUndeclaredIncludes : 1; @@ -215,26 +240,26 @@ private: NoUndeclaredIncludes(false) {} }; - /// \brief A directory for which framework modules can be inferred. + /// A directory for which framework modules can be inferred. struct InferredDirectory { - /// \brief Whether to infer modules from this directory. + /// Whether to infer modules from this directory. unsigned InferModules : 1; - /// \brief The attributes to use for inferred modules. + /// The attributes to use for inferred modules. Attributes Attrs; - /// \brief If \c InferModules is non-zero, the module map file that allowed + /// If \c InferModules is non-zero, the module map file that allowed /// inferred modules. Otherwise, nullptr. const FileEntry *ModuleMapFile; - /// \brief The names of modules that cannot be inferred within this + /// The names of modules that cannot be inferred within this /// directory. SmallVector<std::string, 2> ExcludedModules; InferredDirectory() : InferModules(false) {} }; - /// \brief A mapping from directories to information about inferring + /// A mapping from directories to information about inferring /// framework modules from within those directories. llvm::DenseMap<const DirectoryEntry *, InferredDirectory> InferredDirectories; @@ -244,11 +269,11 @@ private: llvm::DenseMap<const Module *, AdditionalModMapsSet> AdditionalModMaps; - /// \brief Describes whether we haved parsed a particular file as a module + /// Describes whether we haved parsed a particular file as a module /// map. llvm::DenseMap<const FileEntry *, bool> ParsedModuleMap; - /// \brief Resolve the given export declaration into an actual export + /// Resolve the given export declaration into an actual export /// declaration. /// /// \param Mod The module in which we're resolving the export declaration. @@ -264,7 +289,7 @@ private: resolveExport(Module *Mod, const Module::UnresolvedExportDecl &Unresolved, bool Complain) const; - /// \brief Resolve the given module id to an actual module. + /// Resolve the given module id to an actual module. /// /// \param Id The module-id to resolve. /// @@ -278,8 +303,15 @@ private: Module *resolveModuleId(const ModuleId &Id, Module *Mod, bool Complain) const; /// Add an unresolved header to a module. + /// + /// \param Mod The module in which we're adding the unresolved header + /// directive. + /// \param Header The unresolved header directive. + /// \param NeedsFramework If Mod is not a framework but a missing header would + /// be found in case Mod was, set it to true. False otherwise. void addUnresolvedHeader(Module *Mod, - Module::UnresolvedHeaderDirective Header); + Module::UnresolvedHeaderDirective Header, + bool &NeedsFramework); /// Look up the given header directive to find an actual header file. /// @@ -287,14 +319,22 @@ private: /// \param Header The header directive to resolve. /// \param RelativePathName Filled in with the relative path name from the /// module to the resolved header. + /// \param NeedsFramework If M is not a framework but a missing header would + /// be found in case M was, set it to true. False otherwise. /// \return The resolved file, if any. const FileEntry *findHeader(Module *M, const Module::UnresolvedHeaderDirective &Header, - SmallVectorImpl<char> &RelativePathName); + SmallVectorImpl<char> &RelativePathName, + bool &NeedsFramework); /// Resolve the given header directive. - void resolveHeader(Module *M, - const Module::UnresolvedHeaderDirective &Header); + /// + /// \param M The module in which we're resolving the header directive. + /// \param Header The header directive to resolve. + /// \param NeedsFramework If M is not a framework but a missing header would + /// be found in case M was, set it to true. False otherwise. + void resolveHeader(Module *M, const Module::UnresolvedHeaderDirective &Header, + bool &NeedsFramework); /// Attempt to resolve the specified header directive as naming a builtin /// header. @@ -302,14 +342,14 @@ private: bool resolveAsBuiltinHeader(Module *M, const Module::UnresolvedHeaderDirective &Header); - /// \brief Looks up the modules that \p File corresponds to. + /// Looks up the modules that \p File corresponds to. /// /// If \p File represents a builtin header within Clang's builtin include /// directory, this also loads all of the module maps to see if it will get /// associated with a specific module (e.g. in /usr/include). HeadersMap::iterator findKnownHeader(const FileEntry *File); - /// \brief Searches for a module whose umbrella directory contains \p File. + /// Searches for a module whose umbrella directory contains \p File. /// /// \param File The header to search for. /// @@ -318,11 +358,11 @@ private: KnownHeader findHeaderInUmbrellaDirs(const FileEntry *File, SmallVectorImpl<const DirectoryEntry *> &IntermediateDirs); - /// \brief Given that \p File is not in the Headers map, look it up within + /// Given that \p File is not in the Headers map, look it up within /// umbrella directories and find or create a module for it. KnownHeader findOrCreateModuleForHeaderInUmbrellaDir(const FileEntry *File); - /// \brief A convenience method to determine if \p File is (possibly nested) + /// A convenience method to determine if \p File is (possibly nested) /// in an umbrella directory. bool isHeaderInUmbrellaDirs(const FileEntry *File) { SmallVector<const DirectoryEntry *, 2> IntermediateDirs; @@ -333,7 +373,7 @@ private: Attributes Attrs, Module *Parent); public: - /// \brief Construct a new module map. + /// Construct a new module map. /// /// \param SourceMgr The source manager used to find module files and headers. /// This source manager should be shared with the header-search mechanism, @@ -348,32 +388,32 @@ public: const LangOptions &LangOpts, const TargetInfo *Target, HeaderSearch &HeaderInfo); - /// \brief Destroy the module map. + /// Destroy the module map. ~ModuleMap(); - /// \brief Set the target information. + /// Set the target information. void setTarget(const TargetInfo &Target); - /// \brief Set the directory that contains Clang-supplied include + /// Set the directory that contains Clang-supplied include /// files, such as our stdarg.h or tgmath.h. void setBuiltinIncludeDir(const DirectoryEntry *Dir) { BuiltinIncludeDir = Dir; } - /// \brief Get the directory that contains Clang-supplied include files. + /// Get the directory that contains Clang-supplied include files. const DirectoryEntry *getBuiltinDir() const { return BuiltinIncludeDir; } - /// \brief Is this a compiler builtin header? + /// Is this a compiler builtin header? static bool isBuiltinHeader(StringRef FileName); - /// \brief Add a module map callback. + /// Add a module map callback. void addModuleMapCallbacks(std::unique_ptr<ModuleMapCallbacks> Callback) { Callbacks.push_back(std::move(Callback)); } - /// \brief Retrieve the module that owns the given header file, if any. + /// Retrieve the module that owns the given header file, if any. /// /// \param File The header file that is likely to be included. /// @@ -387,7 +427,7 @@ public: KnownHeader findModuleForHeader(const FileEntry *File, bool AllowTextual = false); - /// \brief Retrieve all the modules that contain the given header file. This + /// Retrieve all the modules that contain the given header file. This /// may not include umbrella modules, nor information from external sources, /// if they have not yet been inferred / loaded. /// @@ -404,7 +444,7 @@ public: /// Resolve all lazy header directives for the specified module. void resolveHeaderDirectives(Module *Mod) const; - /// \brief Reports errors if a module must not include a specific file. + /// Reports errors if a module must not include a specific file. /// /// \param RequestingModule The module including a file. /// @@ -423,23 +463,23 @@ public: SourceLocation FilenameLoc, StringRef Filename, const FileEntry *File); - /// \brief Determine whether the given header is part of a module + /// Determine whether the given header is part of a module /// marked 'unavailable'. bool isHeaderInUnavailableModule(const FileEntry *Header) const; - /// \brief Determine whether the given header is unavailable as part + /// Determine whether the given header is unavailable as part /// of the specified module. bool isHeaderUnavailableInModule(const FileEntry *Header, const Module *RequestingModule) const; - /// \brief Retrieve a module with the given name. + /// Retrieve a module with the given name. /// /// \param Name The name of the module to look up. /// /// \returns The named module, if known; otherwise, returns null. Module *findModule(StringRef Name) const; - /// \brief Retrieve a module with the given name using lexical name lookup, + /// Retrieve a module with the given name using lexical name lookup, /// starting at the given context. /// /// \param Name The name of the module to look up. @@ -450,7 +490,7 @@ public: /// \returns The named module, if known; otherwise, returns null. Module *lookupModuleUnqualified(StringRef Name, Module *Context) const; - /// \brief Retrieve a module with the given name within the given context, + /// Retrieve a module with the given name within the given context, /// using direct (qualified) name lookup. /// /// \param Name The name of the module to look up. @@ -461,7 +501,7 @@ public: /// \returns The named submodule, if known; otherwose, returns null. Module *lookupModuleQualified(StringRef Name, Module *Context) const; - /// \brief Find a new module or submodule, or create it if it does not already + /// Find a new module or submodule, or create it if it does not already /// exist. /// /// \param Name The name of the module to find or create. @@ -479,7 +519,7 @@ public: bool IsFramework, bool IsExplicit); - /// \brief Create a 'global module' for a C++ Modules TS module interface + /// Create a 'global module' for a C++ Modules TS module interface /// unit. /// /// We model the global module as a submodule of the module interface unit. @@ -487,7 +527,7 @@ public: /// later, because we don't know what it will be called. Module *createGlobalModuleForInterfaceUnit(SourceLocation Loc); - /// \brief Create a new module for a C++ Modules TS module interface unit. + /// Create a new module for a C++ Modules TS module interface unit. /// The module must not already exist, and will be configured for the current /// compilation. /// @@ -497,12 +537,30 @@ public: Module *createModuleForInterfaceUnit(SourceLocation Loc, StringRef Name, Module *GlobalModule); - /// \brief Infer the contents of a framework module map from the given + /// Infer the contents of a framework module map from the given /// framework directory. Module *inferFrameworkModule(const DirectoryEntry *FrameworkDir, bool IsSystem, Module *Parent); - /// \brief Retrieve the module map file containing the definition of the given + /// Create a new top-level module that is shadowed by + /// \p ShadowingModule. + Module *createShadowedModule(StringRef Name, bool IsFramework, + Module *ShadowingModule); + + /// Creates a new declaration scope for module names, allowing + /// previously defined modules to shadow definitions from the new scope. + /// + /// \note Module names from earlier scopes will shadow names from the new + /// scope, which is the opposite of how shadowing works for variables. + void finishModuleDeclarationScope() { CurrentModuleScopeID += 1; } + + bool mayShadowNewModule(Module *ExistingModule) { + assert(!ExistingModule->Parent && "expected top-level module"); + assert(ModuleScopeIDs.count(ExistingModule) && "unknown module"); + return ModuleScopeIDs[ExistingModule] < CurrentModuleScopeID; + } + + /// Retrieve the module map file containing the definition of the given /// module. /// /// \param Module The module whose module map file will be returned, if known. @@ -511,7 +569,7 @@ public: /// module, or nullptr if the module definition was inferred. const FileEntry *getContainingModuleMapFile(const Module *Module) const; - /// \brief Get the module map file that (along with the module name) uniquely + /// 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 @@ -524,7 +582,7 @@ public: void setInferredModuleAllowedBy(Module *M, const FileEntry *ModuleMap); - /// \brief Get any module map files other than getModuleMapFileForUniquing(M) + /// 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. @@ -539,7 +597,7 @@ public: AdditionalModMaps[M].insert(ModuleMap); } - /// \brief Resolve all of the unresolved exports in the given module. + /// Resolve all of the unresolved exports in the given module. /// /// \param Mod The module whose exports should be resolved. /// @@ -549,7 +607,7 @@ public: /// false otherwise. bool resolveExports(Module *Mod, bool Complain); - /// \brief Resolve all of the unresolved uses in the given module. + /// Resolve all of the unresolved uses in the given module. /// /// \param Mod The module whose uses should be resolved. /// @@ -559,7 +617,7 @@ public: /// false otherwise. bool resolveUses(Module *Mod, bool Complain); - /// \brief Resolve all of the unresolved conflicts in the given module. + /// Resolve all of the unresolved conflicts in the given module. /// /// \param Mod The module whose conflicts should be resolved. /// @@ -569,25 +627,25 @@ public: /// false otherwise. bool resolveConflicts(Module *Mod, bool Complain); - /// \brief Sets the umbrella header of the given module to the given + /// Sets the umbrella header of the given module to the given /// header. void setUmbrellaHeader(Module *Mod, const FileEntry *UmbrellaHeader, Twine NameAsWritten); - /// \brief Sets the umbrella directory of the given module to the given + /// Sets the umbrella directory of the given module to the given /// directory. void setUmbrellaDir(Module *Mod, const DirectoryEntry *UmbrellaDir, Twine NameAsWritten); - /// \brief Adds this header to the given module. + /// Adds this header to the given module. /// \param Role The role of the header wrt the module. void addHeader(Module *Mod, Module::Header Header, ModuleHeaderRole Role, bool Imported = false); - /// \brief Marks this header as being excluded from the given module. + /// 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 + /// Parse the given module map file, and record any modules we /// encounter. /// /// \param File The file to be parsed. @@ -608,11 +666,11 @@ public: /// /// \returns true if an error occurred, false otherwise. bool parseModuleMapFile(const FileEntry *File, bool IsSystem, - const DirectoryEntry *HomeDir, FileID ID = FileID(), - unsigned *Offset = nullptr, + const DirectoryEntry *HomeDir, + FileID ID = FileID(), unsigned *Offset = nullptr, SourceLocation ExternModuleLoc = SourceLocation()); - /// \brief Dump the contents of the module map, for debugging purposes. + /// Dump the contents of the module map, for debugging purposes. void dump(); using module_iterator = llvm::StringMap<Module *>::const_iterator; diff --git a/include/clang/Lex/MultipleIncludeOpt.h b/include/clang/Lex/MultipleIncludeOpt.h index 3967f8688966f..ac0dcc7b51c25 100644 --- a/include/clang/Lex/MultipleIncludeOpt.h +++ b/include/clang/Lex/MultipleIncludeOpt.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the MultipleIncludeOpt interface. +/// Defines the MultipleIncludeOpt interface. // //===----------------------------------------------------------------------===// @@ -20,7 +20,7 @@ namespace clang { class IdentifierInfo; -/// \brief Implements the simple state machine that the Lexer class uses to +/// Implements the simple state machine that the Lexer class uses to /// detect files subject to the 'multiple-include' optimization. /// /// The public methods in this class are triggered by various @@ -113,13 +113,13 @@ public: /// buffer, this method is called to disable the MIOpt if needed. void ExpandedMacro() { DidMacroExpansion = true; } - /// \brief Called when entering a top-level \#ifndef directive (or the + /// Called when entering a top-level \#ifndef directive (or the /// "\#if !defined" equivalent) without any preceding tokens. /// /// Note, we don't care about the input value of 'ReadAnyTokens'. The caller /// ensures that this is only called if there are no tokens read before the /// \#ifndef. The caller is required to do this, because reading the \#if - /// line obviously reads in in tokens. + /// line obviously reads in tokens. void EnterTopLevelIfndef(const IdentifierInfo *M, SourceLocation Loc) { // If the macro is already set, this is after the top-level #endif. if (TheMacro) @@ -139,14 +139,14 @@ public: MacroLoc = Loc; } - /// \brief Invoked when a top level conditional (except \#ifndef) is found. + /// Invoked when a top level conditional (except \#ifndef) is found. void EnterTopLevelConditional() { // If a conditional directive (except #ifndef) is found at the top level, // there is a chunk of the file not guarded by the controlling macro. Invalidate(); } - /// \brief Called when the lexer exits the top-level conditional. + /// Called when the lexer exits the top-level conditional. void ExitTopLevelConditional() { // If we have a macro, that means the top of the file was ok. Set our state // back to "not having read any tokens" so we can detect anything after the @@ -159,7 +159,7 @@ public: ImmediatelyAfterTopLevelIfndef = false; } - /// \brief Once the entire file has been lexed, if there is a controlling + /// Once the entire file has been lexed, if there is a controlling /// macro, return it. const IdentifierInfo *GetControllingMacroAtEndOfFile() const { // If we haven't read any tokens after the #endif, return the controlling @@ -169,7 +169,7 @@ public: return nullptr; } - /// \brief If the ControllingMacro is followed by a macro definition, return + /// If the ControllingMacro is followed by a macro definition, return /// the macro that was defined. const IdentifierInfo *GetDefinedMacro() const { return DefinedMacro; diff --git a/include/clang/Lex/PPCallbacks.h b/include/clang/Lex/PPCallbacks.h index 19bce4dd32e88..eb85bda840afe 100644 --- a/include/clang/Lex/PPCallbacks.h +++ b/include/clang/Lex/PPCallbacks.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Defines the PPCallbacks interface. +/// Defines the PPCallbacks interface. /// //===----------------------------------------------------------------------===// @@ -29,7 +29,7 @@ namespace clang { class MacroDirective; class MacroArgs; -/// \brief This interface provides a way to observe the actions of the +/// This interface provides a way to observe the actions of the /// preprocessor as it does its thing. /// /// Clients can define their hooks here to implement preprocessor level tools. @@ -41,7 +41,7 @@ public: EnterFile, ExitFile, SystemHeaderPragma, RenameFile }; - /// \brief Callback invoked whenever a source file is entered or exited. + /// Callback invoked whenever a source file is entered or exited. /// /// \param Loc Indicates the new location. /// \param PrevFID the file that was exited if \p Reason is ExitFile. @@ -50,7 +50,7 @@ public: FileID PrevFID = FileID()) { } - /// \brief Callback invoked whenever a source file is skipped as the result + /// Callback invoked whenever a source file is skipped as the result /// of header guard optimization. /// /// \param SkippedFile The file that is skipped instead of entering \#include @@ -63,7 +63,7 @@ public: SrcMgr::CharacteristicKind FileType) { } - /// \brief Callback invoked whenever an inclusion directive results in a + /// Callback invoked whenever an inclusion directive results in a /// file-not-found error. /// /// \param FileName The name of the file being included, as written in the @@ -80,7 +80,7 @@ public: return false; } - /// \brief Callback invoked whenever an inclusion directive of + /// Callback invoked whenever an inclusion directive of /// any kind (\c \#include, \c \#import, etc.) has been processed, regardless /// of whether the inclusion will actually result in an inclusion. /// @@ -117,6 +117,10 @@ public: /// \param Imported The module, whenever an inclusion directive was /// automatically turned into a module import or null otherwise. /// + /// \param FileType The characteristic kind, indicates whether a file or + /// directory holds normal user code, system code, or system code which is + /// implicitly 'extern "C"' in C++ mode. + /// virtual void InclusionDirective(SourceLocation HashLoc, const Token &IncludeTok, StringRef FileName, @@ -125,10 +129,11 @@ public: const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) { + const Module *Imported, + SrcMgr::CharacteristicKind FileType) { } - /// \brief Callback invoked whenever there was an explicit module-import + /// Callback invoked whenever there was an explicit module-import /// syntax. /// /// \param ImportLoc The location of import directive token. @@ -143,54 +148,54 @@ public: const Module *Imported) { } - /// \brief Callback invoked when the end of the main file is reached. + /// Callback invoked when the end of the main file is reached. /// /// No subsequent callbacks will be made. virtual void EndOfMainFile() { } - /// \brief Callback invoked when a \#ident or \#sccs directive is read. + /// Callback invoked when a \#ident or \#sccs directive is read. /// \param Loc The location of the directive. /// \param str The text of the directive. /// virtual void Ident(SourceLocation Loc, StringRef str) { } - /// \brief Callback invoked when start reading any pragma directive. + /// Callback invoked when start reading any pragma directive. virtual void PragmaDirective(SourceLocation Loc, PragmaIntroducerKind Introducer) { } - /// \brief Callback invoked when a \#pragma comment directive is read. + /// Callback invoked when a \#pragma comment directive is read. virtual void PragmaComment(SourceLocation Loc, const IdentifierInfo *Kind, StringRef Str) { } - /// \brief Callback invoked when a \#pragma detect_mismatch directive is + /// Callback invoked when a \#pragma detect_mismatch directive is /// read. virtual void PragmaDetectMismatch(SourceLocation Loc, StringRef Name, StringRef Value) { } - /// \brief Callback invoked when a \#pragma clang __debug directive is read. + /// Callback invoked when a \#pragma clang __debug directive is read. /// \param Loc The location of the debug directive. /// \param DebugType The identifier following __debug. virtual void PragmaDebug(SourceLocation Loc, StringRef DebugType) { } - /// \brief Determines the kind of \#pragma invoking a call to PragmaMessage. + /// Determines the kind of \#pragma invoking a call to PragmaMessage. enum PragmaMessageKind { - /// \brief \#pragma message has been invoked. + /// \#pragma message has been invoked. PMK_Message, - /// \brief \#pragma GCC warning has been invoked. + /// \#pragma GCC warning has been invoked. PMK_Warning, - /// \brief \#pragma GCC error has been invoked. + /// \#pragma GCC error has been invoked. PMK_Error }; - /// \brief Callback invoked when a \#pragma message directive is read. + /// Callback invoked when a \#pragma message directive is read. /// \param Loc The location of the message directive. /// \param Namespace The namespace of the message directive. /// \param Kind The type of the message directive. @@ -199,62 +204,62 @@ public: PragmaMessageKind Kind, StringRef Str) { } - /// \brief Callback invoked when a \#pragma gcc diagnostic push directive + /// Callback invoked when a \#pragma gcc diagnostic push directive /// is read. virtual void PragmaDiagnosticPush(SourceLocation Loc, StringRef Namespace) { } - /// \brief Callback invoked when a \#pragma gcc diagnostic pop directive + /// Callback invoked when a \#pragma gcc diagnostic pop directive /// is read. virtual void PragmaDiagnosticPop(SourceLocation Loc, StringRef Namespace) { } - /// \brief Callback invoked when a \#pragma gcc diagnostic directive is read. + /// Callback invoked when a \#pragma gcc diagnostic directive is read. virtual void PragmaDiagnostic(SourceLocation Loc, StringRef Namespace, diag::Severity mapping, StringRef Str) {} - /// \brief Called when an OpenCL extension is either disabled or + /// Called when an OpenCL extension is either disabled or /// enabled with a pragma. virtual void PragmaOpenCLExtension(SourceLocation NameLoc, const IdentifierInfo *Name, SourceLocation StateLoc, unsigned State) { } - /// \brief Callback invoked when a \#pragma warning directive is read. + /// Callback invoked when a \#pragma warning directive is read. virtual void PragmaWarning(SourceLocation Loc, StringRef WarningSpec, ArrayRef<int> Ids) { } - /// \brief Callback invoked when a \#pragma warning(push) directive is read. + /// Callback invoked when a \#pragma warning(push) directive is read. virtual void PragmaWarningPush(SourceLocation Loc, int Level) { } - /// \brief Callback invoked when a \#pragma warning(pop) directive is read. + /// Callback invoked when a \#pragma warning(pop) directive is read. virtual void PragmaWarningPop(SourceLocation Loc) { } - /// \brief Callback invoked when a \#pragma clang assume_nonnull begin directive + /// Callback invoked when a \#pragma clang assume_nonnull begin directive /// is read. virtual void PragmaAssumeNonNullBegin(SourceLocation Loc) {} - /// \brief Callback invoked when a \#pragma clang assume_nonnull end directive + /// Callback invoked when a \#pragma clang assume_nonnull end directive /// is read. virtual void PragmaAssumeNonNullEnd(SourceLocation Loc) {} - /// \brief Called by Preprocessor::HandleMacroExpandedIdentifier when a + /// Called by Preprocessor::HandleMacroExpandedIdentifier when a /// macro invocation is found. virtual void MacroExpands(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range, const MacroArgs *Args) {} - /// \brief Hook called whenever a macro definition is seen. + /// Hook called whenever a macro definition is seen. virtual void MacroDefined(const Token &MacroNameTok, const MacroDirective *MD) { } - /// \brief Hook called whenever a macro \#undef is seen. + /// Hook called whenever a macro \#undef is seen. /// \param MacroNameTok The active Token /// \param MD A MacroDefinition for the named macro. /// \param Undef New MacroDirective if the macro was defined, null otherwise. @@ -265,13 +270,13 @@ public: const MacroDirective *Undef) { } - /// \brief Hook called whenever the 'defined' operator is seen. + /// Hook called whenever the 'defined' operator is seen. /// \param MD The MacroDirective if the name was a macro, null otherwise. virtual void Defined(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range) { } - /// \brief Hook called when a source range is skipped. + /// Hook called when a source range is skipped. /// \param Range The SourceRange that was skipped. The range begins at the /// \#if/\#else directive and ends after the \#endif/\#else directive. /// \param EndifLoc The end location of the 'endif' token, which may precede @@ -284,7 +289,7 @@ public: CVK_NotEvaluated, CVK_False, CVK_True }; - /// \brief Hook called whenever an \#if is seen. + /// Hook called whenever an \#if is seen. /// \param Loc the source location of the directive. /// \param ConditionRange The SourceRange of the expression being tested. /// \param ConditionValue The evaluated value of the condition. @@ -294,7 +299,7 @@ public: ConditionValueKind ConditionValue) { } - /// \brief Hook called whenever an \#elif is seen. + /// Hook called whenever an \#elif is seen. /// \param Loc the source location of the directive. /// \param ConditionRange The SourceRange of the expression being tested. /// \param ConditionValue The evaluated value of the condition. @@ -304,7 +309,7 @@ public: ConditionValueKind ConditionValue, SourceLocation IfLoc) { } - /// \brief Hook called whenever an \#ifdef is seen. + /// Hook called whenever an \#ifdef is seen. /// \param Loc the source location of the directive. /// \param MacroNameTok Information on the token being tested. /// \param MD The MacroDefinition if the name was a macro, null otherwise. @@ -312,7 +317,7 @@ public: const MacroDefinition &MD) { } - /// \brief Hook called whenever an \#ifndef is seen. + /// Hook called whenever an \#ifndef is seen. /// \param Loc the source location of the directive. /// \param MacroNameTok Information on the token being tested. /// \param MD The MacroDefiniton if the name was a macro, null otherwise. @@ -320,20 +325,20 @@ public: const MacroDefinition &MD) { } - /// \brief Hook called whenever an \#else is seen. + /// Hook called whenever an \#else is seen. /// \param Loc the source location of the directive. /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. virtual void Else(SourceLocation Loc, SourceLocation IfLoc) { } - /// \brief Hook called whenever an \#endif is seen. + /// Hook called whenever an \#endif is seen. /// \param Loc the source location of the directive. /// \param IfLoc the source location of the \#if/\#ifdef/\#ifndef directive. virtual void Endif(SourceLocation Loc, SourceLocation IfLoc) { } }; -/// \brief Simple wrapper class for chaining callbacks. +/// Simple wrapper class for chaining callbacks. class PPChainedCallbacks : public PPCallbacks { virtual void anchor(); std::unique_ptr<PPCallbacks> First, Second; @@ -367,13 +372,14 @@ public: StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, StringRef RelativePath, - const Module *Imported) override { + const Module *Imported, + SrcMgr::CharacteristicKind FileType) override { First->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath, RelativePath, - Imported); + Imported, FileType); Second->InclusionDirective(HashLoc, IncludeTok, FileName, IsAngled, FilenameRange, File, SearchPath, RelativePath, - Imported); + Imported, FileType); } void moduleImport(SourceLocation ImportLoc, ModuleIdPath Path, @@ -499,41 +505,41 @@ public: Second->SourceRangeSkipped(Range, EndifLoc); } - /// \brief Hook called whenever an \#if is seen. + /// Hook called whenever an \#if is seen. void If(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue) override { First->If(Loc, ConditionRange, ConditionValue); Second->If(Loc, ConditionRange, ConditionValue); } - /// \brief Hook called whenever an \#elif is seen. + /// Hook called whenever an \#elif is seen. void Elif(SourceLocation Loc, SourceRange ConditionRange, ConditionValueKind ConditionValue, SourceLocation IfLoc) override { First->Elif(Loc, ConditionRange, ConditionValue, IfLoc); Second->Elif(Loc, ConditionRange, ConditionValue, IfLoc); } - /// \brief Hook called whenever an \#ifdef is seen. + /// Hook called whenever an \#ifdef is seen. void Ifdef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override { First->Ifdef(Loc, MacroNameTok, MD); Second->Ifdef(Loc, MacroNameTok, MD); } - /// \brief Hook called whenever an \#ifndef is seen. + /// Hook called whenever an \#ifndef is seen. void Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override { First->Ifndef(Loc, MacroNameTok, MD); Second->Ifndef(Loc, MacroNameTok, MD); } - /// \brief Hook called whenever an \#else is seen. + /// Hook called whenever an \#else is seen. void Else(SourceLocation Loc, SourceLocation IfLoc) override { First->Else(Loc, IfLoc); Second->Else(Loc, IfLoc); } - /// \brief Hook called whenever an \#endif is seen. + /// Hook called whenever an \#endif is seen. void Endif(SourceLocation Loc, SourceLocation IfLoc) override { First->Endif(Loc, IfLoc); Second->Endif(Loc, IfLoc); diff --git a/include/clang/Lex/PPConditionalDirectiveRecord.h b/include/clang/Lex/PPConditionalDirectiveRecord.h index 8c5227561b838..a653b8339948d 100644 --- a/include/clang/Lex/PPConditionalDirectiveRecord.h +++ b/include/clang/Lex/PPConditionalDirectiveRecord.h @@ -21,7 +21,7 @@ namespace clang { -/// \brief Records preprocessor conditional directive regions and allows +/// Records preprocessor conditional directive regions and allows /// querying in which region source locations belong to. class PPConditionalDirectiveRecord : public PPCallbacks { SourceManager &SourceMgr; @@ -57,25 +57,25 @@ class PPConditionalDirectiveRecord : public PPCallbacks { }; typedef std::vector<CondDirectiveLoc> CondDirectiveLocsTy; - /// \brief The locations of conditional directives in source order. + /// The locations of conditional directives in source order. CondDirectiveLocsTy CondDirectiveLocs; void addCondDirectiveLoc(CondDirectiveLoc DirLoc); public: - /// \brief Construct a new preprocessing record. + /// Construct a new preprocessing record. explicit PPConditionalDirectiveRecord(SourceManager &SM); size_t getTotalMemory() const; SourceManager &getSourceManager() const { return SourceMgr; } - /// \brief Returns true if the given range intersects with a conditional + /// Returns true if the given range intersects with a conditional /// directive. if a \#if/\#endif block is fully contained within the range, /// this function will return false. bool rangeIntersectsConditionalDirective(SourceRange Range) const; - /// \brief Returns true if the given locations are in different regions, + /// Returns true if the given locations are in different regions, /// separated by conditional directive blocks. bool areInDifferentConditionalDirectiveRegion(SourceLocation LHS, SourceLocation RHS) const { diff --git a/include/clang/Lex/Pragma.h b/include/clang/Lex/Pragma.h index 090ae2a98236e..9348388bc28cf 100644 --- a/include/clang/Lex/Pragma.h +++ b/include/clang/Lex/Pragma.h @@ -26,22 +26,22 @@ class Preprocessor; class Token; /** - * \brief Describes how the pragma was introduced, e.g., with \#pragma, + * Describes how the pragma was introduced, e.g., with \#pragma, * _Pragma, or __pragma. */ enum PragmaIntroducerKind { /** - * \brief The pragma was introduced via \#pragma. + * The pragma was introduced via \#pragma. */ PIK_HashPragma, /** - * \brief The pragma was introduced via the C99 _Pragma(string-literal). + * The pragma was introduced via the C99 _Pragma(string-literal). */ PIK__Pragma, /** - * \brief The pragma was introduced via the Microsoft + * The pragma was introduced via the Microsoft * __pragma(token-string). */ PIK___pragma diff --git a/include/clang/Lex/PreprocessingRecord.h b/include/clang/Lex/PreprocessingRecord.h index 5f7a6efcef107..54e28a52f5b36 100644 --- a/include/clang/Lex/PreprocessingRecord.h +++ b/include/clang/Lex/PreprocessingRecord.h @@ -39,11 +39,11 @@ class PreprocessingRecord; } // namespace clang -/// \brief Allocates memory within a Clang preprocessing record. +/// Allocates memory within a Clang preprocessing record. void *operator new(size_t bytes, clang::PreprocessingRecord &PR, unsigned alignment = 8) noexcept; -/// \brief Frees memory allocated in a Clang preprocessing record. +/// Frees memory allocated in a Clang preprocessing record. void operator delete(void *ptr, clang::PreprocessingRecord &PR, unsigned) noexcept; @@ -55,25 +55,25 @@ class MacroInfo; class SourceManager; class Token; - /// \brief Base class that describes a preprocessed entity, which may be a + /// Base class that describes a preprocessed entity, which may be a /// preprocessor directive or macro expansion. class PreprocessedEntity { public: - /// \brief The kind of preprocessed entity an object describes. + /// The kind of preprocessed entity an object describes. enum EntityKind { - /// \brief Indicates a problem trying to load the preprocessed entity. + /// Indicates a problem trying to load the preprocessed entity. InvalidKind, - /// \brief A macro expansion. + /// A macro expansion. MacroExpansionKind, /// \defgroup Preprocessing directives /// @{ - /// \brief A macro definition. + /// A macro definition. MacroDefinitionKind, - /// \brief An inclusion directive, such as \c \#include, \c + /// An inclusion directive, such as \c \#include, \c /// \#import, or \c \#include_next. InclusionDirectiveKind, @@ -84,10 +84,10 @@ class Token; }; private: - /// \brief The kind of preprocessed entity that this object describes. + /// The kind of preprocessed entity that this object describes. EntityKind Kind; - /// \brief The source range that covers this preprocessed entity. + /// The source range that covers this preprocessed entity. SourceRange Range; protected: @@ -97,14 +97,14 @@ class Token; : Kind(Kind), Range(Range) {} public: - /// \brief Retrieve the kind of preprocessed entity stored in this object. + /// Retrieve the kind of preprocessed entity stored in this object. EntityKind getKind() const { return Kind; } - /// \brief Retrieve the source range that covers this entire preprocessed + /// Retrieve the source range that covers this entire preprocessed /// entity. SourceRange getSourceRange() const LLVM_READONLY { return Range; } - /// \brief Returns true if there was a problem loading the preprocessed + /// Returns true if there was a problem loading the preprocessed /// entity. bool isInvalid() const { return Kind == InvalidKind; } @@ -131,7 +131,7 @@ class Token; void operator delete(void *data) noexcept; }; - /// \brief Records the presence of a preprocessor directive. + /// Records the presence of a preprocessor directive. class PreprocessingDirective : public PreprocessedEntity { public: PreprocessingDirective(EntityKind Kind, SourceRange Range) @@ -144,9 +144,9 @@ class Token; } }; - /// \brief Record the location of a macro definition. + /// Record the location of a macro definition. class MacroDefinitionRecord : public PreprocessingDirective { - /// \brief The name of the macro being defined. + /// The name of the macro being defined. const IdentifierInfo *Name; public: @@ -154,10 +154,10 @@ class Token; SourceRange Range) : PreprocessingDirective(MacroDefinitionKind, Range), Name(Name) {} - /// \brief Retrieve the name of the macro being defined. + /// Retrieve the name of the macro being defined. const IdentifierInfo *getName() const { return Name; } - /// \brief Retrieve the location of the macro name in the definition. + /// Retrieve the location of the macro name in the definition. SourceLocation getLocation() const { return getSourceRange().getBegin(); } // Implement isa/cast/dyncast/etc. @@ -166,9 +166,9 @@ class Token; } }; - /// \brief Records the location of a macro expansion. + /// Records the location of a macro expansion. class MacroExpansion : public PreprocessedEntity { - /// \brief The definition of this macro or the name of the macro if it is + /// The definition of this macro or the name of the macro if it is /// a builtin macro. llvm::PointerUnion<IdentifierInfo *, MacroDefinitionRecord *> NameOrDef; @@ -181,17 +181,17 @@ class Token; : PreprocessedEntity(MacroExpansionKind, Range), NameOrDef(Definition) { } - /// \brief True if it is a builtin macro. + /// True if it is a builtin macro. bool isBuiltinMacro() const { return NameOrDef.is<IdentifierInfo *>(); } - /// \brief The name of the macro being expanded. + /// The name of the macro being expanded. const IdentifierInfo *getName() const { if (MacroDefinitionRecord *Def = getDefinition()) return Def->getName(); return NameOrDef.get<IdentifierInfo *>(); } - /// \brief The definition of the macro being expanded. May return null if + /// The definition of the macro being expanded. May return null if /// this is a builtin macro. MacroDefinitionRecord *getDefinition() const { return NameOrDef.dyn_cast<MacroDefinitionRecord *>(); @@ -203,45 +203,45 @@ class Token; } }; - /// \brief Record the location of an inclusion directive, such as an + /// Record the location of an inclusion directive, such as an /// \c \#include or \c \#import statement. class InclusionDirective : public PreprocessingDirective { public: - /// \brief The kind of inclusion directives known to the + /// The kind of inclusion directives known to the /// preprocessor. enum InclusionKind { - /// \brief An \c \#include directive. + /// An \c \#include directive. Include, - /// \brief An Objective-C \c \#import directive. + /// An Objective-C \c \#import directive. Import, - /// \brief A GNU \c \#include_next directive. + /// A GNU \c \#include_next directive. IncludeNext, - /// \brief A Clang \c \#__include_macros directive. + /// A Clang \c \#__include_macros directive. IncludeMacros }; private: - /// \brief The name of the file that was included, as written in + /// The name of the file that was included, as written in /// the source. StringRef FileName; - /// \brief Whether the file name was in quotation marks; otherwise, it was + /// Whether the file name was in quotation marks; otherwise, it was /// in angle brackets. unsigned InQuotes : 1; - /// \brief The kind of inclusion directive we have. + /// The kind of inclusion directive we have. /// /// This is a value of type InclusionKind. unsigned Kind : 2; - /// \brief Whether the inclusion directive was automatically turned into + /// Whether the inclusion directive was automatically turned into /// a module import. unsigned ImportedModule : 1; - /// \brief The file that was included. + /// The file that was included. const FileEntry *File; public: @@ -250,21 +250,21 @@ class Token; bool InQuotes, bool ImportedModule, const FileEntry *File, SourceRange Range); - /// \brief Determine what kind of inclusion directive this is. + /// Determine what kind of inclusion directive this is. InclusionKind getKind() const { return static_cast<InclusionKind>(Kind); } - /// \brief Retrieve the included file name as it was written in the source. + /// Retrieve the included file name as it was written in the source. StringRef getFileName() const { return FileName; } - /// \brief Determine whether the included file name was written in quotes; + /// Determine whether the included file name was written in quotes; /// otherwise, it was written in angle brackets. bool wasInQuotes() const { return InQuotes; } - /// \brief Determine whether the inclusion directive was automatically + /// Determine whether the inclusion directive was automatically /// turned into a module import. bool importedModule() const { return ImportedModule; } - /// \brief Retrieve the file entry for the actual file that was included + /// Retrieve the file entry for the actual file that was included /// by this directive. const FileEntry *getFile() const { return File; } @@ -274,55 +274,60 @@ class Token; } }; - /// \brief An abstract class that should be subclassed by any external source + /// An abstract class that should be subclassed by any external source /// of preprocessing record entries. class ExternalPreprocessingRecordSource { public: virtual ~ExternalPreprocessingRecordSource(); - /// \brief Read a preallocated preprocessed entity from the external source. + /// Read a preallocated preprocessed entity from the external source. /// /// \returns null if an error occurred that prevented the preprocessed /// entity from being loaded. virtual PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) = 0; - /// \brief Returns a pair of [Begin, End) indices of preallocated + /// Returns a pair of [Begin, End) indices of preallocated /// preprocessed entities that \p Range encompasses. virtual std::pair<unsigned, unsigned> findPreprocessedEntitiesInRange(SourceRange Range) = 0; - /// \brief Optionally returns true or false if the preallocated preprocessed + /// Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. virtual Optional<bool> isPreprocessedEntityInFileID(unsigned Index, FileID FID) { return None; } + + /// Read a preallocated skipped range from the external source. + virtual SourceRange ReadSkippedRange(unsigned Index) = 0; }; - /// \brief A record of the steps taken while preprocessing a source file, + /// A record of the steps taken while preprocessing a source file, /// including the various preprocessing directives processed, macros /// expanded, etc. class PreprocessingRecord : public PPCallbacks { SourceManager &SourceMgr; - /// \brief Allocator used to store preprocessing objects. + /// Allocator used to store preprocessing objects. llvm::BumpPtrAllocator BumpAlloc; - /// \brief The set of preprocessed entities in this record, in order they + /// The set of preprocessed entities in this record, in order they /// were seen. std::vector<PreprocessedEntity *> PreprocessedEntities; - /// \brief The set of preprocessed entities in this record that have been + /// The set of preprocessed entities in this record that have been /// loaded from external sources. /// /// The entries in this vector are loaded lazily from the external source, /// and are referenced by the iterator using negative indices. std::vector<PreprocessedEntity *> LoadedPreprocessedEntities; - /// \brief The set of ranges that were skipped by the preprocessor, + /// The set of ranges that were skipped by the preprocessor, std::vector<SourceRange> SkippedRanges; - /// \brief Global (loaded or local) ID for a preprocessed entity. + bool SkippedRangesAllLoaded = true; + + /// Global (loaded or local) ID for a preprocessed entity. /// Negative values are used to indicate preprocessed entities /// loaded from the external source while non-negative values are used to /// indicate preprocessed entities introduced by the current preprocessor. @@ -346,50 +351,60 @@ class Token; return isLoaded ? PPEntityID(-int(Index)-1) : PPEntityID(Index+1); } - /// \brief Mapping from MacroInfo structures to their definitions. + /// Mapping from MacroInfo structures to their definitions. llvm::DenseMap<const MacroInfo *, MacroDefinitionRecord *> MacroDefinitions; - /// \brief External source of preprocessed entities. + /// External source of preprocessed entities. ExternalPreprocessingRecordSource *ExternalSource = nullptr; - /// \brief Retrieve the preprocessed entity at the given ID. + /// Retrieve the preprocessed entity at the given ID. PreprocessedEntity *getPreprocessedEntity(PPEntityID PPID); - /// \brief Retrieve the loaded preprocessed entity at the given index. + /// Retrieve the loaded preprocessed entity at the given index. PreprocessedEntity *getLoadedPreprocessedEntity(unsigned Index); - /// \brief Determine the number of preprocessed entities that were + /// Determine the number of preprocessed entities that were /// loaded (or can be loaded) from an external source. unsigned getNumLoadedPreprocessedEntities() const { return LoadedPreprocessedEntities.size(); } - /// \brief Returns a pair of [Begin, End) indices of local preprocessed + /// Returns a pair of [Begin, End) indices of local preprocessed /// entities that \p Range encompasses. std::pair<unsigned, unsigned> findLocalPreprocessedEntitiesInRange(SourceRange Range) const; unsigned findBeginLocalPreprocessedEntity(SourceLocation Loc) const; unsigned findEndLocalPreprocessedEntity(SourceLocation Loc) const; - /// \brief Allocate space for a new set of loaded preprocessed entities. + /// Allocate space for a new set of loaded preprocessed entities. /// /// \returns The index into the set of loaded preprocessed entities, which /// corresponds to the first newly-allocated entity. unsigned allocateLoadedEntities(unsigned NumEntities); - /// \brief Register a new macro definition. + /// Allocate space for a new set of loaded preprocessed skipped + /// ranges. + /// + /// \returns The index into the set of loaded preprocessed ranges, which + /// corresponds to the first newly-allocated range. + unsigned allocateSkippedRanges(unsigned NumRanges); + + /// Ensures that all external skipped ranges have been loaded. + void ensureSkippedRangesLoaded(); + + /// Register a new macro definition. void RegisterMacroDefinition(MacroInfo *Macro, MacroDefinitionRecord *Def); public: - /// \brief Construct a new preprocessing record. + /// Construct a new preprocessing record. explicit PreprocessingRecord(SourceManager &SM); - /// \brief Allocate memory in the preprocessing record. + /// Allocate memory in the preprocessing record. void *Allocate(unsigned Size, unsigned Align = 8) { return BumpAlloc.Allocate(Size, Align); } - /// \brief Deallocate memory in the preprocessing record. + /// Deallocate memory in the preprocessing record. void Deallocate(void *Ptr) {} size_t getTotalMemory() const; @@ -436,27 +451,27 @@ class Token; PreprocessedEntity *operator->() const { return **this; } }; - /// \brief Begin iterator for all preprocessed entities. + /// Begin iterator for all preprocessed entities. iterator begin() { return iterator(this, -(int)LoadedPreprocessedEntities.size()); } - /// \brief End iterator for all preprocessed entities. + /// End iterator for all preprocessed entities. iterator end() { return iterator(this, PreprocessedEntities.size()); } - /// \brief Begin iterator for local, non-loaded, preprocessed entities. + /// Begin iterator for local, non-loaded, preprocessed entities. iterator local_begin() { return iterator(this, 0); } - /// \brief End iterator for local, non-loaded, preprocessed entities. + /// End iterator for local, non-loaded, preprocessed entities. iterator local_end() { return iterator(this, PreprocessedEntities.size()); } - /// \brief iterator range for the given range of loaded + /// iterator range for the given range of loaded /// preprocessed entities. llvm::iterator_range<iterator> getIteratorsForLoadedRange(unsigned start, unsigned count) { @@ -467,14 +482,14 @@ class Token; iterator(this, int(end) - LoadedPreprocessedEntities.size())); } - /// \brief Returns a range of preprocessed entities that source range \p R + /// Returns a range of preprocessed entities that source range \p R /// encompasses. /// /// \param R the range to look for preprocessed entities. llvm::iterator_range<iterator> getPreprocessedEntitiesInRange(SourceRange R); - /// \brief Returns true if the preprocessed entity that \p PPEI iterator + /// Returns true if the preprocessed entity that \p PPEI iterator /// points to is coming from the file \p FID. /// /// Can be used to avoid implicit deserializations of preallocated @@ -483,23 +498,24 @@ class Token; /// \see getPreprocessedEntitiesInRange. bool isEntityInFileID(iterator PPEI, FileID FID); - /// \brief Add a new preprocessed entity to this record. + /// Add a new preprocessed entity to this record. PPEntityID addPreprocessedEntity(PreprocessedEntity *Entity); - /// \brief Set the external source for preprocessed entities. + /// Set the external source for preprocessed entities. void SetExternalSource(ExternalPreprocessingRecordSource &Source); - /// \brief Retrieve the external source for preprocessed entities. + /// Retrieve the external source for preprocessed entities. ExternalPreprocessingRecordSource *getExternalSource() const { return ExternalSource; } - /// \brief Retrieve the macro definition that corresponds to the given + /// Retrieve the macro definition that corresponds to the given /// \c MacroInfo. MacroDefinitionRecord *findMacroDefinition(const MacroInfo *MI); - /// \brief Retrieve all ranges that got skipped while preprocessing. - const std::vector<SourceRange> &getSkippedRanges() const { + /// Retrieve all ranges that got skipped while preprocessing. + const std::vector<SourceRange> &getSkippedRanges() { + ensureSkippedRangesLoaded(); return SkippedRanges; } @@ -516,14 +532,14 @@ class Token; StringRef FileName, bool IsAngled, CharSourceRange FilenameRange, const FileEntry *File, StringRef SearchPath, - StringRef RelativePath, - const Module *Imported) override; + StringRef RelativePath, const Module *Imported, + SrcMgr::CharacteristicKind FileType) override; void Ifdef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override; void Ifndef(SourceLocation Loc, const Token &MacroNameTok, const MacroDefinition &MD) override; - /// \brief Hook called whenever the 'defined' operator is seen. + /// Hook called whenever the 'defined' operator is seen. void Defined(const Token &MacroNameTok, const MacroDefinition &MD, SourceRange Range) override; @@ -533,7 +549,7 @@ class Token; void addMacroExpansion(const Token &Id, const MacroInfo *MI, SourceRange Range); - /// \brief Cached result of the last \see getPreprocessedEntitiesInRange + /// Cached result of the last \see getPreprocessedEntitiesInRange /// query. struct { SourceRange Range; diff --git a/include/clang/Lex/Preprocessor.h b/include/clang/Lex/Preprocessor.h index 485600f122329..4ec29fe8f331c 100644 --- a/include/clang/Lex/Preprocessor.h +++ b/include/clang/Lex/Preprocessor.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the clang::Preprocessor interface. +/// Defines the clang::Preprocessor interface. // //===----------------------------------------------------------------------===// @@ -83,7 +83,7 @@ class PTHManager; class ScratchBuffer; class TargetInfo; -/// \brief Stores token information for comparing actual tokens with +/// Stores token information for comparing actual tokens with /// predefined values. Only handles simple tokens and identifiers. class TokenValue { tok::TokenKind Kind; @@ -106,7 +106,7 @@ public: } }; -/// \brief Context in which macro name is used. +/// Context in which macro name is used. enum MacroUse { // other than #define or #undef MU_Other = 0, @@ -118,7 +118,7 @@ enum MacroUse { MU_Undef = 2 }; -/// \brief Engages in a tight little dance with the lexer to efficiently +/// Engages in a tight little dance with the lexer to efficiently /// preprocess tokens. /// /// Lexers know only about tokens within a single source file, and don't @@ -140,7 +140,7 @@ class Preprocessor { HeaderSearch &HeaderInfo; ModuleLoader &TheModuleLoader; - /// \brief External source of macros. + /// External source of macros. ExternalPreprocessorSource *ExternalSource; /// An optional PTHManager object used for getting tokens from @@ -186,7 +186,7 @@ class Preprocessor { unsigned CounterValue = 0; enum { - /// \brief Maximum depth of \#includes. + /// Maximum depth of \#includes. MaxAllowedIncludeStackDepth = 200 }; @@ -210,26 +210,26 @@ class Preprocessor { class ResetMacroExpansionHelper; - /// \brief Whether we have already loaded macros from the external source. + /// Whether we have already loaded macros from the external source. mutable bool ReadMacrosFromExternalSource : 1; - /// \brief True if pragmas are enabled. + /// True if pragmas are enabled. bool PragmasEnabled : 1; - /// \brief True if the current build action is a preprocessing action. + /// True if the current build action is a preprocessing action. bool PreprocessedOutput : 1; - /// \brief True if we are currently preprocessing a #if or #elif directive + /// True if we are currently preprocessing a #if or #elif directive bool ParsingIfOrElifDirective; - /// \brief True if we are pre-expanding macro arguments. + /// True if we are pre-expanding macro arguments. bool InMacroArgPreExpansion; - /// \brief Mapping/lookup information for all identifiers in + /// Mapping/lookup information for all identifiers in /// the program, including program keywords. mutable IdentifierTable Identifiers; - /// \brief This table contains all the selectors in the program. + /// This table contains all the selectors in the program. /// /// Unlike IdentifierTable above, this table *isn't* populated by the /// preprocessor. It is declared/expanded here because its role/lifetime is @@ -240,82 +240,82 @@ class Preprocessor { /// the lifetime of the preprocessor. SelectorTable Selectors; - /// \brief Information about builtins. + /// Information about builtins. Builtin::Context BuiltinInfo; - /// \brief Tracks all of the pragmas that the client registered + /// Tracks all of the pragmas that the client registered /// with this preprocessor. std::unique_ptr<PragmaNamespace> PragmaHandlers; - /// \brief Pragma handlers of the original source is stored here during the + /// 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 + /// Tracks all of the comment handlers that the client registered /// with this preprocessor. std::vector<CommentHandler *> CommentHandlers; - /// \brief True if we want to ignore EOF token and continue later on (thus + /// True if we want to ignore EOF token and continue later on (thus /// avoid tearing the Lexer and etc. down). bool IncrementalProcessing = false; /// The kind of translation unit we are processing. TranslationUnitKind TUKind; - /// \brief The code-completion handler. + /// The code-completion handler. CodeCompletionHandler *CodeComplete = nullptr; - /// \brief The file that we're performing code-completion for, if any. + /// The file that we're performing code-completion for, if any. const FileEntry *CodeCompletionFile = nullptr; - /// \brief The offset in file for the code-completion point. + /// The offset in file for the code-completion point. unsigned CodeCompletionOffset = 0; - /// \brief The location for the code-completion point. This gets instantiated + /// The location for the code-completion point. This gets instantiated /// when the CodeCompletionFile gets \#include'ed for preprocessing. SourceLocation CodeCompletionLoc; - /// \brief The start location for the file of the code-completion point. + /// The start location for the file of the code-completion point. /// /// This gets instantiated when the CodeCompletionFile gets \#include'ed /// for preprocessing. SourceLocation CodeCompletionFileLoc; - /// \brief The source location of the \c import contextual keyword we just + /// The source location of the \c import contextual keyword we just /// lexed, if any. SourceLocation ModuleImportLoc; - /// \brief The module import path that we're currently processing. + /// The module import path that we're currently processing. SmallVector<std::pair<IdentifierInfo *, SourceLocation>, 2> ModuleImportPath; - /// \brief Whether the last token we lexed was an '@'. + /// Whether the last token we lexed was an '@'. bool LastTokenWasAt = false; - /// \brief Whether the module import expects an identifier next. Otherwise, + /// Whether the module import expects an identifier next. Otherwise, /// it expects a '.' or ';'. bool ModuleImportExpectsIdentifier = false; - /// \brief The source location of the currently-active + /// The source location of the currently-active /// \#pragma clang arc_cf_code_audited begin. SourceLocation PragmaARCCFCodeAuditedLoc; - /// \brief The source location of the currently-active + /// The source location of the currently-active /// \#pragma clang assume_nonnull begin. SourceLocation PragmaAssumeNonNullLoc; - /// \brief True if we hit the code-completion point. + /// True if we hit the code-completion point. bool CodeCompletionReached = false; - /// \brief The code completion token containing the information + /// The code completion token containing the information /// on the stem that is to be code completed. IdentifierInfo *CodeCompletionII = nullptr; - /// \brief The directory that the main file should be considered to occupy, + /// 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 = nullptr; - /// \brief The number of bytes that we will initially skip when entering the + /// 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. /// @@ -386,37 +386,37 @@ private: State ConditionalStackState = Off; } PreambleConditionalStack; - /// \brief The current top of the stack that we're lexing from if + /// The current top of the stack that we're lexing from if /// not expanding a macro and we are lexing directly from source code. /// /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. std::unique_ptr<Lexer> CurLexer; - /// \brief The current top of stack that we're lexing from if + /// The current top of stack that we're lexing from if /// not expanding from a macro and we are lexing from a PTH cache. /// /// Only one of CurLexer, CurPTHLexer, or CurTokenLexer will be non-null. std::unique_ptr<PTHLexer> CurPTHLexer; - /// \brief The current top of the stack what we're lexing from + /// The current top of the stack what we're lexing from /// if not expanding a macro. /// /// This is an alias for either CurLexer or CurPTHLexer. PreprocessorLexer *CurPPLexer = nullptr; - /// \brief Used to find the current FileEntry, if CurLexer is non-null + /// Used to find the current FileEntry, if CurLexer is non-null /// and if applicable. /// /// This allows us to implement \#include_next and find directory-specific /// properties. const DirectoryLookup *CurDirLookup = nullptr; - /// \brief The current macro we are expanding, if we are expanding a macro. + /// The current macro we are expanding, if we are expanding a macro. /// /// One of CurLexer and CurTokenLexer must be null. std::unique_ptr<TokenLexer> CurTokenLexer; - /// \brief The kind of lexer we're currently working with. + /// The kind of lexer we're currently working with. enum CurLexerKind { CLK_Lexer, CLK_PTHLexer, @@ -425,11 +425,11 @@ private: CLK_LexAfterModuleImport } CurLexerKind = CLK_Lexer; - /// \brief If the current lexer is for a submodule that is being built, this + /// If the current lexer is for a submodule that is being built, this /// is that submodule. Module *CurLexerSubmodule = nullptr; - /// \brief Keeps track of the stack of files currently + /// Keeps track of the stack of files currently /// \#included, and macros currently being expanded from, not counting /// CurLexer/CurTokenLexer. struct IncludeStackInfo { @@ -458,7 +458,7 @@ private: }; std::vector<IncludeStackInfo> IncludeMacroStack; - /// \brief Actions invoked when some preprocessor activity is + /// Actions invoked when some preprocessor activity is /// encountered (e.g. a file is \#included, etc). std::unique_ptr<PPCallbacks> Callbacks; @@ -617,7 +617,7 @@ private: struct SubmoduleState; - /// \brief Information about a submodule that we're currently building. + /// Information about a submodule that we're currently building. struct BuildingSubmoduleInfo { /// The module that we are building. Module *M; @@ -643,7 +643,7 @@ private: }; SmallVector<BuildingSubmoduleInfo, 8> BuildingSubmoduleStack; - /// \brief Information about a submodule's preprocessor state. + /// Information about a submodule's preprocessor state. struct SubmoduleState { /// The macros for the submodule. MacroMap Macros; @@ -674,7 +674,7 @@ private: llvm::DenseMap<const IdentifierInfo *, llvm::TinyPtrVector<ModuleMacro *>> LeafModuleMacros; - /// \brief Macros that we want to warn because they are not used at the end + /// Macros that we want to warn because they are not used at the end /// of the translation unit. /// /// We store just their SourceLocations instead of @@ -686,7 +686,7 @@ private: using WarnUnusedMacroLocsTy = llvm::SmallPtrSet<SourceLocation, 32>; WarnUnusedMacroLocsTy WarnUnusedMacroLocs; - /// \brief A "freelist" of MacroArg objects that can be + /// A "freelist" of MacroArg objects that can be /// reused for quick allocation. MacroArgs *MacroArgCache = nullptr; @@ -713,21 +713,27 @@ private: unsigned NumFastTokenPaste = 0; unsigned NumSkipped = 0; - /// \brief The predefined macros that preprocessor should use from the + /// The predefined macros that preprocessor should use from the /// command line etc. std::string Predefines; - /// \brief The file ID for the preprocessor predefines. + /// The file ID for the preprocessor predefines. FileID PredefinesFileID; + /// The file ID for the PCH through header. + FileID PCHThroughHeaderFileID; + + /// Whether tokens are being skipped until the through header is seen. + bool SkippingUntilPCHThroughHeader = false; + /// \{ - /// \brief Cache of macro expanders to reduce malloc traffic. + /// Cache of macro expanders to reduce malloc traffic. enum { TokenLexerCacheSize = 8 }; unsigned NumCachedTokenLexers; std::unique_ptr<TokenLexer> TokenLexerCache[TokenLexerCacheSize]; /// \} - /// \brief Keeps macro expanded tokens for TokenLexers. + /// Keeps macro expanded tokens for TokenLexers. // /// Works like a stack; a TokenLexer adds the macro expanded tokens that is /// going to lex in the cache and when it finishes the tokens are removed @@ -735,7 +741,7 @@ private: SmallVector<Token, 16> MacroExpandedTokens; std::vector<std::pair<TokenLexer *, size_t>> MacroExpandingLexersStack; - /// \brief A record of the macro definitions and expansions that + /// A record of the macro definitions and expansions that /// occurred during preprocessing. /// /// This is an optional side structure that can be enabled with @@ -745,18 +751,18 @@ private: /// Cached tokens state. using CachedTokensTy = SmallVector<Token, 1>; - /// \brief Cached tokens are stored here when we do backtracking or + /// Cached tokens are stored here when we do backtracking or /// lookahead. They are "lexed" by the CachingLex() method. CachedTokensTy CachedTokens; - /// \brief The position of the cached token that CachingLex() should + /// The position of the cached token that CachingLex() should /// "lex" next. /// /// If it points beyond the CachedTokens vector, it means that a normal /// Lex() should be invoked. CachedTokensTy::size_type CachedLexPos = 0; - /// \brief Stack of backtrack positions, allowing nested backtracks. + /// Stack of backtrack positions, allowing nested backtracks. /// /// The EnableBacktrackAtThisPos() method pushes a position to /// indicate where CachedLexPos should be set when the BackTrack() method is @@ -785,7 +791,7 @@ public: ~Preprocessor(); - /// \brief Initialize the preprocessor using information about the target. + /// Initialize the preprocessor using information about the target. /// /// \param Target is owned by the caller and must remain valid for the /// lifetime of the preprocessor. @@ -794,7 +800,7 @@ public: void Initialize(const TargetInfo &Target, const TargetInfo *AuxTarget = nullptr); - /// \brief Initialize the preprocessor to parse a model file + /// 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 @@ -802,10 +808,10 @@ public: /// to parse model files. This method does that cleanup. void InitializeForModelFile(); - /// \brief Cleanup after model file parsing + /// Cleanup after model file parsing void FinalizeForModelFile(); - /// \brief Retrieve the preprocessor options used to initialize this + /// Retrieve the preprocessor options used to initialize this /// preprocessor. PreprocessorOptions &getPreprocessorOpts() const { return *PPOpts; } @@ -838,19 +844,19 @@ public: return ExternalSource; } - /// \brief Retrieve the module loader associated with this preprocessor. + /// Retrieve the module loader associated with this preprocessor. ModuleLoader &getModuleLoader() const { return TheModuleLoader; } bool hadModuleLoaderFatalFailure() const { return TheModuleLoader.HadFatalFailure; } - /// \brief True if we are currently preprocessing a #if or #elif directive + /// True if we are currently preprocessing a #if or #elif directive bool isParsingIfOrElifDirective() const { return ParsingIfOrElifDirective; } - /// \brief Control whether the preprocessor retains comments in output. + /// Control whether the preprocessor retains comments in output. void SetCommentRetentionState(bool KeepComments, bool KeepMacroComments) { this->KeepComments = KeepComments | KeepMacroComments; this->KeepMacroComments = KeepMacroComments; @@ -879,32 +885,32 @@ public: /// false if it is producing tokens to be consumed by Parse and Sema. bool isPreprocessedOutput() const { return PreprocessedOutput; } - /// \brief Return true if we are lexing directly from the specified lexer. + /// Return true if we are lexing directly from the specified lexer. bool isCurrentLexer(const PreprocessorLexer *L) const { return CurPPLexer == L; } - /// \brief Return the current lexer being lexed from. + /// Return the current lexer being lexed from. /// /// Note that this ignores any potentially active macro expansions and _Pragma /// expansions going on at the time. PreprocessorLexer *getCurrentLexer() const { return CurPPLexer; } - /// \brief Return the current file lexer being lexed from. + /// Return the current file lexer being lexed from. /// /// Note that this ignores any potentially active macro expansions and _Pragma /// expansions going on at the time. PreprocessorLexer *getCurrentFileLexer() const; - /// \brief Return the submodule owning the file being lexed. This may not be + /// Return the submodule owning the file being lexed. This may not be /// the current module if we have changed modules since entering the file. Module *getCurrentLexerSubmodule() const { return CurLexerSubmodule; } - /// \brief Returns the FileID for the preprocessor predefines. + /// Returns the FileID for the preprocessor predefines. FileID getPredefinesFileID() const { return PredefinesFileID; } /// \{ - /// \brief Accessors for preprocessor callbacks. + /// Accessors for preprocessor callbacks. /// /// Note that this class takes ownership of any PPCallbacks object given to /// it. @@ -925,7 +931,7 @@ public: (!getLangOpts().Modules || (bool)getMacroDefinition(II)); } - /// \brief Determine whether II is defined as a macro within the module M, + /// Determine whether II is defined as a macro within the module M, /// if that is a module that we've already preprocessed. Does not check for /// macros imported into M. bool isMacroDefinedInLocalModule(const IdentifierInfo *II, Module *M) { @@ -969,7 +975,7 @@ public: S.isAmbiguous(*this, II)); } - /// \brief Given an identifier, return its latest non-imported MacroDirective + /// Given an identifier, return its latest non-imported MacroDirective /// if it is \#define'd and not \#undef'd, or null if it isn't \#define'd. MacroDirective *getLocalMacroDirective(const IdentifierInfo *II) const { if (!II->hasMacroDefinition()) @@ -994,14 +1000,14 @@ public: return nullptr; } - /// \brief Given an identifier, return the latest non-imported macro + /// Given an identifier, return the latest non-imported macro /// directive for that identifier. /// /// One can iterate over all previous macro directives from the most recent /// one. MacroDirective *getLocalMacroDirectiveHistory(const IdentifierInfo *II) const; - /// \brief Add a directive to the macro directive history for this identifier. + /// Add a directive to the macro directive history for this identifier. void appendMacroDirective(IdentifierInfo *II, MacroDirective *MD); DefMacroDirective *appendDefMacroDirective(IdentifierInfo *II, MacroInfo *MI, SourceLocation Loc) { @@ -1014,16 +1020,16 @@ public: return appendDefMacroDirective(II, MI, MI->getDefinitionLoc()); } - /// \brief Set a MacroDirective that was loaded from a PCH file. + /// Set a MacroDirective that was loaded from a PCH file. void setLoadedMacroDirective(IdentifierInfo *II, MacroDirective *ED, MacroDirective *MD); - /// \brief Register an exported macro for a module and identifier. + /// Register an exported macro for a module and identifier. ModuleMacro *addModuleMacro(Module *Mod, IdentifierInfo *II, MacroInfo *Macro, ArrayRef<ModuleMacro *> Overrides, bool &IsNew); ModuleMacro *getModuleMacro(Module *Mod, IdentifierInfo *II); - /// \brief Get the list of leaf (non-overridden) module macros for a name. + /// Get the list of leaf (non-overridden) module macros for a name. ArrayRef<ModuleMacro*> getLeafModuleMacros(const IdentifierInfo *II) const { if (II->isOutOfDate()) updateOutOfDateIdentifier(const_cast<IdentifierInfo&>(*II)); @@ -1041,15 +1047,17 @@ public: macro_iterator macro_begin(bool IncludeExternalMacros = true) const; macro_iterator macro_end(bool IncludeExternalMacros = true) const; - llvm::iterator_range<macro_iterator> + llvm::iterator_range<macro_iterator> macros(bool IncludeExternalMacros = true) const { - return llvm::make_range(macro_begin(IncludeExternalMacros), - macro_end(IncludeExternalMacros)); + macro_iterator begin = macro_begin(IncludeExternalMacros); + macro_iterator end = macro_end(IncludeExternalMacros); + return llvm::make_range(begin, end); } + /// \} - /// \brief Return the name of the macro defined before \p Loc that has + /// Return the name of the macro defined before \p Loc that has /// spelling \p Tokens. If there are multiple macros with same spelling, /// return the last one defined. StringRef getLastMacroWithSpelling(SourceLocation Loc, @@ -1057,7 +1065,7 @@ public: const std::string &getPredefines() const { return Predefines; } - /// \brief Set the predefines for this Preprocessor. + /// Set the predefines for this Preprocessor. /// /// These predefines are automatically injected when parsing the main file. void setPredefines(const char *P) { Predefines = P; } @@ -1069,7 +1077,7 @@ public: return &Identifiers.get(Name); } - /// \brief Add the specified pragma handler to this preprocessor. + /// Add the specified pragma handler to this preprocessor. /// /// If \p Namespace is non-null, then it is a token required to exist on the /// pragma line before the pragma string starts, e.g. "STDC" or "GCC". @@ -1078,7 +1086,7 @@ public: AddPragmaHandler(StringRef(), Handler); } - /// \brief Remove the specific pragma handler from this preprocessor. + /// Remove the specific pragma handler from this preprocessor. /// /// If \p Namespace is non-null, then it should be the namespace that /// \p Handler was added to. It is an error to remove a handler that @@ -1091,68 +1099,84 @@ public: /// Install empty handlers for all pragmas (making them ignored). void IgnorePragmas(); - /// \brief Add the specified comment handler to the preprocessor. + /// Add the specified comment handler to the preprocessor. void addCommentHandler(CommentHandler *Handler); - /// \brief Remove the specified comment handler. + /// Remove the specified comment handler. /// /// It is an error to remove a handler that has not been registered. void removeCommentHandler(CommentHandler *Handler); - /// \brief Set the code completion handler to the given object. + /// Set the code completion handler to the given object. void setCodeCompletionHandler(CodeCompletionHandler &Handler) { CodeComplete = &Handler; } - /// \brief Retrieve the current code-completion handler. + /// Retrieve the current code-completion handler. CodeCompletionHandler *getCodeCompletionHandler() const { return CodeComplete; } - /// \brief Clear out the code completion handler. + /// Clear out the code completion handler. void clearCodeCompletionHandler() { CodeComplete = nullptr; } - /// \brief Hook used by the lexer to invoke the "natural language" code + /// Hook used by the lexer to invoke the "natural language" code /// completion point. void CodeCompleteNaturalLanguage(); - /// \brief Set the code completion token for filtering purposes. + /// Set the code completion token for filtering purposes. void setCodeCompletionIdentifierInfo(IdentifierInfo *Filter) { CodeCompletionII = Filter; } - /// \brief Get the code completion token for filtering purposes. + /// Get the code completion token for filtering purposes. StringRef getCodeCompletionFilter() { if (CodeCompletionII) return CodeCompletionII->getName(); return {}; } - /// \brief Retrieve the preprocessing record, or NULL if there is no + /// Retrieve the preprocessing record, or NULL if there is no /// preprocessing record. PreprocessingRecord *getPreprocessingRecord() const { return Record; } - /// \brief Create a new preprocessing record, which will keep track of + /// Create a new preprocessing record, which will keep track of /// all macro expansions, macro definitions, etc. void createPreprocessingRecord(); - /// \brief Enter the specified FileID as the main source file, + /// Returns true if the FileEntry is the PCH through header. + bool isPCHThroughHeader(const FileEntry *File); + + /// True if creating a PCH with a through header. + bool creatingPCHWithThroughHeader(); + + /// True if using a PCH with a through header. + bool usingPCHWithThroughHeader(); + + /// Skip tokens until after the #include of the through header. + void SkipTokensUntilPCHThroughHeader(); + + /// Process directives while skipping until the through header is found. + void HandleSkippedThroughHeaderDirective(Token &Result, + SourceLocation HashLoc); + + /// Enter the specified FileID as the main source file, /// which implicitly adds the builtin defines etc. void EnterMainSourceFile(); - /// \brief Inform the preprocessor callbacks that processing is complete. + /// Inform the preprocessor callbacks that processing is complete. void EndSourceFile(); - /// \brief Add a source file to the top of the include stack and + /// Add a source file to the top of the include stack and /// start lexing tokens from it instead of the current buffer. /// /// Emits a diagnostic, doesn't enter the file, and returns true on error. bool EnterSourceFile(FileID CurFileID, const DirectoryLookup *Dir, SourceLocation Loc); - /// \brief Add a Macro to the top of the include stack and start lexing + /// Add a Macro to the top of the include stack and start lexing /// tokens from it instead of the current buffer. /// /// \param Args specifies the tokens input to a function-like macro. @@ -1161,7 +1185,7 @@ public: void EnterMacro(Token &Identifier, SourceLocation ILEnd, MacroInfo *Macro, MacroArgs *Args); - /// \brief Add a "macro" context to the top of the include stack, + /// Add a "macro" context to the top of the include stack, /// which will cause the lexer to start returning the specified tokens. /// /// If \p DisableMacroExpansion is true, tokens lexed from the token stream @@ -1186,7 +1210,7 @@ public: EnterTokenStream(Toks.data(), Toks.size(), DisableMacroExpansion, false); } - /// \brief Pop the current lexer/macro exp off the top of the lexer stack. + /// Pop the current lexer/macro exp off the top of the lexer stack. /// /// This should only be used in situations where the current state of the /// top-of-stack lexer is known. @@ -1207,7 +1231,7 @@ public: /// void EnableBacktrackAtThisPos(); - /// \brief Disable the last EnableBacktrackAtThisPos call. + /// Disable the last EnableBacktrackAtThisPos call. void CommitBacktrackedTokens(); struct CachedTokensRange { @@ -1215,28 +1239,28 @@ public: }; private: - /// \brief A range of cached tokens that should be erased after lexing + /// A range of cached tokens that should be erased after lexing /// when backtracking requires the erasure of such cached tokens. Optional<CachedTokensRange> CachedTokenRangeToErase; public: - /// \brief Returns the range of cached tokens that were lexed since + /// Returns the range of cached tokens that were lexed since /// EnableBacktrackAtThisPos() was previously called. CachedTokensRange LastCachedTokenRange(); - /// \brief Erase the range of cached tokens that were lexed since + /// Erase the range of cached tokens that were lexed since /// EnableBacktrackAtThisPos() was previously called. void EraseCachedTokens(CachedTokensRange TokenRange); - /// \brief Make Preprocessor re-lex the tokens that were lexed since + /// Make Preprocessor re-lex the tokens that were lexed since /// EnableBacktrackAtThisPos() was previously called. void Backtrack(); - /// \brief True if EnableBacktrackAtThisPos() was called and + /// True if EnableBacktrackAtThisPos() was called and /// caching of tokens is on. bool isBacktrackEnabled() const { return !BacktrackPositions.empty(); } - /// \brief Lex the next token for this preprocessor. + /// Lex the next token for this preprocessor. void Lex(Token &Result); void LexAfterModuleImport(Token &Result); @@ -1247,7 +1271,7 @@ public: return CurSubmoduleState->VisibleModules.getImportLoc(M); } - /// \brief Lex a string literal, which may be the concatenation of multiple + /// Lex a string literal, which may be the concatenation of multiple /// string literals and may even come from macro expansion. /// \returns true on success, false if a error diagnostic has been generated. bool LexStringLiteral(Token &Result, std::string &String, @@ -1260,13 +1284,13 @@ public: AllowMacroExpansion); } - /// \brief Complete the lexing of a string literal where the first token has + /// Complete the lexing of a string literal where the first token has /// already been lexed (see LexStringLiteral). bool FinishLexStringLiteral(Token &Result, std::string &String, const char *DiagnosticTag, bool AllowMacroExpansion); - /// \brief Lex a token. If it's a comment, keep lexing until we get + /// Lex a token. If it's a comment, keep lexing until we get /// something not a comment. /// /// This is useful in -E -C mode where comments would foul up preprocessor @@ -1277,7 +1301,7 @@ public: while (Result.getKind() == tok::comment); } - /// \brief Just like Lex, but disables macro expansion of identifier tokens. + /// Just like Lex, but disables macro expansion of identifier tokens. void LexUnexpandedToken(Token &Result) { // Disable macro expansion. bool OldVal = DisableMacroExpansion; @@ -1289,7 +1313,7 @@ public: DisableMacroExpansion = OldVal; } - /// \brief Like LexNonComment, but this disables macro expansion of + /// Like LexNonComment, but this disables macro expansion of /// identifier tokens. void LexUnexpandedNonComment(Token &Result) { do @@ -1297,7 +1321,7 @@ public: while (Result.getKind() == tok::comment); } - /// \brief Parses a simple integer literal to get its numeric value. Floating + /// Parses a simple integer literal to get its numeric value. Floating /// point literals and user defined literals are rejected. Used primarily to /// handle pragmas that accept integer arguments. bool parseSimpleIntegerLiteral(Token &Tok, uint64_t &Value); @@ -1308,7 +1332,7 @@ public: MacroExpansionInDirectivesOverride = true; } - /// \brief Peeks ahead N tokens and returns that token without consuming any + /// Peeks ahead N tokens and returns that token without consuming any /// tokens. /// /// LookAhead(0) returns the next token that would be returned by Lex(), @@ -1322,7 +1346,7 @@ public: return PeekAhead(N+1); } - /// \brief When backtracking is enabled and tokens are cached, + /// When backtracking is enabled and tokens are cached, /// this allows to revert a specific number of tokens. /// /// Note that the number of tokens being reverted should be up to the last @@ -1337,7 +1361,7 @@ public: CachedLexPos -= N; } - /// \brief Enters a token in the token stream to be lexed next. + /// Enters a token in the token stream to be lexed next. /// /// If BackTrack() is called afterwards, the token will remain at the /// insertion point. @@ -1367,18 +1391,18 @@ public: return CachedTokens[CachedLexPos-1].getLastLoc(); } - /// \brief Whether \p Tok is the most recent token (`CachedLexPos - 1`) in + /// Whether \p Tok is the most recent token (`CachedLexPos - 1`) in /// CachedTokens. bool IsPreviousCachedToken(const Token &Tok) const; - /// \brief Replace token in `CachedLexPos - 1` in CachedTokens by the tokens + /// Replace token in `CachedLexPos - 1` in CachedTokens by the tokens /// in \p NewToks. /// /// Useful when a token needs to be split in smaller ones and CachedTokens /// most recent token must to be updated to reflect that. void ReplacePreviousCachedToken(ArrayRef<Token> NewToks); - /// \brief Replace the last token with an annotation token. + /// Replace the last token with an annotation token. /// /// Like AnnotateCachedTokens(), this routine replaces an /// already-parsed (and resolved) token with an annotation @@ -1404,19 +1428,19 @@ public: CachedTokens[CachedLexPos-1] = Tok; } - /// \brief Recompute the current lexer kind based on the CurLexer/CurPTHLexer/ + /// Recompute the current lexer kind based on the CurLexer/CurPTHLexer/ /// CurTokenLexer pointers. void recomputeCurLexerKind(); - /// \brief Returns true if incremental processing is enabled + /// Returns true if incremental processing is enabled bool isIncrementalProcessingEnabled() const { return IncrementalProcessing; } - /// \brief Enables the incremental processing + /// Enables the incremental processing void enableIncrementalProcessing(bool value = true) { IncrementalProcessing = value; } - /// \brief Specify the point at which code-completion will be performed. + /// Specify the point at which code-completion will be performed. /// /// \param File the file in which code completion should occur. If /// this file is included multiple times, code-completion will @@ -1433,16 +1457,16 @@ public: bool SetCodeCompletionPoint(const FileEntry *File, unsigned Line, unsigned Column); - /// \brief Determine if we are performing code completion. + /// Determine if we are performing code completion. bool isCodeCompletionEnabled() const { return CodeCompletionFile != nullptr; } - /// \brief Returns the location of the code-completion point. + /// Returns the location of the code-completion point. /// /// Returns an invalid location if code-completion is not enabled or the file /// containing the code-completion point has not been lexed yet. SourceLocation getCodeCompletionLoc() const { return CodeCompletionLoc; } - /// \brief Returns the start location of the file of code-completion point. + /// Returns the start location of the file of code-completion point. /// /// Returns an invalid location if code-completion is not enabled or the file /// containing the code-completion point has not been lexed yet. @@ -1450,11 +1474,11 @@ public: return CodeCompletionFileLoc; } - /// \brief Returns true if code-completion is enabled and we have hit the + /// Returns true if code-completion is enabled and we have hit the /// code-completion point. bool isCodeCompletionReached() const { return CodeCompletionReached; } - /// \brief Note that we hit the code-completion point. + /// Note that we hit the code-completion point. void setCodeCompletionReached() { assert(isCodeCompletionEnabled() && "Code-completion not enabled!"); CodeCompletionReached = true; @@ -1462,7 +1486,7 @@ public: getDiagnostics().setSuppressAllDiagnostics(true); } - /// \brief The location of the currently-active \#pragma clang + /// The location of the currently-active \#pragma clang /// arc_cf_code_audited begin. /// /// Returns an invalid location if there is no such pragma active. @@ -1470,13 +1494,13 @@ public: return PragmaARCCFCodeAuditedLoc; } - /// \brief Set the location of the currently-active \#pragma clang + /// Set the location of the currently-active \#pragma clang /// arc_cf_code_audited begin. An invalid location ends the pragma. void setPragmaARCCFCodeAuditedLoc(SourceLocation Loc) { PragmaARCCFCodeAuditedLoc = Loc; } - /// \brief The location of the currently-active \#pragma clang + /// The location of the currently-active \#pragma clang /// assume_nonnull begin. /// /// Returns an invalid location if there is no such pragma active. @@ -1484,19 +1508,19 @@ public: return PragmaAssumeNonNullLoc; } - /// \brief Set the location of the currently-active \#pragma clang + /// Set the location of the currently-active \#pragma clang /// assume_nonnull begin. An invalid location ends the pragma. void setPragmaAssumeNonNullLoc(SourceLocation Loc) { PragmaAssumeNonNullLoc = Loc; } - /// \brief Set the directory in which the main file should be considered + /// 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. + /// Instruct the preprocessor to skip part of the main source file. /// /// \param Bytes The number of bytes in the preamble to skip. /// @@ -1531,7 +1555,7 @@ public: return Lexer::getSpelling(loc, buffer, SourceMgr, LangOpts, invalid); } - /// \brief Return the 'spelling' of the Tok token. + /// Return the 'spelling' of the Tok token. /// /// The spelling of a token is the characters used to represent the token in /// the source file after trigraph expansion and escaped-newline folding. In @@ -1543,7 +1567,7 @@ public: return Lexer::getSpelling(Tok, SourceMgr, LangOpts, Invalid); } - /// \brief Get the spelling of a token into a preallocated buffer, instead + /// Get the spelling of a token into a preallocated buffer, instead /// of as an std::string. /// /// The caller is required to allocate enough space for the token, which is @@ -1560,7 +1584,7 @@ public: return Lexer::getSpelling(Tok, Buffer, SourceMgr, LangOpts, Invalid); } - /// \brief Get the spelling of a token into a SmallVector. + /// Get the spelling of a token into a SmallVector. /// /// Note that the returned StringRef may not point to the /// supplied buffer if a copy can be avoided. @@ -1568,14 +1592,14 @@ public: SmallVectorImpl<char> &Buffer, bool *Invalid = nullptr) const; - /// \brief Relex the token at the specified location. + /// Relex the token at the specified location. /// \returns true if there was a failure, false on success. bool getRawToken(SourceLocation Loc, Token &Result, bool IgnoreWhiteSpace = false) { return Lexer::getRawToken(Loc, Result, SourceMgr, LangOpts, IgnoreWhiteSpace); } - /// \brief Given a Token \p Tok that is a numeric constant with length 1, + /// Given a Token \p Tok that is a numeric constant with length 1, /// return the character. char getSpellingOfSingleCharacterNumericConstant(const Token &Tok, @@ -1593,7 +1617,7 @@ public: return *SourceMgr.getCharacterData(Tok.getLocation(), Invalid); } - /// \brief Retrieve the name of the immediate macro expansion. + /// Retrieve the name of the immediate macro expansion. /// /// This routine starts from a source location, and finds the name of the /// macro responsible for its immediate expansion. It looks through any @@ -1605,7 +1629,7 @@ public: return Lexer::getImmediateMacroName(Loc, SourceMgr, getLangOpts()); } - /// \brief Plop the specified string into a scratch buffer and set the + /// Plop the specified string into a scratch buffer and set the /// specified token's location and length to it. /// /// If specified, the source location provides a location of the expansion @@ -1614,7 +1638,12 @@ public: SourceLocation ExpansionLocStart = SourceLocation(), SourceLocation ExpansionLocEnd = SourceLocation()); - /// \brief Computes the source location just past the end of the + /// Split the first Length characters out of the token starting at TokLoc + /// and return a location pointing to the split token. Re-lexing from the + /// split token will return the split token rather than the original. + SourceLocation SplitToken(SourceLocation TokLoc, unsigned Length); + + /// Computes the source location just past the end of the /// token at this source location. /// /// This routine can be used to produce a source location that @@ -1633,7 +1662,7 @@ public: return Lexer::getLocForEndOfToken(Loc, Offset, SourceMgr, LangOpts); } - /// \brief Returns true if the given MacroID location points at the first + /// Returns true if the given MacroID location points at the first /// token of the macro expansion. /// /// \param MacroBegin If non-null and function returns true, it is set to @@ -1644,7 +1673,7 @@ public: MacroBegin); } - /// \brief Returns true if the given MacroID location points at the last + /// Returns true if the given MacroID location points at the last /// token of the macro expansion. /// /// \param MacroEnd If non-null and function returns true, it is set to @@ -1654,20 +1683,20 @@ public: return Lexer::isAtEndOfMacroExpansion(loc, SourceMgr, LangOpts, MacroEnd); } - /// \brief Print the token to stderr, used for debugging. + /// Print the token to stderr, used for debugging. void DumpToken(const Token &Tok, bool DumpFlags = false) const; void DumpLocation(SourceLocation Loc) const; void DumpMacro(const MacroInfo &MI) const; void dumpMacroInfo(const IdentifierInfo *II); - /// \brief Given a location that specifies the start of a + /// Given a location that specifies the start of a /// token, return a new location that specifies a character within the token. SourceLocation AdvanceToTokenCharacter(SourceLocation TokStart, unsigned Char) const { return Lexer::AdvanceToTokenCharacter(TokStart, Char, SourceMgr, LangOpts); } - /// \brief Increment the counters for the number of token paste operations + /// Increment the counters for the number of token paste operations /// performed. /// /// If fast was specified, this is a 'fast paste' case we handled. @@ -1700,13 +1729,13 @@ private: llvm::DenseMap<IdentifierInfo*,unsigned> PoisonReasons; public: - /// \brief Specifies the reason for poisoning an identifier. + /// Specifies the reason for poisoning an identifier. /// /// If that identifier is accessed while poisoned, then this reason will be /// used instead of the default "poisoned" diagnostic. void SetPoisonReason(IdentifierInfo *II, unsigned DiagID); - /// \brief Display reason for poisoned identifier. + /// Display reason for poisoned identifier. void HandlePoisonedIdentifier(Token & Tok); void MaybeHandlePoisonedIdentifier(Token & Identifier) { @@ -1739,7 +1768,7 @@ private: public: void PoisonSEHIdentifiers(bool Poison = true); // Borland - /// \brief Callback invoked when the lexer reads an identifier and has + /// Callback invoked when the lexer reads an identifier and has /// filled in the tokens IdentifierInfo member. /// /// This callback potentially macro expands it or turns it into a named @@ -1749,36 +1778,36 @@ public: /// lex again. bool HandleIdentifier(Token &Identifier); - /// \brief Callback invoked when the lexer hits the end of the current file. + /// Callback invoked when the lexer hits the end of the current file. /// /// This either returns the EOF token and returns true, or /// pops a level off the include stack and returns false, at which point the /// client should call lex again. bool HandleEndOfFile(Token &Result, bool isEndOfMacro = false); - /// \brief Callback invoked when the current TokenLexer hits the end of its + /// Callback invoked when the current TokenLexer hits the end of its /// token stream. bool HandleEndOfTokenLexer(Token &Result); - /// \brief Callback invoked when the lexer sees a # token at the start of a + /// Callback invoked when the lexer sees a # token at the start of a /// line. /// /// This consumes the directive, modifies the lexer/preprocessor state, and /// advances the lexer(s) so that the next token read is the correct one. void HandleDirective(Token &Result); - /// \brief Ensure that the next token is a tok::eod token. + /// Ensure that the next token is a tok::eod token. /// /// If not, emit a diagnostic and consume up until the eod. /// If \p EnableMacros is true, then we consider macros that expand to zero /// tokens as being ok. void CheckEndOfDirective(const char *Directive, bool EnableMacros = false); - /// \brief Read and discard all tokens remaining on the current line until + /// Read and discard all tokens remaining on the current line until /// the tok::eod token is found. void DiscardUntilEndOfDirective(); - /// \brief Returns true if the preprocessor has seen a use of + /// Returns true if the preprocessor has seen a use of /// __DATE__ or __TIME__ in the file so far. bool SawDateOrTime() const { return DATELoc != SourceLocation() || TIMELoc != SourceLocation(); @@ -1786,13 +1815,13 @@ public: unsigned getCounterValue() const { return CounterValue; } void setCounterValue(unsigned V) { CounterValue = V; } - /// \brief Retrieves the module that we're currently building, if any. + /// Retrieves the module that we're currently building, if any. Module *getCurrentModule(); - /// \brief Allocate a new MacroInfo object with the provided SourceLocation. + /// Allocate a new MacroInfo object with the provided SourceLocation. MacroInfo *AllocateMacroInfo(SourceLocation L); - /// \brief Turn the specified lexer token into a fully checked and spelled + /// Turn the specified lexer token into a fully checked and spelled /// filename, e.g. as an operand of \#include. /// /// The caller is expected to provide a buffer that is large enough to hold @@ -1803,7 +1832,7 @@ public: /// in ""'s. bool GetIncludeFilenameSpelling(SourceLocation Loc,StringRef &Filename); - /// \brief Given a "foo" or \<foo> reference, look up the indicated file. + /// Given a "foo" or \<foo> reference, look up the indicated file. /// /// Returns null on failure. \p isAngled indicates whether the file /// reference is for system \#include's or not (i.e. using <> instead of ""). @@ -1816,17 +1845,17 @@ public: ModuleMap::KnownHeader *SuggestedModule, bool *IsMapped, bool SkipCache = false); - /// \brief Get the DirectoryLookup structure used to find the current + /// Get the DirectoryLookup structure used to find the current /// FileEntry, if CurLexer is non-null and if applicable. /// /// This allows us to implement \#include_next and find directory-specific /// properties. const DirectoryLookup *GetCurDirLookup() { return CurDirLookup; } - /// \brief Return true if we're in the top-level file, not in a \#include. + /// Return true if we're in the top-level file, not in a \#include. bool isInPrimaryFile() const; - /// \brief Handle cases where the \#include name is expanded + /// Handle cases where the \#include name is expanded /// from a macro as multiple tokens, which need to be glued together. /// /// This occurs for code like: @@ -1842,7 +1871,7 @@ public: bool ConcatenateIncludeName(SmallString<128> &FilenameBuffer, SourceLocation &End); - /// \brief Lex an on-off-switch (C99 6.10.6p2) and verify that it is + /// Lex an on-off-switch (C99 6.10.6p2) and verify that it is /// followed by EOD. Return true if the token is not a valid on-off-switch. bool LexOnOffSwitch(tok::OnOffSwitch &OOS); @@ -1891,7 +1920,7 @@ private: VisibilityMacroDirective *AllocateVisibilityMacroDirective(SourceLocation Loc, bool isPublic); - /// \brief Lex and validate a macro name, which occurs after a + /// Lex and validate a macro name, which occurs after a /// \#define or \#undef. /// /// \param MacroNameTok Token that represents the name defined or undefined. @@ -1935,7 +1964,7 @@ private: bool FoundNonSkipPortion, bool FoundElse, SourceLocation ElseLoc = SourceLocation()); - /// \brief A fast PTH version of SkipExcludedConditionalBlock. + /// A fast PTH version of SkipExcludedConditionalBlock. void PTHSkipExcludedConditionalBlock(); /// Information about the result for evaluating an expression for a @@ -1948,17 +1977,17 @@ private: bool IncludedUndefinedIds; }; - /// \brief Evaluate an integer constant expression that may occur after a + /// Evaluate an integer constant expression that may occur after a /// \#if or \#elif directive and return a \p DirectiveEvalResult object. /// /// If the expression is equivalent to "!defined(X)" return X in IfNDefMacro. DirectiveEvalResult EvaluateDirectiveExpression(IdentifierInfo *&IfNDefMacro); - /// \brief Install the standard preprocessor pragmas: + /// Install the standard preprocessor pragmas: /// \#pragma GCC poison/system_header/dependency and \#pragma once. void RegisterBuiltinPragmas(); - /// \brief Register builtin macros such as __LINE__ with the identifier table. + /// Register builtin macros such as __LINE__ with the identifier table. void RegisterBuiltinMacros(); /// If an identifier token is read that is to be expanded as a macro, handle @@ -1966,7 +1995,7 @@ private: /// otherwise the caller should lex again. bool HandleMacroExpandedIdentifier(Token &Tok, const MacroDefinition &MD); - /// \brief Cache macro expanded tokens for TokenLexers. + /// Cache macro expanded tokens for TokenLexers. // /// Works like a stack; a TokenLexer adds the macro expanded tokens that is /// going to lex in the cache and when it finishes the tokens are removed @@ -1986,34 +2015,37 @@ private: MacroArgs *ReadMacroCallArgumentList(Token &MacroName, MacroInfo *MI, SourceLocation &ExpansionEnd); - /// \brief If an identifier token is read that is to be expanded + /// If an identifier token is read that is to be expanded /// as a builtin macro, handle it and return the next token as 'Tok'. void ExpandBuiltinMacro(Token &Tok); - /// \brief Read a \c _Pragma directive, slice it up, process it, then + /// Read a \c _Pragma directive, slice it up, process it, then /// return the first token after the directive. /// This assumes that the \c _Pragma token has just been read into \p Tok. void Handle_Pragma(Token &Tok); - /// \brief Like Handle_Pragma except the pragma text is not enclosed within + /// Like Handle_Pragma except the pragma text is not enclosed within /// a string literal. void HandleMicrosoft__pragma(Token &Tok); - /// \brief Add a lexer to the top of the include stack and + /// Add a lexer to the top of the include stack and /// start lexing tokens from it instead of the current buffer. void EnterSourceFileWithLexer(Lexer *TheLexer, const DirectoryLookup *Dir); - /// \brief Add a lexer to the top of the include stack and + /// Add a lexer to the top of the include stack and /// start getting tokens from it using the PTH cache. void EnterSourceFileWithPTH(PTHLexer *PL, const DirectoryLookup *Dir); - /// \brief Set the FileID for the preprocessor predefines. + /// Set the FileID for the preprocessor predefines. void setPredefinesFileID(FileID FID) { assert(PredefinesFileID.isInvalid() && "PredefinesFileID already set!"); PredefinesFileID = FID; } - /// \brief Returns true if we are lexing from a file and not a + /// Set the FileID for the PCH through header. + void setPCHThroughHeaderFileID(FileID FID); + + /// Returns true if we are lexing from a file and not a /// pragma or a macro. static bool IsFileLexer(const Lexer* L, const PreprocessorLexer* P) { return L ? !L->isPragmaLexer() : P != nullptr; @@ -2079,12 +2111,12 @@ public: DiagnosticsEngine &Diags, Module *M); // Module inclusion testing. - /// \brief Find the module that owns the source or header file that + /// Find the module that owns the source or header file that /// \p Loc points to. If the location is in a file that was included /// into a module, or is outside any module, returns nullptr. Module *getModuleForLocation(SourceLocation Loc); - /// \brief We want to produce a diagnostic at location IncLoc concerning a + /// We want to produce a diagnostic at location IncLoc concerning a /// missing module import. /// /// \param IncLoc The location at which the missing import was detected. @@ -2127,7 +2159,7 @@ public: } private: - /// \brief After processing predefined file, initialize the conditional stack from + /// After processing predefined file, initialize the conditional stack from /// the preamble. void replayPreambleConditionalStack(); @@ -2164,12 +2196,12 @@ public: // has inserted some tokens and getCommentRetentionState() is false. bool HandleComment(Token &Token, SourceRange Comment); - /// \brief A macro is used, update information about macros that need unused + /// A macro is used, update information about macros that need unused /// warnings. void markMacroAsUsed(MacroInfo *MI); }; -/// \brief Abstract base class that describes a handler that will receive +/// Abstract base class that describes a handler that will receive /// source ranges for each of the comments encountered in the source file. class CommentHandler { public: @@ -2180,7 +2212,7 @@ public: virtual bool HandleComment(Preprocessor &PP, SourceRange Comment) = 0; }; -/// \brief Registry of pragma handlers added by plugins +/// Registry of pragma handlers added by plugins using PragmaHandlerRegistry = llvm::Registry<PragmaHandler>; } // namespace clang diff --git a/include/clang/Lex/PreprocessorLexer.h b/include/clang/Lex/PreprocessorLexer.h index ff71d11b4511b..bb02725b116f0 100644 --- a/include/clang/Lex/PreprocessorLexer.h +++ b/include/clang/Lex/PreprocessorLexer.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// // /// \file -/// \brief Defines the PreprocessorLexer interface. +/// Defines the PreprocessorLexer interface. // //===----------------------------------------------------------------------===// @@ -39,21 +39,21 @@ protected: /// The SourceManager FileID corresponding to the file being lexed. const FileID FID; - /// \brief Number of SLocEntries before lexing the file. + /// Number of SLocEntries before lexing the file. unsigned InitialNumSLocEntries = 0; //===--------------------------------------------------------------------===// // Context-specific lexing flags set by the preprocessor. //===--------------------------------------------------------------------===// - /// \brief True when parsing \#XXX; turns '\\n' into a tok::eod token. + /// True when parsing \#XXX; turns '\\n' into a tok::eod token. bool ParsingPreprocessorDirective = false; - /// \brief True after \#include; turns \<xx> into a tok::angle_string_literal + /// True after \#include; turns \<xx> into a tok::angle_string_literal /// token. bool ParsingFilename = false; - /// \brief True if in raw mode. + /// True if in raw mode. /// /// Raw mode disables interpretation of tokens and is a far faster mode to /// lex in than non-raw-mode. This flag: @@ -68,11 +68,11 @@ protected: /// Note that in raw mode that the PP pointer may be null. bool LexingRawMode = false; - /// \brief A state machine that detects the \#ifndef-wrapping a file + /// A state machine that detects the \#ifndef-wrapping a file /// idiom for the multiple-include optimization. MultipleIncludeOpt MIOpt; - /// \brief Information about the set of \#if/\#ifdef/\#ifndef blocks + /// Information about the set of \#if/\#ifdef/\#ifndef blocks /// we are currently in. SmallVector<PPConditionalInfo, 4> ConditionalStack; @@ -82,7 +82,7 @@ protected: virtual void IndirectLex(Token& Result) = 0; - /// \brief Return the source location for the next observable location. + /// Return the source location for the next observable location. virtual SourceLocation getSourceLocation() = 0; //===--------------------------------------------------------------------===// @@ -114,7 +114,7 @@ protected: return false; } - /// \brief Return the top of the conditional stack. + /// Return the top of the conditional stack. /// \pre This requires that there be a conditional active. PPConditionalInfo &peekConditionalLevel() { assert(!ConditionalStack.empty() && "No conditionals active!"); @@ -130,23 +130,23 @@ public: //===--------------------------------------------------------------------===// // Misc. lexing methods. - /// \brief After the preprocessor has parsed a \#include, lex and + /// After the preprocessor has parsed a \#include, lex and /// (potentially) macro expand the filename. /// /// If the sequence parsed is not lexically legal, emit a diagnostic and /// return a result EOD token. void LexIncludeFilename(Token &Result); - /// \brief Inform the lexer whether or not we are currently lexing a + /// Inform the lexer whether or not we are currently lexing a /// preprocessor directive. void setParsingPreprocessorDirective(bool f) { ParsingPreprocessorDirective = f; } - /// \brief Return true if this lexer is in raw mode or not. + /// Return true if this lexer is in raw mode or not. bool isLexingRawMode() const { return LexingRawMode; } - /// \brief Return the preprocessor object for this lexer. + /// Return the preprocessor object for this lexer. Preprocessor *getPP() const { return PP; } FileID getFileID() const { @@ -155,7 +155,7 @@ public: return FID; } - /// \brief Number of SLocEntries before lexing the file. + /// Number of SLocEntries before lexing the file. unsigned getInitialNumSLocEntries() const { return InitialNumSLocEntries; } @@ -164,7 +164,7 @@ public: /// getFileID(), this only works for lexers with attached preprocessors. const FileEntry *getFileEntry() const; - /// \brief Iterator that traverses the current stack of preprocessor + /// Iterator that traverses the current stack of preprocessor /// conditional directives (\#if/\#ifdef/\#ifndef). using conditional_iterator = SmallVectorImpl<PPConditionalInfo>::const_iterator; diff --git a/include/clang/Lex/PreprocessorOptions.h b/include/clang/Lex/PreprocessorOptions.h index 55fc305dc2950..3d7e5ab4a8dc7 100644 --- a/include/clang/Lex/PreprocessorOptions.h +++ b/include/clang/Lex/PreprocessorOptions.h @@ -27,14 +27,14 @@ class MemoryBuffer; namespace clang { -/// \brief Enumerate the kinds of standard library that +/// Enumerate the kinds of standard library that enum ObjCXXARCStandardLibraryKind { ARCXX_nolib, - /// \brief libc++ + /// libc++ ARCXX_libcxx, - /// \brief libstdc++ + /// libstdc++ ARCXX_libstdcxx }; @@ -46,48 +46,60 @@ public: std::vector<std::string> Includes; std::vector<std::string> MacroIncludes; - /// \brief Initialize the preprocessor with the compiler and target specific + /// Initialize the preprocessor with the compiler and target specific /// predefines. bool UsePredefines = true; - /// \brief Whether we should maintain a detailed record of all macro + /// Whether we should maintain a detailed record of all macro /// definitions and expansions. bool DetailedRecord = false; + /// If non-empty, the filename used in an #include directive in the primary + /// source file (or command-line preinclude) that is used to implement + /// MSVC-style precompiled headers. When creating a PCH, after the #include + /// of this header, the PCH generation stops. When using a PCH, tokens are + /// skipped until after an #include of this header is seen. + std::string PCHThroughHeader; + /// The implicit PCH included at the start of the translation unit, or empty. std::string ImplicitPCHInclude; - /// \brief Headers that will be converted to chained PCHs in memory. + /// Headers that will be converted to chained PCHs in memory. std::vector<std::string> ChainedIncludes; - /// \brief When true, disables most of the normal validation performed on + /// When true, disables most of the normal validation performed on /// precompiled headers. bool DisablePCHValidation = false; - /// \brief When true, a PCH with compiler errors will not be rejected. + /// When true, a PCH with compiler errors will not be rejected. bool AllowPCHWithCompilerErrors = false; - /// \brief Dump declarations that are deserialized from PCH, for testing. + /// Dump declarations that are deserialized from PCH, for testing. bool DumpDeserializedPCHDecls = false; - /// \brief This is a set of names for decls that we do not want to be + /// This is a set of names for decls that we do not want to be /// deserialized, and we emit an error if they are; for testing purposes. std::set<std::string> DeserializedPCHDeclsToErrorOn; - /// \brief If non-zero, the implicit PCH include is actually a precompiled + /// If non-zero, the implicit PCH include is actually a precompiled /// preamble that covers this number of bytes in the main source file. /// /// The boolean indicates whether the preamble ends at the start of a new /// line. std::pair<unsigned, bool> PrecompiledPreambleBytes; - /// \brief True indicates that a preamble is being generated. + /// True indicates that a preamble is being generated. /// /// When the lexer is done, one of the things that need to be preserved is the /// conditional #if stack, so the ASTWriter/ASTReader can save/restore it when /// processing the rest of the file. bool GeneratePreamble = false; + /// Whether to write comment locations into the PCH when building it. + /// Reading the comments from the PCH can be a performance hit even if the + /// clients don't use them. + bool WriteCommentListToPCH = true; + /// The implicit PTH input included at the start of the translation unit, or /// empty. std::string ImplicitPTHInclude; @@ -105,22 +117,22 @@ public: /// When enabled, the preprocessor will construct editor placeholder tokens. bool LexEditorPlaceholders = true; - /// \brief True if the SourceManager should report the original file name for + /// True if the SourceManager should report the original file name for /// contents of files that were remapped to other files. Defaults to true. bool RemappedFilesKeepOriginalName = true; - /// \brief The set of file remappings, which take existing files on + /// The set of file remappings, which take existing files on /// the system (the first part of each pair) and gives them the /// contents of other files on the system (the second part of each /// pair). std::vector<std::pair<std::string, std::string>> RemappedFiles; - /// \brief The set of file-to-buffer remappings, which take existing files + /// The set of file-to-buffer remappings, which take existing files /// on the system (the first part of each pair) and gives them the contents /// of the specified memory buffer (the second part of each pair). std::vector<std::pair<std::string, llvm::MemoryBuffer *>> RemappedFileBuffers; - /// \brief Whether the compiler instance should retain (i.e., not free) + /// Whether the compiler instance should retain (i.e., not free) /// the buffers associated with remapped files. /// /// This flag defaults to false; it can be set true only through direct @@ -128,12 +140,12 @@ public: /// compiler invocation and its buffers will be reused. bool RetainRemappedFileBuffers = false; - /// \brief The Objective-C++ ARC standard library that we should support, + /// The Objective-C++ ARC standard library that we should support, /// by providing appropriate definitions to retrofit the standard library /// with support for lifetime-qualified pointers. ObjCXXARCStandardLibraryKind ObjCXXARCStandardLibrary = ARCXX_nolib; - /// \brief Records the set of modules + /// Records the set of modules class FailedModulesSet { llvm::StringSet<> Failed; @@ -147,7 +159,7 @@ public: } }; - /// \brief The set of modules that failed to build. + /// The set of modules that failed to build. /// /// This pointer will be shared among all of the compiler instances created /// to (re)build modules, so that once a module fails to build anywhere, @@ -174,7 +186,7 @@ public: RemappedFileBuffers.clear(); } - /// \brief Reset any options that are not considered when building a + /// Reset any options that are not considered when building a /// module. void resetNonModularOptions() { Includes.clear(); diff --git a/include/clang/Lex/Token.h b/include/clang/Lex/Token.h index 02a1fef70f2bc..633e1d15697b9 100644 --- a/include/clang/Lex/Token.h +++ b/include/clang/Lex/Token.h @@ -102,24 +102,24 @@ public: return is(K1) || isOneOf(K2, Ks...); } - /// \brief Return true if this is a raw identifier (when lexing + /// Return true if this is a raw identifier (when lexing /// in raw mode) or a non-keyword identifier (when lexing in non-raw mode). bool isAnyIdentifier() const { return tok::isAnyIdentifier(getKind()); } - /// \brief Return true if this is a "literal", like a numeric + /// Return true if this is a "literal", like a numeric /// constant, string, etc. bool isLiteral() const { return tok::isLiteral(getKind()); } - /// \brief Return true if this is any of tok::annot_* kind tokens. + /// Return true if this is any of tok::annot_* kind tokens. bool isAnnotation() const { return tok::isAnnotation(getKind()); } - /// \brief Return a source location identifier for the specified + /// Return a source location identifier for the specified /// offset in the current file. SourceLocation getLocation() const { return SourceLocation::getFromRawEncoding(Loc); @@ -153,7 +153,7 @@ public: : getLocation().getLocWithOffset(getLength()); } - /// \brief SourceRange of the group of tokens that this annotation token + /// SourceRange of the group of tokens that this annotation token /// represents. SourceRange getAnnotationRange() const { return SourceRange(getLocation(), getAnnotationEndLoc()); @@ -165,7 +165,7 @@ public: const char *getName() const { return tok::getTokenName(Kind); } - /// \brief Reset all flags to cleared. + /// Reset all flags to cleared. void startToken() { Kind = tok::unknown; Flags = 0; @@ -230,22 +230,22 @@ public: PtrData = val; } - /// \brief Set the specified flag. + /// Set the specified flag. void setFlag(TokenFlags Flag) { Flags |= Flag; } - /// \brief Get the specified flag. + /// Get the specified flag. bool getFlag(TokenFlags Flag) const { return (Flags & Flag) != 0; } - /// \brief Unset the specified flag. + /// Unset the specified flag. void clearFlag(TokenFlags Flag) { Flags &= ~Flag; } - /// \brief Return the internal represtation of the flags. + /// Return the internal represtation of the flags. /// /// This is only intended for low-level operations such as writing tokens to /// disk. @@ -253,7 +253,7 @@ public: return Flags; } - /// \brief Set a flag to either true or false. + /// Set a flag to either true or false. void setFlagValue(TokenFlags Flag, bool Val) { if (Val) setFlag(Flag); @@ -265,28 +265,28 @@ public: /// bool isAtStartOfLine() const { return getFlag(StartOfLine); } - /// \brief Return true if this token has whitespace before it. + /// Return true if this token has whitespace before it. /// bool hasLeadingSpace() const { return getFlag(LeadingSpace); } - /// \brief Return true if this identifier token should never + /// Return true if this identifier token should never /// be expanded in the future, due to C99 6.10.3.4p2. bool isExpandDisabled() const { return getFlag(DisableExpand); } - /// \brief Return true if we have an ObjC keyword identifier. + /// Return true if we have an ObjC keyword identifier. bool isObjCAtKeyword(tok::ObjCKeywordKind objcKey) const; - /// \brief Return the ObjC keyword kind. + /// Return the ObjC keyword kind. tok::ObjCKeywordKind getObjCKeywordID() const; - /// \brief Return true if this token has trigraphs or escaped newlines in it. + /// Return true if this token has trigraphs or escaped newlines in it. bool needsCleaning() const { return getFlag(NeedsCleaning); } - /// \brief Return true if this token has an empty macro before it. + /// Return true if this token has an empty macro before it. /// bool hasLeadingEmptyMacro() const { return getFlag(LeadingEmptyMacro); } - /// \brief Return true if this token is a string or character literal which + /// Return true if this token is a string or character literal which /// has a ud-suffix. bool hasUDSuffix() const { return getFlag(HasUDSuffix); } @@ -308,21 +308,21 @@ public: bool isEditorPlaceholder() const { return getFlag(IsEditorPlaceholder); } }; -/// \brief Information about the conditional stack (\#if directives) +/// Information about the conditional stack (\#if directives) /// currently active. struct PPConditionalInfo { - /// \brief Location where the conditional started. + /// Location where the conditional started. SourceLocation IfLoc; - /// \brief True if this was contained in a skipping directive, e.g., + /// True if this was contained in a skipping directive, e.g., /// in a "\#if 0" block. bool WasSkipping; - /// \brief True if we have emitted tokens already, and now we're in + /// True if we have emitted tokens already, and now we're in /// an \#else block or something. Only useful in Skipping blocks. bool FoundNonSkip; - /// \brief True if we've seen a \#else in this block. If so, + /// True if we've seen a \#else in this block. If so, /// \#elif/\#else directives are not allowed. bool FoundElse; }; diff --git a/include/clang/Lex/TokenLexer.h b/include/clang/Lex/TokenLexer.h index b8b0beabf2ba2..e616d497eec69 100644 --- a/include/clang/Lex/TokenLexer.h +++ b/include/clang/Lex/TokenLexer.h @@ -62,18 +62,18 @@ class TokenLexer { /// expanded. SourceLocation ExpandLocStart, ExpandLocEnd; - /// \brief Source location pointing at the source location entry chunk that + /// Source location pointing at the source location entry chunk that /// was reserved for the current macro expansion. SourceLocation MacroExpansionStart; - /// \brief The offset of the macro expansion in the + /// The offset of the macro expansion in the /// "source location address space". unsigned MacroStartSLocOffset; - /// \brief Location of the macro definition. + /// Location of the macro definition. SourceLocation MacroDefStart; - /// \brief Length of the macro definition. + /// Length of the macro definition. unsigned MacroDefLength; /// Lexical information about the expansion point of the macro: the identifier @@ -198,7 +198,7 @@ private: /// the tokens just expanded through __VA_OPT__ processing. These (sub) /// sequence of tokens are folded into one stringified token. /// - /// \param[in] VCtx - contains relevent contextual information about the + /// \param[in] VCtx - contains relevant contextual information about the /// state of the tokens around and including the __VA_OPT__ token, necessary /// for stringification. void stringifyVAOPTContents(SmallVectorImpl<Token> &ReplacementToks, @@ -216,12 +216,12 @@ private: /// first token on the next line. void HandleMicrosoftCommentPaste(Token &Tok, SourceLocation OpLoc); - /// \brief If \p loc is a FileID and points inside the current macro + /// If \p loc is a FileID and points inside the current macro /// definition, returns the appropriate source location pointing at the /// macro expansion source location entry. SourceLocation getExpansionLocForMacroDefLoc(SourceLocation loc) const; - /// \brief Creates SLocEntries and updates the locations of macro argument + /// Creates SLocEntries and updates the locations of macro argument /// tokens to their new expanded locations. /// /// \param ArgIdSpellLoc the location of the macro argument id inside the diff --git a/include/clang/Lex/VariadicMacroSupport.h b/include/clang/Lex/VariadicMacroSupport.h index cebaf15187de0..55202ffc34d75 100644 --- a/include/clang/Lex/VariadicMacroSupport.h +++ b/include/clang/Lex/VariadicMacroSupport.h @@ -55,7 +55,7 @@ namespace clang { /// Client code should call this function as soon as the Preprocessor has /// either completed lexing the macro's definition tokens, or an error - /// occured and the context is being exited. This function is idempotent + /// occurred and the context is being exited. This function is idempotent /// (might be explicitly called, and then reinvoked via the destructor). void exitScope() { Ident__VA_ARGS__->setIsPoisoned(true); @@ -66,7 +66,7 @@ namespace clang { ~VariadicMacroScopeGuard() { exitScope(); } }; - /// \brief A class for tracking whether we're inside a VA_OPT during a + /// A class for tracking whether we're inside a VA_OPT during a /// traversal of the tokens of a variadic macro definition. class VAOptDefinitionContext { /// Contains all the locations of so far unmatched lparens. @@ -116,7 +116,7 @@ namespace clang { }; - /// \brief A class for tracking whether we're inside a VA_OPT during a + /// A class for tracking whether we're inside a VA_OPT during a /// traversal of the tokens of a macro during macro expansion. class VAOptExpansionContext : VAOptDefinitionContext { diff --git a/include/clang/Parse/ParseAST.h b/include/clang/Parse/ParseAST.h index 34c96816ebdf6..34b04060346f8 100644 --- a/include/clang/Parse/ParseAST.h +++ b/include/clang/Parse/ParseAST.h @@ -23,7 +23,7 @@ namespace clang { class CodeCompleteConsumer; class Sema; - /// \brief Parse the entire file specified, notifying the ASTConsumer as + /// Parse the entire file specified, notifying the ASTConsumer as /// the file is parsed. /// /// This operation inserts the parsed decls into the translation @@ -42,7 +42,7 @@ namespace clang { CodeCompleteConsumer *CompletionConsumer = nullptr, bool SkipFunctionBodies = false); - /// \brief Parse the main file known to the preprocessor, producing an + /// Parse the main file known to the preprocessor, producing an /// abstract syntax tree. void ParseAST(Sema &S, bool PrintStats = false, bool SkipFunctionBodies = false); diff --git a/include/clang/Parse/Parser.h b/include/clang/Parse/Parser.h index 4a25c70956a3b..d7b83803af202 100644 --- a/include/clang/Parse/Parser.h +++ b/include/clang/Parse/Parser.h @@ -15,6 +15,7 @@ #define LLVM_CLANG_PARSE_PARSER_H #include "clang/AST/Availability.h" +#include "clang/Basic/BitmaskEnum.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/OperatorPrecedence.h" #include "clang/Basic/Specifiers.h" @@ -45,7 +46,6 @@ namespace clang { class ColonProtectionRAIIObject; class InMessageExpressionRAIIObject; class PoisonSEHIdentifiersRAIIObject; - class VersionTuple; class OMPClause; class ObjCTypeParamList; class ObjCTypeParameter; @@ -121,25 +121,25 @@ class Parser : public CodeCompletionHandler { /// Objective-C contextual keywords. mutable IdentifierInfo *Ident_instancetype; - /// \brief Identifier for "introduced". + /// Identifier for "introduced". IdentifierInfo *Ident_introduced; - /// \brief Identifier for "deprecated". + /// Identifier for "deprecated". IdentifierInfo *Ident_deprecated; - /// \brief Identifier for "obsoleted". + /// Identifier for "obsoleted". IdentifierInfo *Ident_obsoleted; - /// \brief Identifier for "unavailable". + /// Identifier for "unavailable". IdentifierInfo *Ident_unavailable; - /// \brief Identifier for "message". + /// Identifier for "message". IdentifierInfo *Ident_message; - /// \brief Identifier for "strict". + /// Identifier for "strict". IdentifierInfo *Ident_strict; - /// \brief Identifier for "replacement". + /// Identifier for "replacement". IdentifierInfo *Ident_replacement; /// Identifiers used by the 'external_source_symbol' attribute. @@ -179,12 +179,16 @@ class Parser : public CodeCompletionHandler { std::unique_ptr<PragmaHandler> MSSection; std::unique_ptr<PragmaHandler> MSRuntimeChecks; std::unique_ptr<PragmaHandler> MSIntrinsic; + std::unique_ptr<PragmaHandler> MSOptimize; std::unique_ptr<PragmaHandler> CUDAForceHostDeviceHandler; std::unique_ptr<PragmaHandler> OptimizeHandler; std::unique_ptr<PragmaHandler> LoopHintHandler; std::unique_ptr<PragmaHandler> UnrollHintHandler; std::unique_ptr<PragmaHandler> NoUnrollHintHandler; std::unique_ptr<PragmaHandler> FPHandler; + std::unique_ptr<PragmaHandler> STDCFENVHandler; + std::unique_ptr<PragmaHandler> STDCCXLIMITHandler; + std::unique_ptr<PragmaHandler> STDCUnknownHandler; std::unique_ptr<PragmaHandler> AttributePragmaHandler; std::unique_ptr<CommentHandler> CommentSemaHandler; @@ -201,7 +205,7 @@ class Parser : public CodeCompletionHandler { /// ColonProtectionRAIIObject RAII object. bool ColonIsSacred; - /// \brief When true, we are directly inside an Objective-C message + /// When true, we are directly inside an Objective-C message /// send expression. /// /// This is managed by the \c InMessageExpressionRAIIObject class, and @@ -211,7 +215,7 @@ class Parser : public CodeCompletionHandler { /// The "depth" of the template parameters currently being parsed. unsigned TemplateParameterDepth; - /// \brief RAII class that manages the template parameter depth. + /// RAII class that manages the template parameter depth. class TemplateParameterDepthRAII { unsigned &Depth; unsigned AddedLevels; @@ -234,16 +238,100 @@ class Parser : public CodeCompletionHandler { unsigned getDepth() const { return Depth; } }; - /// Factory object for creating AttributeList objects. + /// Factory object for creating ParsedAttr objects. AttributeFactory AttrFactory; - /// \brief Gathers and cleans up TemplateIdAnnotations when parsing of a + /// Gathers and cleans up TemplateIdAnnotations when parsing of a /// top-level declaration is finished. SmallVector<TemplateIdAnnotation *, 16> TemplateIds; - /// \brief Identifiers which have been declared within a tentative parse. + /// Identifiers which have been declared within a tentative parse. SmallVector<IdentifierInfo *, 8> TentativelyDeclaredIdentifiers; + /// Tracker for '<' tokens that might have been intended to be treated as an + /// angle bracket instead of a less-than comparison. + /// + /// This happens when the user intends to form a template-id, but typoes the + /// template-name or forgets a 'template' keyword for a dependent template + /// name. + /// + /// We track these locations from the point where we see a '<' with a + /// name-like expression on its left until we see a '>' or '>>' that might + /// match it. + struct AngleBracketTracker { + /// Flags used to rank candidate template names when there is more than one + /// '<' in a scope. + enum Priority : unsigned short { + /// A non-dependent name that is a potential typo for a template name. + PotentialTypo = 0x0, + /// A dependent name that might instantiate to a template-name. + DependentName = 0x2, + + /// A space appears before the '<' token. + SpaceBeforeLess = 0x0, + /// No space before the '<' token + NoSpaceBeforeLess = 0x1, + + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ DependentName) + }; + + struct Loc { + Expr *TemplateName; + SourceLocation LessLoc; + AngleBracketTracker::Priority Priority; + unsigned short ParenCount, BracketCount, BraceCount; + + bool isActive(Parser &P) const { + return P.ParenCount == ParenCount && P.BracketCount == BracketCount && + P.BraceCount == BraceCount; + } + + bool isActiveOrNested(Parser &P) const { + return isActive(P) || P.ParenCount > ParenCount || + P.BracketCount > BracketCount || P.BraceCount > BraceCount; + } + }; + + SmallVector<Loc, 8> Locs; + + /// Add an expression that might have been intended to be a template name. + /// In the case of ambiguity, we arbitrarily select the innermost such + /// expression, for example in 'foo < bar < baz', 'bar' is the current + /// candidate. No attempt is made to track that 'foo' is also a candidate + /// for the case where we see a second suspicious '>' token. + void add(Parser &P, Expr *TemplateName, SourceLocation LessLoc, + Priority Prio) { + if (!Locs.empty() && Locs.back().isActive(P)) { + if (Locs.back().Priority <= Prio) { + Locs.back().TemplateName = TemplateName; + Locs.back().LessLoc = LessLoc; + Locs.back().Priority = Prio; + } + } else { + Locs.push_back({TemplateName, LessLoc, Prio, + P.ParenCount, P.BracketCount, P.BraceCount}); + } + } + + /// Mark the current potential missing template location as having been + /// handled (this happens if we pass a "corresponding" '>' or '>>' token + /// or leave a bracket scope). + void clear(Parser &P) { + while (!Locs.empty() && Locs.back().isActiveOrNested(P)) + Locs.pop_back(); + } + + /// Get the current enclosing expression that might hve been intended to be + /// a template name. + Loc *getCurrent(Parser &P) { + if (!Locs.empty() && Locs.back().isActive(P)) + return &Locs.back(); + return nullptr; + } + }; + + AngleBracketTracker AngleBrackets; + IdentifierInfo *getSEHExceptKeyword(); /// True if we are within an Objective-C container while parsing C-like decls. @@ -376,15 +464,15 @@ private: /// isTokenParen - Return true if the cur token is '(' or ')'. bool isTokenParen() const { - return Tok.getKind() == tok::l_paren || Tok.getKind() == tok::r_paren; + return Tok.isOneOf(tok::l_paren, tok::r_paren); } /// isTokenBracket - Return true if the cur token is '[' or ']'. bool isTokenBracket() const { - return Tok.getKind() == tok::l_square || Tok.getKind() == tok::r_square; + return Tok.isOneOf(tok::l_square, tok::r_square); } /// isTokenBrace - Return true if the cur token is '{' or '}'. bool isTokenBrace() const { - return Tok.getKind() == tok::l_brace || Tok.getKind() == tok::r_brace; + return Tok.isOneOf(tok::l_brace, tok::r_brace); } /// isTokenStringLiteral - True if this token is a string-literal. bool isTokenStringLiteral() const { @@ -396,11 +484,11 @@ private: isTokenBrace() || Tok.is(tok::code_completion) || Tok.isAnnotation(); } - /// \brief Returns true if the current token is '=' or is a type of '='. + /// Returns true if the current token is '=' or is a type of '='. /// For typos, give a fixit to '=' bool isTokenEqualOrEqualTypo(); - /// \brief Return the current token to the token stream and make the given + /// Return the current token to the token stream and make the given /// token the current token. void UnconsumeToken(Token &Consumed) { Token Next = Tok; @@ -423,8 +511,10 @@ private: assert(isTokenParen() && "wrong consume method"); if (Tok.getKind() == tok::l_paren) ++ParenCount; - else if (ParenCount) + else if (ParenCount) { + AngleBrackets.clear(*this); --ParenCount; // Don't let unbalanced )'s drive the count negative. + } PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); return PrevTokLocation; @@ -436,8 +526,10 @@ private: assert(isTokenBracket() && "wrong consume method"); if (Tok.getKind() == tok::l_square) ++BracketCount; - else if (BracketCount) + else if (BracketCount) { + AngleBrackets.clear(*this); --BracketCount; // Don't let unbalanced ]'s drive the count negative. + } PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); @@ -450,8 +542,10 @@ private: assert(isTokenBrace() && "wrong consume method"); if (Tok.getKind() == tok::l_brace) ++BraceCount; - else if (BraceCount) + else if (BraceCount) { + AngleBrackets.clear(*this); --BraceCount; // Don't let unbalanced }'s drive the count negative. + } PrevTokLocation = Tok.getLocation(); PP.Lex(Tok); @@ -470,7 +564,7 @@ private: return PrevTokLocation; } - /// \brief Consume the current code-completion token. + /// Consume the current code-completion token. /// /// This routine can be called to consume the code-completion token and /// continue processing in special cases where \c cutOffParsing() isn't @@ -489,7 +583,7 @@ private: /// \returns the source location of the code-completion token. SourceLocation handleUnexpectedCodeCompletionToken(); - /// \brief Abruptly cut off parsing; mainly used when we have reached the + /// Abruptly cut off parsing; mainly used when we have reached the /// code-completion point. void cutOffParsing() { if (PP.isCodeCompletionEnabled()) @@ -498,7 +592,7 @@ private: Tok.setKind(tok::eof); } - /// \brief Determine if we're at the end of the file or at a transition + /// Determine if we're at the end of the file or at a transition /// between modules. bool isEofOrEom() { tok::TokenKind Kind = Tok.getKind(); @@ -506,34 +600,34 @@ private: Kind == tok::annot_module_end || Kind == tok::annot_module_include; } - /// \brief Checks if the \p Level is valid for use in a fold expression. + /// Checks if the \p Level is valid for use in a fold expression. bool isFoldOperator(prec::Level Level) const; - /// \brief Checks if the \p Kind is a valid operator for fold expressions. + /// Checks if the \p Kind is a valid operator for fold expressions. bool isFoldOperator(tok::TokenKind Kind) const; - /// \brief Initialize all pragma handlers. + /// Initialize all pragma handlers. void initializePragmaHandlers(); - /// \brief Destroy and reset all pragma handlers. + /// Destroy and reset all pragma handlers. void resetPragmaHandlers(); - /// \brief Handle the annotation token produced for #pragma unused(...) + /// Handle the annotation token produced for #pragma unused(...) void HandlePragmaUnused(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma GCC visibility... void HandlePragmaVisibility(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma pack... void HandlePragmaPack(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma ms_struct... void HandlePragmaMSStruct(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma comment... void HandlePragmaMSComment(); @@ -549,43 +643,43 @@ private: bool HandlePragmaMSInitSeg(StringRef PragmaName, SourceLocation PragmaLocation); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma align... void HandlePragmaAlign(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma clang __debug dump... void HandlePragmaDump(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma weak id... void HandlePragmaWeak(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma weak id = id... void HandlePragmaWeakAlias(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma redefine_extname... void HandlePragmaRedefineExtname(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma STDC FP_CONTRACT... void HandlePragmaFPContract(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma clang fp ... void HandlePragmaFP(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma OPENCL EXTENSION... void HandlePragmaOpenCLExtension(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma clang __debug captured StmtResult HandlePragmaCaptured(); - /// \brief Handle the annotation token produced for + /// Handle the annotation token produced for /// #pragma clang loop and #pragma unroll. bool HandlePragmaLoopHint(LoopHint &Hint); @@ -624,13 +718,13 @@ private: Tok.setAnnotationValue(T.getAsOpaquePtr()); } - /// \brief Read an already-translated primary expression out of an annotation + /// Read an already-translated primary expression out of an annotation /// token. static ExprResult getExprAnnotation(const Token &Tok) { return ExprResult::getFromOpaquePointer(Tok.getAnnotationValue()); } - /// \brief Set the primary expression corresponding to the given annotation + /// Set the primary expression corresponding to the given annotation /// token. static void setExprAnnotation(Token &Tok, ExprResult ER) { Tok.setAnnotationValue(ER.getAsOpaquePointer()); @@ -714,7 +808,7 @@ private: /// otherwise emits a diagnostic and returns true. bool TryKeywordIdentFallback(bool DisableKeyword); - /// \brief Get the TemplateIdAnnotation from the token. + /// Get the TemplateIdAnnotation from the token. TemplateIdAnnotation *takeTemplateIdAnnotation(const Token &tok); /// TentativeParsingAction - An object that is used as a kind of "tentative @@ -812,14 +906,14 @@ private: unsigned Diag = diag::err_expected, StringRef DiagMsg = ""); - /// \brief The parser expects a semicolon and, if present, will consume it. + /// The parser expects a semicolon and, if present, will consume it. /// /// If the next token is not a semicolon, this emits the specified diagnostic, /// or, if there's just some closing-delimiter noise (e.g., ')' or ']') prior /// to the semicolon, consumes that extra token. bool ExpectAndConsumeSemi(unsigned DiagID); - /// \brief The kind of extra semi diagnostic to emit. + /// The kind of extra semi diagnostic to emit. enum ExtraSemiKind { OutsideFunction = 0, InsideStruct = 1, @@ -827,7 +921,7 @@ private: AfterMemberFunctionDefinition = 3 }; - /// \brief Consume any extra semi-colons until the end of the line. + /// Consume any extra semi-colons until the end of the line. void ConsumeExtraSemi(ExtraSemiKind Kind, unsigned TST = TST_unspecified); /// Return false if the next token is an identifier. An 'expected identifier' @@ -891,7 +985,7 @@ public: void ExitScope(); private: - /// \brief RAII object used to modify the scope flags for the current scope. + /// RAII object used to modify the scope flags for the current scope. class ParseScopeFlags { Scope *CurScope; unsigned OldFlags; @@ -920,10 +1014,10 @@ private: public: - /// \brief Control flags for SkipUntil functions. + /// Control flags for SkipUntil functions. enum SkipUntilFlags { StopAtSemi = 1 << 0, ///< Stop skipping at semicolon - /// \brief Stop skipping at specified token, but don't skip the token itself + /// Stop skipping at specified token, but don't skip the token itself StopBeforeMatch = 1 << 1, StopAtCodeCompletion = 1 << 2 ///< Stop at code completion }; @@ -1045,7 +1139,7 @@ private: Decl *D; CachedTokens Toks; - /// \brief Whether this member function had an associated template + /// Whether this member function had an associated template /// scope. When true, D is a template declaration. /// otherwise, it is a member function declaration. bool TemplateScope; @@ -1091,9 +1185,9 @@ private: /// Method - The method declaration. Decl *Method; - /// \brief Whether this member function had an associated template + /// Whether this member function had an associated template /// scope. When true, D is a template declaration. - /// othewise, it is a member function declaration. + /// otherwise, it is a member function declaration. bool TemplateScope; /// DefaultArgs - Contains the parameters of the function and @@ -1103,7 +1197,7 @@ private: /// scope at the appropriate times. SmallVector<LateParsedDefaultArgument, 8> DefaultArgs; - /// \brief The set of tokens that make up an exception-specification that + /// The set of tokens that make up an exception-specification that /// has not yet been parsed. CachedTokens *ExceptionSpecTokens; }; @@ -1135,7 +1229,7 @@ private: /// entities. typedef SmallVector<LateParsedDeclaration*,2> LateParsedDeclarationsContainer; - /// \brief Representation of a class that has been parsed, including + /// Representation of a class that has been parsed, including /// any member function declarations or definitions that need to be /// parsed after the corresponding top-level class is complete. struct ParsingClass { @@ -1143,19 +1237,19 @@ private: : TopLevelClass(TopLevelClass), TemplateScope(false), IsInterface(IsInterface), TagOrTemplate(TagOrTemplate) { } - /// \brief Whether this is a "top-level" class, meaning that it is + /// Whether this is a "top-level" class, meaning that it is /// not nested within another class. bool TopLevelClass : 1; - /// \brief Whether this class had an associated template + /// Whether this class had an associated template /// scope. When true, TagOrTemplate is a template declaration; - /// othewise, it is a tag declaration. + /// otherwise, it is a tag declaration. bool TemplateScope : 1; - /// \brief Whether this class is an __interface. + /// Whether this class is an __interface. bool IsInterface : 1; - /// \brief The class or class template whose definition we are parsing. + /// The class or class template whose definition we are parsing. Decl *TagOrTemplate; /// LateParsedDeclarations - Method declarations, inline definitions and @@ -1164,7 +1258,7 @@ private: LateParsedDeclarationsContainer LateParsedDeclarations; }; - /// \brief The stack of classes that is currently being + /// The stack of classes that is currently being /// parsed. Nested and local classes will be pushed onto this stack /// when they are parsed, and removed afterward. std::stack<ParsingClass *> ClassStack; @@ -1174,7 +1268,7 @@ private: return *ClassStack.top(); } - /// \brief RAII object used to manage the parsing of a class definition. + /// RAII object used to manage the parsing of a class definition. class ParsingClassDefinition { Parser &P; bool Popped; @@ -1187,7 +1281,7 @@ private: State(P.PushParsingClass(TagOrTemplate, TopLevelClass, IsInterface)) { } - /// \brief Pop this class of the stack. + /// Pop this class of the stack. void Pop() { assert(!Popped && "Nested class has already been popped"); Popped = true; @@ -1200,7 +1294,7 @@ private: } }; - /// \brief Contains information about any template-specific + /// Contains information about any template-specific /// information that has been parsed prior to parsing declaration /// specifiers. struct ParsedTemplateInfo { @@ -1220,31 +1314,31 @@ private: ExternLoc(ExternLoc), TemplateLoc(TemplateLoc), LastParameterListWasEmpty(false){ } - /// \brief The kind of template we are parsing. + /// The kind of template we are parsing. enum { - /// \brief We are not parsing a template at all. + /// We are not parsing a template at all. NonTemplate = 0, - /// \brief We are parsing a template declaration. + /// We are parsing a template declaration. Template, - /// \brief We are parsing an explicit specialization. + /// We are parsing an explicit specialization. ExplicitSpecialization, - /// \brief We are parsing an explicit instantiation. + /// We are parsing an explicit instantiation. ExplicitInstantiation } Kind; - /// \brief The template parameter lists, for template declarations + /// The template parameter lists, for template declarations /// and explicit specializations. TemplateParameterLists *TemplateParams; - /// \brief The location of the 'extern' keyword, if any, for an explicit + /// The location of the 'extern' keyword, if any, for an explicit /// instantiation SourceLocation ExternLoc; - /// \brief The location of the 'template' keyword, for an explicit + /// The location of the 'template' keyword, for an explicit /// instantiation. SourceLocation TemplateLoc; - /// \brief Whether the last template parameter list was empty. + /// Whether the last template parameter list was empty. bool LastParameterListWasEmpty; SourceRange getSourceRange() const LLVM_READONLY; @@ -1267,11 +1361,11 @@ private: }; NamedDecl *ParseCXXInlineMethodDef(AccessSpecifier AS, - AttributeList *AccessAttrs, - ParsingDeclarator &D, - const ParsedTemplateInfo &TemplateInfo, - const VirtSpecifiers& VS, - SourceLocation PureSpecLoc); + ParsedAttributes &AccessAttrs, + ParsingDeclarator &D, + const ParsedTemplateInfo &TemplateInfo, + const VirtSpecifiers &VS, + SourceLocation PureSpecLoc); void ParseCXXNonStaticMemberInitializer(Decl *VarD); void ParseLexedAttributes(ParsingClass &Class); void ParseLexedAttributeList(LateParsedAttrList &LAs, Decl *D, @@ -1312,6 +1406,15 @@ private: SourceRange Range; }; + struct ParsedAttributesViewWithRange : ParsedAttributesView { + ParsedAttributesViewWithRange() : ParsedAttributesView() {} + void clearListOnly() { + ParsedAttributesView::clearListOnly(); + Range = SourceRange(); + } + + SourceRange Range; + }; DeclGroupPtrTy ParseExternalDeclaration(ParsedAttributesWithRange &attrs, ParsingDeclSpec *DS = nullptr); @@ -1337,7 +1440,7 @@ private: // Objective-C External Declarations void MaybeSkipAttributes(tok::ObjCKeywordKind Kind); - DeclGroupPtrTy ParseObjCAtDirectives(); + DeclGroupPtrTy ParseObjCAtDirectives(ParsedAttributesWithRange &Attrs); DeclGroupPtrTy ParseObjCAtClassDeclaration(SourceLocation atLoc); Decl *ParseObjCAtInterfaceDeclaration(SourceLocation AtLoc, ParsedAttributes &prefixAttrs); @@ -1447,7 +1550,7 @@ private: bool isTokIdentifier_in() const; - ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, Declarator::TheContext Ctx, + ParsedType ParseObjCTypeName(ObjCDeclSpec &DS, DeclaratorContext Ctx, ParsedAttributes *ParamAttrs); void ParseObjCMethodRequirement(); Decl *ParseObjCMethodPrototype( @@ -1475,6 +1578,7 @@ public: ExprResult ParseConstantExpressionInExprEvalContext( TypeCastState isTypeCast = NotTypeCast); ExprResult ParseConstantExpression(TypeCastState isTypeCast = NotTypeCast); + ExprResult ParseCaseExpression(SourceLocation CaseLoc); ExprResult ParseConstraintExpression(); // Expr that doesn't include commas. ExprResult ParseAssignmentExpression(TypeCastState isTypeCast = NotTypeCast); @@ -1513,6 +1617,14 @@ private: } bool diagnoseUnknownTemplateId(ExprResult TemplateName, SourceLocation Less); + void checkPotentialAngleBracket(ExprResult &PotentialTemplateName); + bool checkPotentialAngleBracketDelimiter(const AngleBracketTracker::Loc &, + const Token &OpToken); + bool checkPotentialAngleBracketDelimiter(const Token &OpToken) { + if (auto *Info = AngleBrackets.getCurrent(*this)) + return checkPotentialAngleBracketDelimiter(*Info, OpToken); + return false; + } ExprResult ParsePostfixExpressionSuffix(ExprResult LHS); ExprResult ParseUnaryExprOrTypeTraitExpression(); @@ -1641,7 +1753,8 @@ private: //===--------------------------------------------------------------------===// // C++0x 8: Function declaration trailing-return-type - TypeResult ParseTrailingReturnType(SourceRange &Range); + TypeResult ParseTrailingReturnType(SourceRange &Range, + bool MayBeFollowedByDirectInit); //===--------------------------------------------------------------------===// // C++ 2.13.5: C++ Boolean Literals @@ -1737,11 +1850,11 @@ private: StmtResult ParseStatement(SourceLocation *TrailingElseLoc = nullptr, bool AllowOpenMPStandalone = false); enum AllowedConstructsKind { - /// \brief Allow any declarations, statements, OpenMP directives. + /// Allow any declarations, statements, OpenMP directives. ACK_Any, - /// \brief Allow only statements and non-standalone OpenMP directives. + /// Allow only statements and non-standalone OpenMP directives. ACK_StatementsOpenMPNonStandalone, - /// \brief Allow statements and all executable OpenMP directives + /// Allow statements and all executable OpenMP directives ACK_StatementsOpenMPAnyExecutable }; StmtResult @@ -1782,34 +1895,34 @@ private: SourceLocation *TrailingElseLoc, ParsedAttributesWithRange &Attrs); - /// \brief Describes the behavior that should be taken for an __if_exists + /// Describes the behavior that should be taken for an __if_exists /// block. enum IfExistsBehavior { - /// \brief Parse the block; this code is always used. + /// Parse the block; this code is always used. IEB_Parse, - /// \brief Skip the block entirely; this code is never used. + /// Skip the block entirely; this code is never used. IEB_Skip, - /// \brief Parse the block as a dependent block, which may be used in + /// Parse the block as a dependent block, which may be used in /// some template instantiations but not others. IEB_Dependent }; - /// \brief Describes the condition of a Microsoft __if_exists or + /// Describes the condition of a Microsoft __if_exists or /// __if_not_exists block. struct IfExistsCondition { - /// \brief The location of the initial keyword. + /// The location of the initial keyword. SourceLocation KeywordLoc; - /// \brief Whether this is an __if_exists block (rather than an + /// Whether this is an __if_exists block (rather than an /// __if_not_exists block). bool IsIfExists; - /// \brief Nested-name-specifier preceding the name. + /// Nested-name-specifier preceding the name. CXXScopeSpec SS; - /// \brief The name we're looking for. + /// The name we're looking for. UnqualifiedId Name; - /// \brief The behavior of this __if_exists or __if_not_exists block + /// The behavior of this __if_exists or __if_not_exists block /// should. IfExistsBehavior Behavior; }; @@ -1818,7 +1931,8 @@ private: void ParseMicrosoftIfExistsStatement(StmtVector &Stmts); void ParseMicrosoftIfExistsExternalDeclaration(); void ParseMicrosoftIfExistsClassDeclaration(DeclSpec::TST TagType, - AccessSpecifier& CurAS); + ParsedAttributes &AccessAttrs, + AccessSpecifier &CurAS); bool ParseMicrosoftIfExistsBraceInitializer(ExprVector &InitExprs, bool &InitExprsOk); bool ParseAsmOperandsOpt(SmallVectorImpl<IdentifierInfo *> &Names, @@ -1856,7 +1970,7 @@ private: /// A context for parsing declaration specifiers. TODO: flesh this /// out, there are other significant restrictions on specifiers than /// would be best implemented in the parser. - enum DeclSpecContext { + enum class DeclSpecContext { DSC_normal, // normal context DSC_class, // class context, enables 'friend' DSC_type_specifier, // C++ type-specifier-seq or C specifier-qualifier-list @@ -1873,18 +1987,18 @@ private: /// trailing-type-specifier)? static bool isTypeSpecifier(DeclSpecContext DSC) { switch (DSC) { - case DSC_normal: - case DSC_template_param: - case DSC_class: - case DSC_top_level: - case DSC_objc_method_result: - case DSC_condition: + case DeclSpecContext::DSC_normal: + case DeclSpecContext::DSC_template_param: + case DeclSpecContext::DSC_class: + case DeclSpecContext::DSC_top_level: + case DeclSpecContext::DSC_objc_method_result: + case DeclSpecContext::DSC_condition: return false; - case DSC_template_type_arg: - case DSC_type_specifier: - case DSC_trailing: - case DSC_alias_declaration: + case DeclSpecContext::DSC_template_type_arg: + case DeclSpecContext::DSC_type_specifier: + case DeclSpecContext::DSC_trailing: + case DeclSpecContext::DSC_alias_declaration: return true; } llvm_unreachable("Missing DeclSpecContext case"); @@ -1894,18 +2008,18 @@ private: /// deduction? static bool isClassTemplateDeductionContext(DeclSpecContext DSC) { switch (DSC) { - case DSC_normal: - case DSC_template_param: - case DSC_class: - case DSC_top_level: - case DSC_condition: - case DSC_type_specifier: + case DeclSpecContext::DSC_normal: + case DeclSpecContext::DSC_template_param: + case DeclSpecContext::DSC_class: + case DeclSpecContext::DSC_top_level: + case DeclSpecContext::DSC_condition: + case DeclSpecContext::DSC_type_specifier: return true; - case DSC_objc_method_result: - case DSC_template_type_arg: - case DSC_trailing: - case DSC_alias_declaration: + case DeclSpecContext::DSC_objc_method_result: + case DeclSpecContext::DSC_template_type_arg: + case DeclSpecContext::DSC_trailing: + case DeclSpecContext::DSC_alias_declaration: return false; } llvm_unreachable("Missing DeclSpecContext case"); @@ -1920,15 +2034,16 @@ private: bool ParsedForRangeDecl() { return !ColonLoc.isInvalid(); } }; - DeclGroupPtrTy ParseDeclaration(unsigned Context, SourceLocation &DeclEnd, + DeclGroupPtrTy ParseDeclaration(DeclaratorContext Context, + SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs); - DeclGroupPtrTy ParseSimpleDeclaration(unsigned Context, + DeclGroupPtrTy ParseSimpleDeclaration(DeclaratorContext Context, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs, bool RequireSemi, ForRangeInit *FRI = nullptr); - bool MightBeDeclarator(unsigned Context); - DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, unsigned Context, + bool MightBeDeclarator(DeclaratorContext Context); + DeclGroupPtrTy ParseDeclGroup(ParsingDeclSpec &DS, DeclaratorContext Context, SourceLocation *DeclEnd = nullptr, ForRangeInit *FRI = nullptr); Decl *ParseDeclarationAfterDeclarator(Declarator &D, @@ -1941,7 +2056,7 @@ private: Decl *ParseFunctionStatementBody(Decl *Decl, ParseScope &BodyScope); Decl *ParseFunctionTryBlock(Decl *Decl, ParseScope &BodyScope); - /// \brief When in code-completion, skip parsing of the function/method body + /// When in code-completion, skip parsing of the function/method body /// unless the body contains the code-completion point. /// /// \returns true if the function body was skipped. @@ -1951,21 +2066,24 @@ private: const ParsedTemplateInfo &TemplateInfo, AccessSpecifier AS, DeclSpecContext DSC, ParsedAttributesWithRange &Attrs); - DeclSpecContext getDeclSpecContextFromDeclaratorContext(unsigned Context); - void ParseDeclarationSpecifiers(DeclSpec &DS, - const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), - AccessSpecifier AS = AS_none, - DeclSpecContext DSC = DSC_normal, - LateParsedAttrList *LateAttrs = nullptr); - bool DiagnoseMissingSemiAfterTagDefinition(DeclSpec &DS, AccessSpecifier AS, - DeclSpecContext DSContext, - LateParsedAttrList *LateAttrs = nullptr); - - void ParseSpecifierQualifierList(DeclSpec &DS, AccessSpecifier AS = AS_none, - DeclSpecContext DSC = DSC_normal); + DeclSpecContext + getDeclSpecContextFromDeclaratorContext(DeclaratorContext Context); + void ParseDeclarationSpecifiers( + DeclSpec &DS, + const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), + AccessSpecifier AS = AS_none, + DeclSpecContext DSC = DeclSpecContext::DSC_normal, + LateParsedAttrList *LateAttrs = nullptr); + bool DiagnoseMissingSemiAfterTagDefinition( + DeclSpec &DS, AccessSpecifier AS, DeclSpecContext DSContext, + LateParsedAttrList *LateAttrs = nullptr); + + void ParseSpecifierQualifierList( + DeclSpec &DS, AccessSpecifier AS = AS_none, + DeclSpecContext DSC = DeclSpecContext::DSC_normal); void ParseObjCTypeQualifierList(ObjCDeclSpec &DS, - Declarator::TheContext Context); + DeclaratorContext Context); void ParseEnumSpecifier(SourceLocation TagLoc, DeclSpec &DS, const ParsedTemplateInfo &TemplateInfo, @@ -1986,7 +2104,7 @@ private: /// specifier or if we're not sure. bool isKnownToBeTypeSpecifier(const Token &Tok) const; - /// \brief Return true if we know that we are definitely looking at a + /// Return true if we know that we are definitely looking at a /// decl-specifier, and isn't part of an expression such as a function-style /// cast. Return false if it's no a decl-specifier, or we're not sure. bool isKnownToBeDeclarationSpecifier() { @@ -2014,19 +2132,19 @@ private: return isDeclarationSpecifier(true); } - /// \brief Determine whether this is a C++1z for-range-identifier. + /// Determine whether this is a C++1z for-range-identifier. bool isForRangeIdentifier(); - /// \brief Determine whether we are currently at the start of an Objective-C + /// Determine whether we are currently at the start of an Objective-C /// class message that appears to be missing the open bracket '['. bool isStartOfObjCClassMessageMissingOpenBracket(); - /// \brief Starting with a scope specifier, identifier, or + /// Starting with a scope specifier, identifier, or /// template-id that refers to the current class, determine whether /// this is a constructor declarator. bool isConstructorDeclarator(bool Unqualified, bool DeductionGuide = false); - /// \brief Specifies the context in which type-id/expression + /// Specifies the context in which type-id/expression /// disambiguation will occur. enum TentativeCXXTypeIdContext { TypeIdInParens, @@ -2049,7 +2167,7 @@ private: return isTypeIdInParens(isAmbiguous); } - /// \brief Checks if the current tokens form type-id or expression. + /// Checks if the current tokens form type-id or expression. /// It is similar to isTypeIdInParens but does not suppose that type-id /// is in parenthesis. bool isTypeIdUnambiguously() { @@ -2087,7 +2205,7 @@ private: InitStmtDecl, ///< Disambiguated as a simple-declaration init-statement. Error ///< Can't be any of the above! }; - /// \brief Disambiguates between the different kinds of things that can happen + /// Disambiguates between the different kinds of things that can happen /// after 'if (' or 'switch ('. This could be one of two different kinds of /// declaration (depending on whether there is a ';' later) or an expression. ConditionOrInitStatement @@ -2105,7 +2223,7 @@ private: True, False, Ambiguous, Error }; - /// \brief Based only on the given token kind, determine whether we know that + /// Based only on the given token kind, determine whether we know that /// we're at the start of an expression or a type-specifier-seq (which may /// be an expression, in C++). /// @@ -2133,7 +2251,7 @@ private: /// a type-specifier other than a cv-qualifier. bool isCXXDeclarationSpecifierAType(); - /// \brief Determine whether an identifier has been tentatively declared as a + /// Determine whether an identifier has been tentatively declared as a /// non-type. Such tentative declarations should not be found to name a type /// during a tentative parse, but also should not be annotated as a non-type. bool isTentativelyDeclared(IdentifierInfo *II); @@ -2151,7 +2269,8 @@ private: TPResult TryParsePtrOperatorSeq(); TPResult TryParseOperatorId(); TPResult TryParseInitDeclaratorList(); - TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier=true); + TPResult TryParseDeclarator(bool mayBeAbstract, bool mayHaveIdentifier = true, + bool mayHaveDirectInit = false); TPResult TryParseParameterDeclarationClause(bool *InvalidAsDeclaration = nullptr, bool VersusTemplateArg = false); @@ -2161,8 +2280,8 @@ private: public: TypeResult ParseTypeName(SourceRange *Range = nullptr, - Declarator::TheContext Context - = Declarator::TypeNameContext, + DeclaratorContext Context + = DeclaratorContext::TypeNameContext, AccessSpecifier AS = AS_none, Decl **OwnedType = nullptr, ParsedAttributes *Attrs = nullptr); @@ -2202,14 +2321,23 @@ private: DeclSpec &DS, Sema::TagUseKind TUK); // FixItLoc = possible correct location for the attributes - void ProhibitAttributes(ParsedAttributesWithRange &attrs, + void ProhibitAttributes(ParsedAttributesWithRange &Attrs, + SourceLocation FixItLoc = SourceLocation()) { + if (Attrs.Range.isInvalid()) + return; + DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + Attrs.clear(); + } + + void ProhibitAttributes(ParsedAttributesViewWithRange &Attrs, SourceLocation FixItLoc = SourceLocation()) { - if (!attrs.Range.isValid()) return; - DiagnoseProhibitedAttributes(attrs, FixItLoc); - attrs.clear(); + if (Attrs.Range.isInvalid()) + return; + DiagnoseProhibitedAttributes(Attrs.Range, FixItLoc); + Attrs.clearListOnly(); } - void DiagnoseProhibitedAttributes(ParsedAttributesWithRange &attrs, - SourceLocation FixItLoc); + void DiagnoseProhibitedAttributes(const SourceRange &Range, + SourceLocation FixItLoc); // Forbid C++11 and C2x attributes that appear on certain syntactic locations // which standard permits but we don't supported yet, for example, attributes @@ -2217,16 +2345,16 @@ private: void ProhibitCXX11Attributes(ParsedAttributesWithRange &Attrs, unsigned DiagID); - /// \brief Skip C++11 and C2x attributes and return the end location of the + /// Skip C++11 and C2x attributes and return the end location of the /// last one. /// \returns SourceLocation() if there are no attributes. SourceLocation SkipCXX11Attributes(); - /// \brief Diagnose and skip C++11 and C2x attributes that appear in syntactic + /// Diagnose and skip C++11 and C2x attributes that appear in syntactic /// locations where attributes are not allowed. void DiagnoseAndSkipCXX11Attributes(); - /// \brief Parses syntax-generic attribute arguments for attributes which are + /// Parses syntax-generic attribute arguments for attributes which are /// known to the implementation, and adds them to the given ParsedAttributes /// list with the given attribute syntax. Returns the number of arguments /// parsed for the attribute. @@ -2234,7 +2362,7 @@ private: ParseAttributeArgsCommon(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void MaybeParseGNUAttributes(Declarator &D, LateParsedAttrList *LateAttrs = nullptr) { @@ -2257,19 +2385,16 @@ private: Declarator *D = nullptr); void ParseGNUAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - AttributeList::Syntax Syntax, - Declarator *D); + ParsedAttributes &Attrs, SourceLocation *EndLoc, + IdentifierInfo *ScopeName, SourceLocation ScopeLoc, + ParsedAttr::Syntax Syntax, Declarator *D); IdentifierLoc *ParseIdentifierLoc(); unsigned ParseClangAttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, ParsedAttributes &Attrs, SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void MaybeParseCXX11Attributes(Declarator &D) { if (standardAttributesAllowed() && isCXX11AttributeSpecifier()) { @@ -2299,7 +2424,7 @@ private: SourceLocation *EndLoc = nullptr); void ParseCXX11Attributes(ParsedAttributesWithRange &attrs, SourceLocation *EndLoc = nullptr); - /// \brief Parses a C++11 (or C2x)-style attribute argument list. Returns true + /// Parses a C++11 (or C2x)-style attribute argument list. Returns true /// if this results in adding an attribute to the ParsedAttributes list. bool ParseCXX11AttributeArgs(IdentifierInfo *AttrName, SourceLocation AttrNameLoc, @@ -2335,7 +2460,7 @@ private: void ParseBorlandTypeAttributes(ParsedAttributes &attrs); void ParseOpenCLKernelAttributes(ParsedAttributes &attrs); void ParseOpenCLQualifiers(ParsedAttributes &Attrs); - /// \brief Parses opencl_unroll_hint attribute if language is OpenCL v2.0 + /// Parses opencl_unroll_hint attribute if language is OpenCL v2.0 /// or higher. /// \return false if error happens. bool MaybeParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs) { @@ -2343,7 +2468,7 @@ private: return ParseOpenCLUnrollHintAttribute(Attrs); return true; } - /// \brief Parses opencl_unroll_hint attribute. + /// Parses opencl_unroll_hint attribute. /// \return false if error happens. bool ParseOpenCLUnrollHintAttribute(ParsedAttributes &Attrs); void ParseNullabilityTypeSpecifiers(ParsedAttributes &attrs); @@ -2355,7 +2480,7 @@ private: SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); Optional<AvailabilitySpec> ParseAvailabilitySpec(); ExprResult ParseAvailabilityCheckExpr(SourceLocation StartLoc); @@ -2366,7 +2491,7 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void ParseObjCBridgeRelatedAttribute(IdentifierInfo &ObjCBridgeRelated, SourceLocation ObjCBridgeRelatedLoc, @@ -2374,7 +2499,7 @@ private: SourceLocation *endLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); void ParseTypeTagForDatatypeAttribute(IdentifierInfo &AttrName, SourceLocation AttrNameLoc, @@ -2382,15 +2507,13 @@ private: SourceLocation *EndLoc, IdentifierInfo *ScopeName, SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + ParsedAttr::Syntax Syntax); - void ParseAttributeWithTypeArg(IdentifierInfo &AttrName, - SourceLocation AttrNameLoc, - ParsedAttributes &Attrs, - SourceLocation *EndLoc, - IdentifierInfo *ScopeName, - SourceLocation ScopeLoc, - AttributeList::Syntax Syntax); + void + ParseAttributeWithTypeArg(IdentifierInfo &AttrName, + SourceLocation AttrNameLoc, ParsedAttributes &Attrs, + SourceLocation *EndLoc, IdentifierInfo *ScopeName, + SourceLocation ScopeLoc, ParsedAttr::Syntax Syntax); void ParseTypeofSpecifier(DeclSpec &DS); SourceLocation ParseDecltypeSpecifier(DeclSpec &DS); @@ -2512,20 +2635,21 @@ private: void DiagnoseUnexpectedNamespace(NamedDecl *Context); - DeclGroupPtrTy ParseNamespace(unsigned Context, SourceLocation &DeclEnd, + DeclGroupPtrTy ParseNamespace(DeclaratorContext Context, + SourceLocation &DeclEnd, SourceLocation InlineLoc = SourceLocation()); - void ParseInnerNamespace(std::vector<SourceLocation>& IdentLoc, - std::vector<IdentifierInfo*>& Ident, - std::vector<SourceLocation>& NamespaceLoc, - unsigned int index, SourceLocation& InlineLoc, - ParsedAttributes& attrs, + void ParseInnerNamespace(std::vector<SourceLocation> &IdentLoc, + std::vector<IdentifierInfo *> &Ident, + std::vector<SourceLocation> &NamespaceLoc, + unsigned int index, SourceLocation &InlineLoc, + ParsedAttributes &attrs, BalancedDelimiterTracker &Tracker); - Decl *ParseLinkage(ParsingDeclSpec &DS, unsigned Context); + Decl *ParseLinkage(ParsingDeclSpec &DS, DeclaratorContext Context); Decl *ParseExportDeclaration(); DeclGroupPtrTy ParseUsingDirectiveOrDeclaration( - unsigned Context, const ParsedTemplateInfo &TemplateInfo, + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation &DeclEnd, ParsedAttributesWithRange &attrs); - Decl *ParseUsingDirective(unsigned Context, + Decl *ParseUsingDirective(DeclaratorContext Context, SourceLocation UsingLoc, SourceLocation &DeclEnd, ParsedAttributes &attrs); @@ -2533,19 +2657,18 @@ private: struct UsingDeclarator { SourceLocation TypenameLoc; CXXScopeSpec SS; - SourceLocation TemplateKWLoc; UnqualifiedId Name; SourceLocation EllipsisLoc; void clear() { - TypenameLoc = TemplateKWLoc = EllipsisLoc = SourceLocation(); + TypenameLoc = EllipsisLoc = SourceLocation(); SS.clear(); Name.clear(); } }; - bool ParseUsingDeclarator(unsigned Context, UsingDeclarator &D); - DeclGroupPtrTy ParseUsingDeclaration(unsigned Context, + bool ParseUsingDeclarator(DeclaratorContext Context, UsingDeclarator &D); + DeclGroupPtrTy ParseUsingDeclaration(DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, SourceLocation UsingLoc, SourceLocation &DeclEnd, @@ -2586,7 +2709,7 @@ private: void MaybeParseAndDiagnoseDeclSpecAfterCXX11VirtSpecifierSeq(Declarator &D, VirtSpecifiers &VS); DeclGroupPtrTy ParseCXXClassMemberDeclaration( - AccessSpecifier AS, AttributeList *Attr, + AccessSpecifier AS, ParsedAttributes &Attr, const ParsedTemplateInfo &TemplateInfo = ParsedTemplateInfo(), ParsingDeclRAIIObject *DiagsFromTParams = nullptr); DeclGroupPtrTy ParseCXXClassMemberDeclarationWithPragmas( @@ -2623,18 +2746,18 @@ private: DeclGroupPtrTy ParseOMPDeclareSimdClauses(DeclGroupPtrTy Ptr, CachedTokens &Toks, SourceLocation Loc); - /// \brief Parses declarative OpenMP directives. + /// Parses declarative OpenMP directives. DeclGroupPtrTy ParseOpenMPDeclarativeDirectiveWithExtDecl( AccessSpecifier &AS, ParsedAttributesWithRange &Attrs, DeclSpec::TST TagType = DeclSpec::TST_unspecified, Decl *TagDecl = nullptr); - /// \brief Parse 'omp declare reduction' construct. + /// Parse 'omp declare reduction' construct. DeclGroupPtrTy ParseOpenMPDeclareReductionDirective(AccessSpecifier AS); /// Parses initializer for provided omp_priv declaration inside the reduction /// initializer. void ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm); - /// \brief Parses simple list of variables. + /// Parses simple list of variables. /// /// \param Kind Kind of the directive. /// \param Callback Callback function to be called for the list elements. @@ -2646,7 +2769,7 @@ private: const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)> & Callback, bool AllowScopeSpecifier); - /// \brief Parses declarative or executable directive. + /// Parses declarative or executable directive. /// /// \param Allowed ACK_Any, if any directives are allowed, /// ACK_StatementsOpenMPAnyExecutable - if any executable directives are @@ -2655,7 +2778,7 @@ private: /// StmtResult ParseOpenMPDeclarativeOrExecutableDirective(AllowedConstructsKind Allowed); - /// \brief Parses clause of kind \a CKind for directive of a kind \a Kind. + /// Parses clause of kind \a CKind for directive of a kind \a Kind. /// /// \param DKind Kind of current directive. /// \param CKind Kind of current clause. @@ -2664,33 +2787,45 @@ private: /// OMPClause *ParseOpenMPClause(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind, bool FirstClause); - /// \brief Parses clause with a single expression of a kind \a Kind. + /// Parses clause with a single expression of a kind \a Kind. /// /// \param Kind Kind of current clause. + /// \param ParseOnly true to skip the clause's semantic actions and return + /// nullptr. /// - OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind); - /// \brief Parses simple clause of a kind \a Kind. + OMPClause *ParseOpenMPSingleExprClause(OpenMPClauseKind Kind, + bool ParseOnly); + /// Parses simple clause of a kind \a Kind. /// /// \param Kind Kind of current clause. + /// \param ParseOnly true to skip the clause's semantic actions and return + /// nullptr. /// - OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind); - /// \brief Parses clause with a single expression and an additional argument + OMPClause *ParseOpenMPSimpleClause(OpenMPClauseKind Kind, bool ParseOnly); + /// Parses clause with a single expression and an additional argument /// of a kind \a Kind. /// /// \param Kind Kind of current clause. + /// \param ParseOnly true to skip the clause's semantic actions and return + /// nullptr. /// - OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind); - /// \brief Parses clause without any additional arguments. + OMPClause *ParseOpenMPSingleExprWithArgClause(OpenMPClauseKind Kind, + bool ParseOnly); + /// Parses clause without any additional arguments. /// /// \param Kind Kind of current clause. + /// \param ParseOnly true to skip the clause's semantic actions and return + /// nullptr. /// - OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind); - /// \brief Parses clause with the list of variables of a kind \a Kind. + OMPClause *ParseOpenMPClause(OpenMPClauseKind Kind, bool ParseOnly = false); + /// Parses clause with the list of variables of a kind \a Kind. /// /// \param Kind Kind of current clause. + /// \param ParseOnly true to skip the clause's semantic actions and return + /// nullptr. /// OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind, - OpenMPClauseKind Kind); + OpenMPClauseKind Kind, bool ParseOnly); public: /// Parses simple expression in parens for single-expression clauses of OpenMP @@ -2702,6 +2837,7 @@ public: struct OpenMPVarListDataTy { Expr *TailExpr = nullptr; SourceLocation ColonLoc; + SourceLocation RLoc; CXXScopeSpec ReductionIdScopeSpec; DeclarationNameInfo ReductionId; OpenMPDependClauseKind DepKind = OMPC_DEPEND_unknown; @@ -2721,7 +2857,7 @@ public: bool AllowConstructorName, bool AllowDeductionGuide, ParsedType ObjectType, - SourceLocation& TemplateKWLoc, + SourceLocation *TemplateKWLoc, UnqualifiedId &Result); private: @@ -2729,21 +2865,18 @@ private: // C++ 14: Templates [temp] // C++ 14.1: Template Parameters [temp.param] - Decl *ParseDeclarationStartingWithTemplate(unsigned Context, - SourceLocation &DeclEnd, - AccessSpecifier AS = AS_none, - AttributeList *AccessAttrs = nullptr); - Decl *ParseTemplateDeclarationOrSpecialization(unsigned Context, + Decl *ParseDeclarationStartingWithTemplate(DeclaratorContext Context, + SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, + AccessSpecifier AS = AS_none); + Decl *ParseTemplateDeclarationOrSpecialization(DeclaratorContext Context, SourceLocation &DeclEnd, - AccessSpecifier AS, - AttributeList *AccessAttrs); + ParsedAttributes &AccessAttrs, + AccessSpecifier AS); Decl *ParseSingleDeclarationAfterTemplate( - unsigned Context, - const ParsedTemplateInfo &TemplateInfo, - ParsingDeclRAIIObject &DiagsFromParams, - SourceLocation &DeclEnd, - AccessSpecifier AS=AS_none, - AttributeList *AccessAttrs = nullptr); + DeclaratorContext Context, const ParsedTemplateInfo &TemplateInfo, + ParsingDeclRAIIObject &DiagsFromParams, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none); bool ParseTemplateParameters(unsigned Depth, SmallVectorImpl<NamedDecl *> &TemplateParams, SourceLocation &LAngleLoc, @@ -2782,10 +2915,11 @@ private: bool ParseTemplateArgumentList(TemplateArgList &TemplateArgs); ParsedTemplateArgument ParseTemplateTemplateArgument(); ParsedTemplateArgument ParseTemplateArgument(); - Decl *ParseExplicitInstantiation(unsigned Context, + Decl *ParseExplicitInstantiation(DeclaratorContext Context, SourceLocation ExternLoc, SourceLocation TemplateLoc, SourceLocation &DeclEnd, + ParsedAttributes &AccessAttrs, AccessSpecifier AS = AS_none); //===--------------------------------------------------------------------===// diff --git a/include/clang/Parse/RAIIObjectsForParser.h b/include/clang/Parse/RAIIObjectsForParser.h index 0422b038da656..f45d6434833ea 100644 --- a/include/clang/Parse/RAIIObjectsForParser.h +++ b/include/clang/Parse/RAIIObjectsForParser.h @@ -25,7 +25,7 @@ namespace clang { // TODO: move ParsingClassDefinition here. // TODO: move TentativeParsingAction here. - /// \brief A RAII object used to temporarily suppress access-like + /// A RAII object used to temporarily suppress access-like /// checking. Access-like checks are those associated with /// controlling the use of a declaration, like C++ access control /// errors and deprecation warnings. They are contextually @@ -84,7 +84,7 @@ namespace clang { } }; - /// \brief RAII object used to inform the actions that we're + /// RAII object used to inform the actions that we're /// currently parsing a declaration. This is active when parsing a /// variable's initializer, but not when parsing the body of a /// class or function definition. @@ -202,7 +202,7 @@ namespace clang { ParsingDeclRAIIObject ParsingRAII; public: - ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, TheContext C) + ParsingDeclarator(Parser &P, const ParsingDeclSpec &DS, DeclaratorContext C) : Declarator(DS, C), ParsingRAII(P, &DS.getDelayedDiagnosticPool()) { } @@ -288,7 +288,7 @@ namespace clang { } }; - /// \brief RAII object that makes '>' behave either as an operator + /// RAII object that makes '>' behave either as an operator /// or as the closing angle bracket for a template argument list. class GreaterThanIsOperatorScope { bool &GreaterThanIsOperator; @@ -320,7 +320,7 @@ namespace clang { } }; - /// \brief RAII object that makes sure paren/bracket/brace count is correct + /// RAII object that makes sure paren/bracket/brace count is correct /// after declaration/statement parsing, even when there's a parsing error. class ParenBraceBracketBalancer { Parser &P; @@ -331,6 +331,7 @@ namespace clang { BraceCount(p.BraceCount) { } ~ParenBraceBracketBalancer() { + P.AngleBrackets.clear(P); P.ParenCount = ParenCount; P.BracketCount = BracketCount; P.BraceCount = BraceCount; @@ -361,7 +362,7 @@ namespace clang { } }; - /// \brief RAII class that helps handle the parsing of an open/close delimiter + /// RAII class that helps handle the parsing of an open/close delimiter /// pair, such as braces { ... } or parentheses ( ... ). class BalancedDelimiterTracker : public GreaterThanIsOperatorScope { Parser& P; @@ -378,8 +379,6 @@ namespace clang { } } - enum { MaxDepth = 256 }; - bool diagnoseOverflow(); bool diagnoseMissingClose(); @@ -443,7 +442,7 @@ namespace clang { void skipToEnd(); }; - /// \brief RAIIObject to destroy the contents of a SmallVector of + /// RAIIObject to destroy the contents of a SmallVector of /// TemplateIdAnnotation pointers and clear the vector. class DestroyTemplateIdAnnotationsRAIIObj { SmallVectorImpl<TemplateIdAnnotation *> &Container; diff --git a/include/clang/Rewrite/Core/DeltaTree.h b/include/clang/Rewrite/Core/DeltaTree.h index fbffb38e377dd..f798e9fc41eb3 100644 --- a/include/clang/Rewrite/Core/DeltaTree.h +++ b/include/clang/Rewrite/Core/DeltaTree.h @@ -1,4 +1,4 @@ -//===--- DeltaTree.h - B-Tree for Rewrite Delta tracking --------*- C++ -*-===// +//===- DeltaTree.h - B-Tree for Rewrite Delta tracking ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,8 +14,6 @@ #ifndef LLVM_CLANG_REWRITE_CORE_DELTATREE_H #define LLVM_CLANG_REWRITE_CORE_DELTATREE_H -#include "llvm/Support/Compiler.h" - namespace clang { /// DeltaTree - a multiway search tree (BTree) structure with some fancy @@ -27,12 +25,14 @@ namespace clang { /// as well, without traversing the whole tree. class DeltaTree { void *Root; // "DeltaTreeNode *" - void operator=(const DeltaTree &) = delete; + public: DeltaTree(); // Note: Currently we only support copying when the RHS is empty. DeltaTree(const DeltaTree &RHS); + + DeltaTree &operator=(const DeltaTree &) = delete; ~DeltaTree(); /// getDeltaAt - Return the accumulated delta at the specified file offset. @@ -45,6 +45,7 @@ namespace clang { /// into the current DeltaTree at offset FileIndex. void AddDelta(unsigned FileIndex, int Delta); }; -} // end namespace clang -#endif +} // namespace clang + +#endif // LLVM_CLANG_REWRITE_CORE_DELTATREE_H diff --git a/include/clang/Rewrite/Core/HTMLRewrite.h b/include/clang/Rewrite/Core/HTMLRewrite.h index 1fd7c7a3f84e2..0f1f490d8305a 100644 --- a/include/clang/Rewrite/Core/HTMLRewrite.h +++ b/include/clang/Rewrite/Core/HTMLRewrite.h @@ -31,7 +31,8 @@ namespace html { /// start/end tags are placed at the start/end of each line if the range is /// multiline. void HighlightRange(Rewriter &R, SourceLocation B, SourceLocation E, - const char *StartTag, const char *EndTag); + const char *StartTag, const char *EndTag, + bool IsTokenRange = true); /// HighlightRange - Highlight a range in the source code with the specified /// start/end tags. The Start/end of the range must be in the same file. diff --git a/include/clang/Rewrite/Core/RewriteBuffer.h b/include/clang/Rewrite/Core/RewriteBuffer.h index d69c69b81e482..c618298f5e82e 100644 --- a/include/clang/Rewrite/Core/RewriteBuffer.h +++ b/include/clang/Rewrite/Core/RewriteBuffer.h @@ -1,4 +1,4 @@ -//===--- RewriteBuffer.h - Buffer rewriting interface -----------*- C++ -*-===// +//===- RewriteBuffer.h - Buffer rewriting interface -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,7 +16,6 @@ #include "llvm/ADT/StringRef.h" namespace clang { - class Rewriter; /// RewriteBuffer - As code is rewritten, SourceBuffer's from the original /// input with modifications get a new RewriteBuffer associated with them. The @@ -26,12 +25,16 @@ namespace clang { /// locations after the insertion point have to be mapped. class RewriteBuffer { friend class Rewriter; + /// Deltas - Keep track of all the deltas in the source code due to insertions /// and deletions. DeltaTree Deltas; + RewriteRope Buffer; + public: - typedef RewriteRope::const_iterator iterator; + using iterator = RewriteRope::const_iterator; + iterator begin() const { return Buffer.begin(); } iterator end() const { return Buffer.end(); } unsigned size() const { return Buffer.size(); } @@ -45,7 +48,7 @@ public: Initialize(Input.begin(), Input.end()); } - /// \brief Write to \p Stream the result of applying all changes to the + /// Write to \p Stream the result of applying all changes to the /// original buffer. /// Note that it isn't safe to use this function to overwrite memory mapped /// files in-place (PR17960). Consider using a higher-level utility such as @@ -61,7 +64,6 @@ public: /// InsertText - Insert some text at the specified point, where the offset in /// the buffer is specified relative to the original SourceBuffer. The /// text is inserted after the specified location. - /// void InsertText(unsigned OrigOffset, StringRef Str, bool InsertAfter = true); @@ -87,8 +89,7 @@ public: void ReplaceText(unsigned OrigOffset, unsigned OrigLength, StringRef NewStr); -private: // Methods only usable by Rewriter. - +private: /// getMappedOffset - Given an offset into the original SourceBuffer that this /// RewriteBuffer is based on, map it into the offset space of the /// RewriteBuffer. If AfterInserts is true and if the OrigOffset indicates a @@ -112,6 +113,6 @@ private: // Methods only usable by Rewriter. } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_REWRITE_CORE_REWRITEBUFFER_H diff --git a/include/clang/Rewrite/Core/RewriteRope.h b/include/clang/Rewrite/Core/RewriteRope.h index 50025544854a6..2a0e0a4a639b1 100644 --- a/include/clang/Rewrite/Core/RewriteRope.h +++ b/include/clang/Rewrite/Core/RewriteRope.h @@ -1,4 +1,4 @@ -//===--- RewriteRope.h - Rope specialized for rewriter ----------*- C++ -*-===// +//===- RewriteRope.h - Rope specialized for rewriter ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,13 +16,13 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringRef.h" -#include "llvm/Support/Compiler.h" #include <cassert> #include <cstddef> -#include <cstring> #include <iterator> +#include <utility> namespace clang { + //===--------------------------------------------------------------------===// // RopeRefCountString Class //===--------------------------------------------------------------------===// @@ -58,11 +58,10 @@ namespace clang { /// different offsets) which is a nice constant time operation. struct RopePiece { llvm::IntrusiveRefCntPtr<RopeRefCountString> StrData; - unsigned StartOffs; - unsigned EndOffs; - - RopePiece() : StrData(nullptr), StartOffs(0), EndOffs(0) {} + unsigned StartOffs = 0; + unsigned EndOffs = 0; + RopePiece() = default; RopePiece(llvm::IntrusiveRefCntPtr<RopeRefCountString> Str, unsigned Start, unsigned End) : StrData(std::move(Str)), StartOffs(Start), EndOffs(End) {} @@ -88,18 +87,18 @@ namespace clang { class RopePieceBTreeIterator : public std::iterator<std::forward_iterator_tag, const char, ptrdiff_t> { /// CurNode - The current B+Tree node that we are inspecting. - const void /*RopePieceBTreeLeaf*/ *CurNode; + const void /*RopePieceBTreeLeaf*/ *CurNode = nullptr; + /// CurPiece - The current RopePiece in the B+Tree node that we're /// inspecting. - const RopePiece *CurPiece; + const RopePiece *CurPiece = nullptr; + /// CurChar - The current byte in the RopePiece we are pointing to. - unsigned CurChar; + unsigned CurChar = 0; + public: - // begin iterator. + RopePieceBTreeIterator() = default; RopePieceBTreeIterator(const void /*RopePieceBTreeNode*/ *N); - // end iterator - RopePieceBTreeIterator() - : CurNode(nullptr), CurPiece(nullptr), CurChar(0) {} char operator*() const { return (*CurPiece)[CurChar]; @@ -119,7 +118,8 @@ namespace clang { MoveToNextPiece(); return *this; } - inline RopePieceBTreeIterator operator++(int) { // Postincrement + + RopePieceBTreeIterator operator++(int) { // Postincrement RopePieceBTreeIterator tmp = *this; ++*this; return tmp; } @@ -136,13 +136,15 @@ namespace clang { class RopePieceBTree { void /*RopePieceBTreeNode*/ *Root; - void operator=(const RopePieceBTree &) = delete; + public: RopePieceBTree(); RopePieceBTree(const RopePieceBTree &RHS); + RopePieceBTree &operator=(const RopePieceBTree &) = delete; ~RopePieceBTree(); - typedef RopePieceBTreeIterator iterator; + using iterator = RopePieceBTreeIterator; + iterator begin() const { return iterator(Root); } iterator end() const { return iterator(); } unsigned size() const; @@ -168,19 +170,18 @@ class RewriteRope { /// We allocate space for string data out of a buffer of size AllocChunkSize. /// This keeps track of how much space is left. llvm::IntrusiveRefCntPtr<RopeRefCountString> AllocBuffer; - unsigned AllocOffs; enum { AllocChunkSize = 4080 }; + unsigned AllocOffs = AllocChunkSize; public: - RewriteRope() : AllocBuffer(nullptr), AllocOffs(AllocChunkSize) {} - RewriteRope(const RewriteRope &RHS) - : Chunks(RHS.Chunks), AllocBuffer(nullptr), AllocOffs(AllocChunkSize) { - } + RewriteRope() = default; + RewriteRope(const RewriteRope &RHS) : Chunks(RHS.Chunks) {} + + using iterator = RopePieceBTree::iterator; + using const_iterator = RopePieceBTree::iterator; - typedef RopePieceBTree::iterator iterator; - typedef RopePieceBTree::iterator const_iterator; iterator begin() const { return Chunks.begin(); } - iterator end() const { return Chunks.end(); } + iterator end() const { return Chunks.end(); } unsigned size() const { return Chunks.size(); } void clear() { @@ -209,6 +210,6 @@ private: RopePiece MakeRopeString(const char *Start, const char *End); }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_REWRITE_CORE_REWRITEROPE_H diff --git a/include/clang/Rewrite/Core/Rewriter.h b/include/clang/Rewrite/Core/Rewriter.h index 800372ea557f6..107968a9fb436 100644 --- a/include/clang/Rewrite/Core/Rewriter.h +++ b/include/clang/Rewrite/Core/Rewriter.h @@ -1,4 +1,4 @@ -//===--- Rewriter.h - Code rewriting interface ------------------*- C++ -*-===// +//===- Rewriter.h - Code rewriting interface --------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,52 +15,55 @@ #ifndef LLVM_CLANG_REWRITE_CORE_REWRITER_H #define LLVM_CLANG_REWRITE_CORE_REWRITER_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Rewrite/Core/RewriteBuffer.h" -#include <cstring> +#include "llvm/ADT/StringRef.h" #include <map> #include <string> namespace clang { - class LangOptions; - class SourceManager; + +class LangOptions; +class SourceManager; /// Rewriter - This is the main interface to the rewrite buffers. Its primary /// job is to dispatch high-level requests to the low-level RewriteBuffers that /// are involved. class Rewriter { - SourceManager *SourceMgr; - const LangOptions *LangOpts; + SourceManager *SourceMgr = nullptr; + const LangOptions *LangOpts = nullptr; std::map<FileID, RewriteBuffer> RewriteBuffers; + public: struct RewriteOptions { - /// \brief Given a source range, true to include previous inserts at the + /// Given a source range, true to include previous inserts at the /// beginning of the range as part of the range itself (true by default). - bool IncludeInsertsAtBeginOfRange; - /// \brief Given a source range, true to include previous inserts at the + bool IncludeInsertsAtBeginOfRange = true; + + /// Given a source range, true to include previous inserts at the /// end of the range as part of the range itself (true by default). - bool IncludeInsertsAtEndOfRange; - /// \brief If true and removing some text leaves a blank line + bool IncludeInsertsAtEndOfRange = true; + + /// If true and removing some text leaves a blank line /// also remove the empty line (false by default). - bool RemoveLineIfEmpty; + bool RemoveLineIfEmpty = false; - RewriteOptions() - : IncludeInsertsAtBeginOfRange(true), - IncludeInsertsAtEndOfRange(true), - RemoveLineIfEmpty(false) { } + RewriteOptions() {} }; - typedef std::map<FileID, RewriteBuffer>::iterator buffer_iterator; - typedef std::map<FileID, RewriteBuffer>::const_iterator const_buffer_iterator; + using buffer_iterator = std::map<FileID, RewriteBuffer>::iterator; + using const_buffer_iterator = std::map<FileID, RewriteBuffer>::const_iterator; + explicit Rewriter() = default; explicit Rewriter(SourceManager &SM, const LangOptions &LO) - : SourceMgr(&SM), LangOpts(&LO) {} - explicit Rewriter() : SourceMgr(nullptr), LangOpts(nullptr) {} + : SourceMgr(&SM), LangOpts(&LO) {} void setSourceMgr(SourceManager &SM, const LangOptions &LO) { SourceMgr = &SM; LangOpts = &LO; } + SourceManager &getSourceMgr() const { return *SourceMgr; } const LangOptions &getLangOpts() const { return *LangOpts; } @@ -82,7 +85,6 @@ public: /// in different buffers, this returns an empty string. /// /// Note that this method is not particularly efficient. - /// std::string getRewrittenText(SourceRange Range) const; /// InsertText - Insert the specified string at the specified location in the @@ -103,7 +105,7 @@ public: return InsertText(Loc, Str); } - /// \brief Insert the specified string after the token in the + /// Insert the specified string after the token in the /// specified location. bool InsertTextAfterToken(SourceLocation Loc, StringRef Str); @@ -120,13 +122,13 @@ public: bool RemoveText(SourceLocation Start, unsigned Length, RewriteOptions opts = RewriteOptions()); - /// \brief Remove the specified text region. + /// Remove the specified text region. bool RemoveText(CharSourceRange range, RewriteOptions opts = RewriteOptions()) { return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); } - /// \brief Remove the specified text region. + /// Remove the specified text region. bool RemoveText(SourceRange range, RewriteOptions opts = RewriteOptions()) { return RemoveText(range.getBegin(), getRangeSize(range, opts), opts); } @@ -149,7 +151,7 @@ public: /// operation. bool ReplaceText(SourceRange range, SourceRange replacementRange); - /// \brief Increase indentation for the lines between the given source range. + /// 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 /// lower than the given range. @@ -190,6 +192,6 @@ private: unsigned getLocationOffsetAndFileID(SourceLocation Loc, FileID &FID) const; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_REWRITE_CORE_REWRITER_H diff --git a/include/clang/Rewrite/Core/TokenRewriter.h b/include/clang/Rewrite/Core/TokenRewriter.h index 0f71e81c313e7..ab2c2c8b0adb2 100644 --- a/include/clang/Rewrite/Core/TokenRewriter.h +++ b/include/clang/Rewrite/Core/TokenRewriter.h @@ -1,4 +1,4 @@ -//===--- TokenRewriter.h - Token-based Rewriter -----------------*- C++ -*-===// +//===- TokenRewriter.h - Token-based Rewriter -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,13 +17,16 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Lex/Token.h" +#include <cassert> #include <list> #include <map> #include <memory> namespace clang { - class LangOptions; - class ScratchBuffer; + +class LangOptions; +class ScratchBuffer; +class SourceManager; class TokenRewriter { /// TokenList - This is the list of raw tokens that make up this file. Each @@ -31,7 +34,7 @@ namespace clang { std::list<Token> TokenList; /// TokenRefTy - This is the type used to refer to a token in the TokenList. - typedef std::list<Token>::iterator TokenRefTy; + using TokenRefTy = std::list<Token>::iterator; /// TokenAtLoc - This map indicates which token exists at a specific /// SourceLocation. Since each token has a unique SourceLocation, this is a @@ -40,23 +43,24 @@ namespace clang { std::map<SourceLocation, TokenRefTy> TokenAtLoc; /// ScratchBuf - This is the buffer that we create scratch tokens from. - /// std::unique_ptr<ScratchBuffer> ScratchBuf; - TokenRewriter(const TokenRewriter &) = delete; - void operator=(const TokenRewriter &) = delete; public: /// TokenRewriter - This creates a TokenRewriter for the file with the /// specified FileID. TokenRewriter(FileID FID, SourceManager &SM, const LangOptions &LO); + + TokenRewriter(const TokenRewriter &) = delete; + TokenRewriter &operator=(const TokenRewriter &) = delete; ~TokenRewriter(); - typedef std::list<Token>::const_iterator token_iterator; + using token_iterator = std::list<Token>::const_iterator; + token_iterator token_begin() const { return TokenList.begin(); } token_iterator token_end() const { return TokenList.end(); } - token_iterator AddTokenBefore(token_iterator I, const char *Val); + token_iterator AddTokenAfter(token_iterator I, const char *Val) { assert(I != token_end() && "Cannot insert after token_end()!"); return AddTokenBefore(++I, Val); @@ -72,8 +76,6 @@ namespace clang { TokenRefTy AddToken(const Token &T, TokenRefTy Where); }; +} // namespace clang - -} // end namespace clang - -#endif +#endif // LLVM_CLANG_REWRITE_CORE_TOKENREWRITER_H diff --git a/include/clang/Rewrite/Frontend/FixItRewriter.h b/include/clang/Rewrite/Frontend/FixItRewriter.h index 3b1b31e0cdee0..7456840bc5c16 100644 --- a/include/clang/Rewrite/Frontend/FixItRewriter.h +++ b/include/clang/Rewrite/Frontend/FixItRewriter.h @@ -1,4 +1,4 @@ -//===--- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ----*- C++ -*-===// +//===- FixItRewriter.h - Fix-It Rewriter Diagnostic Client ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,105 +12,108 @@ // then forwards any diagnostics to the adapted diagnostic client. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H #define LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H #include "clang/Basic/Diagnostic.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" #include "clang/Edit/EditedSource.h" #include "clang/Rewrite/Core/Rewriter.h" +#include <memory> +#include <string> +#include <utility> +#include <vector> namespace clang { +class LangOptions; class SourceManager; -class FileEntry; class FixItOptions { public: - FixItOptions() : InPlace(false), FixWhatYouCan(false), - FixOnlyWarnings(false), Silent(false) { } - + FixItOptions() = default; virtual ~FixItOptions(); - /// \brief This file is about to be rewritten. Return the name of the file + /// This file is about to be rewritten. Return the name of the file /// that is okay to write to. /// /// \param fd out parameter for file descriptor. After the call it may be set /// to an open file descriptor for the returned filename, or it will be -1 /// otherwise. - /// virtual std::string RewriteFilename(const std::string &Filename, int &fd) = 0; /// True if files should be updated in place. RewriteFilename is only called /// if this is false. - bool InPlace; + bool InPlace = false; - /// \brief Whether to abort fixing a file when not all errors could be fixed. - bool FixWhatYouCan; + /// Whether to abort fixing a file when not all errors could be fixed. + bool FixWhatYouCan = false; - /// \brief Whether to only fix warnings and not errors. - bool FixOnlyWarnings; + /// Whether to only fix warnings and not errors. + bool FixOnlyWarnings = false; - /// \brief If true, only pass the diagnostic to the actual diagnostic consumer + /// If true, only pass the diagnostic to the actual diagnostic consumer /// if it is an error or a fixit was applied as part of the diagnostic. /// It basically silences warnings without accompanying fixits. - bool Silent; + bool Silent = false; }; class FixItRewriter : public DiagnosticConsumer { - /// \brief The diagnostics machinery. + /// The diagnostics machinery. DiagnosticsEngine &Diags; edit::EditedSource Editor; - /// \brief The rewriter used to perform the various code + /// The rewriter used to perform the various code /// modifications. Rewriter Rewrite; - /// \brief The diagnostic client that performs the actual formatting + /// The diagnostic client that performs the actual formatting /// of error messages. DiagnosticConsumer *Client; std::unique_ptr<DiagnosticConsumer> Owner; - /// \brief Turn an input path into an output path. NULL implies overwriting + /// Turn an input path into an output path. NULL implies overwriting /// the original. FixItOptions *FixItOpts; - /// \brief The number of rewriter failures. - unsigned NumFailures; + /// The number of rewriter failures. + unsigned NumFailures = 0; - /// \brief Whether the previous diagnostic was not passed to the consumer. - bool PrevDiagSilenced; + /// Whether the previous diagnostic was not passed to the consumer. + bool PrevDiagSilenced = false; public: - typedef Rewriter::buffer_iterator iterator; - - /// \brief Initialize a new fix-it rewriter. + /// Initialize a new fix-it rewriter. FixItRewriter(DiagnosticsEngine &Diags, SourceManager &SourceMgr, const LangOptions &LangOpts, FixItOptions *FixItOpts); - /// \brief Destroy the fix-it rewriter. + /// Destroy the fix-it rewriter. ~FixItRewriter() override; - /// \brief Check whether there are modifications for a given file. + /// Check whether there are modifications for a given file. bool IsModified(FileID ID) const { return Rewrite.getRewriteBufferFor(ID) != nullptr; } + using iterator = Rewriter::buffer_iterator; + // Iteration over files with changes. iterator buffer_begin() { return Rewrite.buffer_begin(); } iterator buffer_end() { return Rewrite.buffer_end(); } - /// \brief Write a single modified source file. + /// Write a single modified source file. /// /// \returns true if there was an error, false otherwise. bool WriteFixedFile(FileID ID, raw_ostream &OS); - /// \brief Write the modified source files. + /// Write the modified source files. /// /// \returns true if there was an error, false otherwise. bool WriteFixedFiles( - std::vector<std::pair<std::string, std::string> > *RewrittenFiles=nullptr); + std::vector<std::pair<std::string, std::string>> *RewrittenFiles = nullptr); /// IncludeInDiagnosticCounts - This method (whose default implementation /// returns true) indicates whether the diagnostics handled by this @@ -123,10 +126,10 @@ public: void HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const Diagnostic &Info) override; - /// \brief Emit a diagnostic via the adapted diagnostic client. + /// Emit a diagnostic via the adapted diagnostic client. void Diag(SourceLocation Loc, unsigned DiagID); }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_REWRITE_FRONTEND_FIXITREWRITER_H diff --git a/include/clang/Rewrite/Frontend/FrontendActions.h b/include/clang/Rewrite/Frontend/FrontendActions.h index 5f83ac16fedf6..40d2f4c22afe0 100644 --- a/include/clang/Rewrite/Frontend/FrontendActions.h +++ b/include/clang/Rewrite/Frontend/FrontendActions.h @@ -46,7 +46,7 @@ public: ~FixItAction() override; }; -/// \brief Emits changes to temporary files and uses them for the original +/// Emits changes to temporary files and uses them for the original /// frontend action. class FixItRecompile : public WrapperFrontendAction { public: diff --git a/include/clang/Sema/AnalysisBasedWarnings.h b/include/clang/Sema/AnalysisBasedWarnings.h index 64dd2d36bef89..6e8d83974e5b7 100644 --- a/include/clang/Sema/AnalysisBasedWarnings.h +++ b/include/clang/Sema/AnalysisBasedWarnings.h @@ -54,34 +54,34 @@ private: /// \name Statistics /// @{ - /// \brief Number of function CFGs built and analyzed. + /// Number of function CFGs built and analyzed. unsigned NumFunctionsAnalyzed; - /// \brief Number of functions for which the CFG could not be successfully + /// Number of functions for which the CFG could not be successfully /// built. unsigned NumFunctionsWithBadCFGs; - /// \brief Total number of blocks across all CFGs. + /// Total number of blocks across all CFGs. unsigned NumCFGBlocks; - /// \brief Largest number of CFG blocks for a single function analyzed. + /// Largest number of CFG blocks for a single function analyzed. unsigned MaxCFGBlocksPerFunction; - /// \brief Total number of CFGs with variables analyzed for uninitialized + /// Total number of CFGs with variables analyzed for uninitialized /// uses. unsigned NumUninitAnalysisFunctions; - /// \brief Total number of variables analyzed for uninitialized uses. + /// Total number of variables analyzed for uninitialized uses. unsigned NumUninitAnalysisVariables; - /// \brief Max number of variables analyzed for uninitialized uses in a single + /// Max number of variables analyzed for uninitialized uses in a single /// function. unsigned MaxUninitAnalysisVariablesPerFunction; - /// \brief Total number of block visits during uninitialized use analysis. + /// Total number of block visits during uninitialized use analysis. unsigned NumUninitAnalysisBlockVisits; - /// \brief Max number of block visits during uninitialized use analysis of + /// Max number of block visits during uninitialized use analysis of /// a single function. unsigned MaxUninitAnalysisBlockVisitsPerFunction; diff --git a/include/clang/Sema/CodeCompleteConsumer.h b/include/clang/Sema/CodeCompleteConsumer.h index 5d280b5608e71..ede3ddf919931 100644 --- a/include/clang/Sema/CodeCompleteConsumer.h +++ b/include/clang/Sema/CodeCompleteConsumer.h @@ -1,4 +1,4 @@ -//===---- CodeCompleteConsumer.h - Code Completion Interface ----*- C++ -*-===// +//===- CodeCompleteConsumer.h - Code Completion Interface -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,107 +10,141 @@ // This file defines the CodeCompleteConsumer class. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H #define LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H #include "clang-c/Index.h" -#include "clang/AST/CanonicalType.h" -#include "clang/AST/DeclBase.h" #include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" #include "clang/Sema/CodeCompleteOptions.h" #include "clang/Sema/DeclSpec.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <memory> #include <string> #include <utility> namespace clang { +class ASTContext; class Decl; +class DeclContext; +class FunctionDecl; +class FunctionTemplateDecl; +class IdentifierInfo; +class LangOptions; +class NamedDecl; +class NestedNameSpecifier; +class Preprocessor; +class RawComment; +class Sema; +class UsingShadowDecl; -/// \brief Default priority values for code-completion results based +/// Default priority values for code-completion results based /// on their kind. enum { - /// \brief Priority for the next initialization in a constructor initializer + /// Priority for the next initialization in a constructor initializer /// list. CCP_NextInitializer = 7, - /// \brief Priority for an enumeration constant inside a switch whose + + /// Priority for an enumeration constant inside a switch whose /// condition is of the enumeration type. CCP_EnumInCase = 7, - /// \brief Priority for a send-to-super completion. + + /// Priority for a send-to-super completion. CCP_SuperCompletion = 20, - /// \brief Priority for a declaration that is in the local scope. + + /// Priority for a declaration that is in the local scope. CCP_LocalDeclaration = 34, - /// \brief Priority for a member declaration found from the current + + /// Priority for a member declaration found from the current /// method or member function. CCP_MemberDeclaration = 35, - /// \brief Priority for a language keyword (that isn't any of the other + + /// Priority for a language keyword (that isn't any of the other /// categories). CCP_Keyword = 40, - /// \brief Priority for a code pattern. + + /// Priority for a code pattern. CCP_CodePattern = 40, - /// \brief Priority for a non-type declaration. + + /// Priority for a non-type declaration. CCP_Declaration = 50, - /// \brief Priority for a type. + + /// Priority for a type. CCP_Type = CCP_Declaration, - /// \brief Priority for a constant value (e.g., enumerator). + + /// Priority for a constant value (e.g., enumerator). CCP_Constant = 65, - /// \brief Priority for a preprocessor macro. + + /// Priority for a preprocessor macro. CCP_Macro = 70, - /// \brief Priority for a nested-name-specifier. + + /// Priority for a nested-name-specifier. CCP_NestedNameSpecifier = 75, - /// \brief Priority for a result that isn't likely to be what the user wants, + + /// Priority for a result that isn't likely to be what the user wants, /// but is included for completeness. CCP_Unlikely = 80, - /// \brief Priority for the Objective-C "_cmd" implicit parameter. + /// Priority for the Objective-C "_cmd" implicit parameter. CCP_ObjC_cmd = CCP_Unlikely }; -/// \brief Priority value deltas that are added to code-completion results +/// Priority value deltas that are added to code-completion results /// based on the context of the result. enum { - /// \brief The result is in a base class. + /// The result is in a base class. CCD_InBaseClass = 2, - /// \brief The result is a C++ non-static member function whose qualifiers + + /// The result is a C++ non-static member function whose qualifiers /// exactly match the object type on which the member function can be called. CCD_ObjectQualifierMatch = -1, - /// \brief The selector of the given message exactly matches the selector + + /// The selector of the given message exactly matches the selector /// of the current method, which might imply that some kind of delegation /// is occurring. CCD_SelectorMatch = -3, - /// \brief Adjustment to the "bool" type in Objective-C, where the typedef + /// Adjustment to the "bool" type in Objective-C, where the typedef /// "BOOL" is preferred. CCD_bool_in_ObjC = 1, - /// \brief Adjustment for KVC code pattern priorities when it doesn't look + /// Adjustment for KVC code pattern priorities when it doesn't look /// like the CCD_ProbablyNotObjCCollection = 15, - /// \brief An Objective-C method being used as a property. + /// An Objective-C method being used as a property. CCD_MethodAsProperty = 2, - /// \brief An Objective-C block property completed as a setter with a + /// An Objective-C block property completed as a setter with a /// block placeholder. CCD_BlockPropertySetter = 3 }; -/// \brief Priority value factors by which we will divide or multiply the +/// Priority value factors by which we will divide or multiply the /// priority of a code-completion result. enum { - /// \brief Divide by this factor when a code-completion result's type exactly + /// Divide by this factor when a code-completion result's type exactly /// matches the type we expect. CCF_ExactTypeMatch = 4, - /// \brief Divide by this factor when a code-completion result's type is + + /// Divide by this factor when a code-completion result's type is /// similar to the type we expect (e.g., both arithmetic types, both /// Objective-C object pointer types). CCF_SimilarTypeMatch = 2 }; -/// \brief A simplified classification of types used when determining +/// A simplified classification of types used when determining /// "similar" types for code completion. enum SimplifiedTypeClass { STC_Arithmetic, @@ -124,14 +158,14 @@ enum SimplifiedTypeClass { STC_Void }; -/// \brief Determine the simplified type class of the given canonical type. +/// Determine the simplified type class of the given canonical type. SimplifiedTypeClass getSimplifiedTypeClass(CanQualType T); -/// \brief Determine the type that this declaration will have if it is used +/// Determine the type that this declaration will have if it is used /// as a type or in an expression. QualType getDeclUsageType(ASTContext &C, const NamedDecl *ND); -/// \brief Determine the priority to be given to a macro code completion result +/// Determine the priority to be given to a macro code completion result /// with the given name. /// /// \param MacroName The name of the macro. @@ -144,190 +178,230 @@ unsigned getMacroUsagePriority(StringRef MacroName, const LangOptions &LangOpts, bool PreferredTypeIsPointer = false); -/// \brief Determine the libclang cursor kind associated with the given +/// Determine the libclang cursor kind associated with the given /// declaration. CXCursorKind getCursorKindForDecl(const Decl *D); -class FunctionDecl; -class FunctionType; -class FunctionTemplateDecl; -class IdentifierInfo; -class NamedDecl; -class NestedNameSpecifier; -class Sema; - -/// \brief The context in which code completion occurred, so that the +/// The context in which code completion occurred, so that the /// code-completion consumer can process the results accordingly. class CodeCompletionContext { public: enum Kind { - /// \brief An unspecified code-completion context. + /// An unspecified code-completion context. CCC_Other, - /// \brief An unspecified code-completion context where we should also add + + /// An unspecified code-completion context where we should also add /// macro completions. CCC_OtherWithMacros, - /// \brief Code completion occurred within a "top-level" completion context, + + /// Code completion occurred within a "top-level" completion context, /// e.g., at namespace or global scope. CCC_TopLevel, - /// \brief Code completion occurred within an Objective-C interface, + + /// Code completion occurred within an Objective-C interface, /// protocol, or category interface. CCC_ObjCInterface, - /// \brief Code completion occurred within an Objective-C implementation + + /// Code completion occurred within an Objective-C implementation /// or category implementation. CCC_ObjCImplementation, - /// \brief Code completion occurred within the instance variable list of + + /// Code completion occurred within the instance variable list of /// an Objective-C interface, implementation, or category implementation. CCC_ObjCIvarList, - /// \brief Code completion occurred within a class, struct, or union. + + /// Code completion occurred within a class, struct, or union. CCC_ClassStructUnion, - /// \brief Code completion occurred where a statement (or declaration) is + + /// Code completion occurred where a statement (or declaration) is /// expected in a function, method, or block. CCC_Statement, - /// \brief Code completion occurred where an expression is expected. + + /// Code completion occurred where an expression is expected. CCC_Expression, - /// \brief Code completion occurred where an Objective-C message receiver + + /// Code completion occurred where an Objective-C message receiver /// is expected. CCC_ObjCMessageReceiver, - /// \brief Code completion occurred on the right-hand side of a member + + /// Code completion occurred on the right-hand side of a member /// access expression using the dot operator. /// /// The results of this completion are the members of the type being /// accessed. The type itself is available via /// \c CodeCompletionContext::getType(). CCC_DotMemberAccess, - /// \brief Code completion occurred on the right-hand side of a member + + /// Code completion occurred on the right-hand side of a member /// access expression using the arrow operator. /// /// The results of this completion are the members of the type being /// accessed. The type itself is available via /// \c CodeCompletionContext::getType(). CCC_ArrowMemberAccess, - /// \brief Code completion occurred on the right-hand side of an Objective-C + + /// Code completion occurred on the right-hand side of an Objective-C /// property access expression. /// /// The results of this completion are the members of the type being /// accessed. The type itself is available via /// \c CodeCompletionContext::getType(). CCC_ObjCPropertyAccess, - /// \brief Code completion occurred after the "enum" keyword, to indicate + + /// Code completion occurred after the "enum" keyword, to indicate /// an enumeration name. CCC_EnumTag, - /// \brief Code completion occurred after the "union" keyword, to indicate + + /// Code completion occurred after the "union" keyword, to indicate /// a union name. CCC_UnionTag, - /// \brief Code completion occurred after the "struct" or "class" keyword, + + /// Code completion occurred after the "struct" or "class" keyword, /// to indicate a struct or class name. CCC_ClassOrStructTag, - /// \brief Code completion occurred where a protocol name is expected. + + /// Code completion occurred where a protocol name is expected. CCC_ObjCProtocolName, - /// \brief Code completion occurred where a namespace or namespace alias + + /// Code completion occurred where a namespace or namespace alias /// is expected. CCC_Namespace, - /// \brief Code completion occurred where a type name is expected. + + /// Code completion occurred where a type name is expected. CCC_Type, - /// \brief Code completion occurred where a new name is expected. + + /// Code completion occurred where a new name is expected. CCC_Name, - /// \brief Code completion occurred where a new name is expected and a + + /// Code completion occurred where a new name is expected and a /// qualified name is permissible. CCC_PotentiallyQualifiedName, - /// \brief Code completion occurred where an macro is being defined. + + /// Code completion occurred where an macro is being defined. CCC_MacroName, - /// \brief Code completion occurred where a macro name is expected + + /// Code completion occurred where a macro name is expected /// (without any arguments, in the case of a function-like macro). CCC_MacroNameUse, - /// \brief Code completion occurred within a preprocessor expression. + + /// Code completion occurred within a preprocessor expression. CCC_PreprocessorExpression, - /// \brief Code completion occurred where a preprocessor directive is + + /// Code completion occurred where a preprocessor directive is /// expected. CCC_PreprocessorDirective, - /// \brief Code completion occurred in a context where natural language is + + /// Code completion occurred in a context where natural language is /// expected, e.g., a comment or string literal. /// /// This context usually implies that no completions should be added, /// unless they come from an appropriate natural-language dictionary. CCC_NaturalLanguage, - /// \brief Code completion for a selector, as in an \@selector expression. + + /// Code completion for a selector, as in an \@selector expression. CCC_SelectorName, - /// \brief Code completion within a type-qualifier list. + + /// Code completion within a type-qualifier list. CCC_TypeQualifiers, - /// \brief Code completion in a parenthesized expression, which means that + + /// Code completion in a parenthesized expression, which means that /// we may also have types here in C and Objective-C (as well as in C++). CCC_ParenthesizedExpression, - /// \brief Code completion where an Objective-C instance message is + + /// Code completion where an Objective-C instance message is /// expected. CCC_ObjCInstanceMessage, - /// \brief Code completion where an Objective-C class message is expected. + + /// Code completion where an Objective-C class message is expected. CCC_ObjCClassMessage, - /// \brief Code completion where the name of an Objective-C class is + + /// Code completion where the name of an Objective-C class is /// expected. CCC_ObjCInterfaceName, - /// \brief Code completion where an Objective-C category name is expected. + + /// Code completion where an Objective-C category name is expected. CCC_ObjCCategoryName, - /// \brief An unknown context, in which we are recovering from a parsing + + /// An unknown context, in which we are recovering from a parsing /// error and don't know which completions we should give. CCC_Recovery }; + using VisitedContextSet = llvm::SmallPtrSet<DeclContext *, 8>; + private: - enum Kind Kind; + Kind CCKind; - /// \brief The type that would prefer to see at this point (e.g., the type + /// The type that would prefer to see at this point (e.g., the type /// of an initializer or function parameter). QualType PreferredType; - /// \brief The type of the base object in a member access expression. + /// The type of the base object in a member access expression. QualType BaseType; - /// \brief The identifiers for Objective-C selector parts. + /// The identifiers for Objective-C selector parts. ArrayRef<IdentifierInfo *> SelIdents; - /// \brief The scope specifier that comes before the completion token e.g. + /// The scope specifier that comes before the completion token e.g. /// "a::b::" llvm::Optional<CXXScopeSpec> ScopeSpecifier; + /// A set of declaration contexts visited by Sema when doing lookup for + /// code completion. + VisitedContextSet VisitedContexts; + public: - /// \brief Construct a new code-completion context of the given kind. - CodeCompletionContext(enum Kind Kind) : Kind(Kind), SelIdents(None) { } + /// Construct a new code-completion context of the given kind. + CodeCompletionContext(Kind CCKind) : CCKind(CCKind), SelIdents(None) {} - /// \brief Construct a new code-completion context of the given kind. - CodeCompletionContext(enum Kind Kind, QualType T, + /// Construct a new code-completion context of the given kind. + CodeCompletionContext(Kind CCKind, QualType T, ArrayRef<IdentifierInfo *> SelIdents = None) - : Kind(Kind), - SelIdents(SelIdents) { - if (Kind == CCC_DotMemberAccess || Kind == CCC_ArrowMemberAccess || - Kind == CCC_ObjCPropertyAccess || Kind == CCC_ObjCClassMessage || - Kind == CCC_ObjCInstanceMessage) + : CCKind(CCKind), SelIdents(SelIdents) { + if (CCKind == CCC_DotMemberAccess || CCKind == CCC_ArrowMemberAccess || + CCKind == CCC_ObjCPropertyAccess || CCKind == CCC_ObjCClassMessage || + CCKind == CCC_ObjCInstanceMessage) BaseType = T; else PreferredType = T; } - /// \brief Retrieve the kind of code-completion context. - enum Kind getKind() const { return Kind; } + /// Retrieve the kind of code-completion context. + Kind getKind() const { return CCKind; } - /// \brief Retrieve the type that this expression would prefer to have, e.g., + /// Retrieve the type that this expression would prefer to have, e.g., /// if the expression is a variable initializer or a function argument, the /// type of the corresponding variable or function parameter. QualType getPreferredType() const { return PreferredType; } - /// \brief Retrieve the type of the base object in a member-access + /// Retrieve the type of the base object in a member-access /// expression. QualType getBaseType() const { return BaseType; } - /// \brief Retrieve the Objective-C selector identifiers. + /// Retrieve the Objective-C selector identifiers. ArrayRef<IdentifierInfo *> getSelIdents() const { return SelIdents; } - /// \brief Determines whether we want C++ constructors as results within this + /// Determines whether we want C++ constructors as results within this /// context. bool wantConstructorResults() const; - /// \brief Sets the scope specifier that comes before the completion token. + /// Sets the scope specifier that comes before the completion token. /// This is expected to be set in code completions on qualfied specifiers /// (e.g. "a::b::"). void setCXXScopeSpecifier(CXXScopeSpec SS) { this->ScopeSpecifier = std::move(SS); } + /// Adds a visited context. + void addVisitedContext(DeclContext *Ctx) { + VisitedContexts.insert(Ctx); + } + + /// Retrieves all visited contexts. + const VisitedContextSet &getVisitedContexts() const { + return VisitedContexts; + } + llvm::Optional<const CXXScopeSpec *> getCXXScopeSpecifier() { if (ScopeSpecifier) return ScopeSpecifier.getPointer(); @@ -335,7 +409,10 @@ public: } }; -/// \brief A "string" used to describe how code completion can +/// Get string representation of \p Kind, useful for for debugging. +llvm::StringRef getCompletionKindString(CodeCompletionContext::Kind Kind); + +/// A "string" used to describe how code completion can /// be performed for an entity. /// /// A code completion string typically shows how a particular entity can be @@ -344,128 +421,147 @@ public: /// arguments, etc. class CodeCompletionString { public: - /// \brief The different kinds of "chunks" that can occur within a code + /// The different kinds of "chunks" that can occur within a code /// completion string. enum ChunkKind { - /// \brief The piece of text that the user is expected to type to + /// The piece of text that the user is expected to type to /// match the code-completion string, typically a keyword or the name of a /// declarator or macro. CK_TypedText, - /// \brief A piece of text that should be placed in the buffer, e.g., + + /// A piece of text that should be placed in the buffer, e.g., /// parentheses or a comma in a function call. CK_Text, - /// \brief A code completion string that is entirely optional. For example, + + /// A code completion string that is entirely optional. For example, /// an optional code completion string that describes the default arguments /// in a function call. CK_Optional, - /// \brief A string that acts as a placeholder for, e.g., a function + + /// A string that acts as a placeholder for, e.g., a function /// call argument. CK_Placeholder, - /// \brief A piece of text that describes something about the result but + + /// A piece of text that describes something about the result but /// should not be inserted into the buffer. CK_Informative, - /// \brief A piece of text that describes the type of an entity or, for + /// A piece of text that describes the type of an entity or, for /// functions and methods, the return type. CK_ResultType, - /// \brief A piece of text that describes the parameter that corresponds + + /// A piece of text that describes the parameter that corresponds /// to the code-completion location within a function call, message send, /// macro invocation, etc. CK_CurrentParameter, - /// \brief A left parenthesis ('('). + + /// A left parenthesis ('('). CK_LeftParen, - /// \brief A right parenthesis (')'). + + /// A right parenthesis (')'). CK_RightParen, - /// \brief A left bracket ('['). + + /// A left bracket ('['). CK_LeftBracket, - /// \brief A right bracket (']'). + + /// A right bracket (']'). CK_RightBracket, - /// \brief A left brace ('{'). + + /// A left brace ('{'). CK_LeftBrace, - /// \brief A right brace ('}'). + + /// A right brace ('}'). CK_RightBrace, - /// \brief A left angle bracket ('<'). + + /// A left angle bracket ('<'). CK_LeftAngle, - /// \brief A right angle bracket ('>'). + + /// A right angle bracket ('>'). CK_RightAngle, - /// \brief A comma separator (','). + + /// A comma separator (','). CK_Comma, - /// \brief A colon (':'). + + /// A colon (':'). CK_Colon, - /// \brief A semicolon (';'). + + /// A semicolon (';'). CK_SemiColon, - /// \brief An '=' sign. + + /// An '=' sign. CK_Equal, - /// \brief Horizontal whitespace (' '). + + /// Horizontal whitespace (' '). CK_HorizontalSpace, - /// \brief Vertical whitespace ('\\n' or '\\r\\n', depending on the + + /// Vertical whitespace ('\\n' or '\\r\\n', depending on the /// platform). CK_VerticalSpace }; - /// \brief One piece of the code completion string. + /// One piece of the code completion string. struct Chunk { - /// \brief The kind of data stored in this piece of the code completion + /// The kind of data stored in this piece of the code completion /// string. - ChunkKind Kind; + ChunkKind Kind = CK_Text; union { - /// \brief The text string associated with a CK_Text, CK_Placeholder, + /// The text string associated with a CK_Text, CK_Placeholder, /// CK_Informative, or CK_Comma chunk. /// The string is owned by the chunk and will be deallocated /// (with delete[]) when the chunk is destroyed. const char *Text; - /// \brief The code completion string associated with a CK_Optional chunk. + /// The code completion string associated with a CK_Optional chunk. /// The optional code completion string is owned by the chunk, and will /// be deallocated (with delete) when the chunk is destroyed. CodeCompletionString *Optional; }; - Chunk() : Kind(CK_Text), Text(nullptr) { } + Chunk() : Text(nullptr) {} explicit Chunk(ChunkKind Kind, const char *Text = ""); - /// \brief Create a new text chunk. + /// Create a new text chunk. static Chunk CreateText(const char *Text); - /// \brief Create a new optional chunk. + /// Create a new optional chunk. static Chunk CreateOptional(CodeCompletionString *Optional); - /// \brief Create a new placeholder chunk. + /// Create a new placeholder chunk. static Chunk CreatePlaceholder(const char *Placeholder); - /// \brief Create a new informative chunk. + /// Create a new informative chunk. static Chunk CreateInformative(const char *Informative); - /// \brief Create a new result type chunk. + /// Create a new result type chunk. static Chunk CreateResultType(const char *ResultType); - /// \brief Create a new current-parameter chunk. + /// Create a new current-parameter chunk. static Chunk CreateCurrentParameter(const char *CurrentParameter); }; private: - /// \brief The number of chunks stored in this string. + friend class CodeCompletionBuilder; + friend class CodeCompletionResult; + + /// The number of chunks stored in this string. unsigned NumChunks : 16; - /// \brief The number of annotations for this code-completion result. + /// The number of annotations for this code-completion result. unsigned NumAnnotations : 16; - /// \brief The priority of this code-completion string. + /// The priority of this code-completion string. unsigned Priority : 16; - /// \brief The availability of this code-completion result. + /// The availability of this code-completion result. unsigned Availability : 2; - - /// \brief The name of the parent context. + + /// The name of the parent context. StringRef ParentName; - /// \brief A brief documentation comment attached to the declaration of + /// A brief documentation comment attached to the declaration of /// entity being completed by this result. const char *BriefComment; - - CodeCompletionString(const CodeCompletionString &) = delete; - void operator=(const CodeCompletionString &) = delete; CodeCompletionString(const Chunk *Chunks, unsigned NumChunks, unsigned Priority, CXAvailabilityKind Availability, @@ -474,11 +570,12 @@ private: const char *BriefComment); ~CodeCompletionString() = default; - friend class CodeCompletionBuilder; - friend class CodeCompletionResult; - public: - typedef const Chunk *iterator; + CodeCompletionString(const CodeCompletionString &) = delete; + CodeCompletionString &operator=(const CodeCompletionString &) = delete; + + using iterator = const Chunk *; + iterator begin() const { return reinterpret_cast<const Chunk *>(this + 1); } iterator end() const { return begin() + NumChunks; } bool empty() const { return NumChunks == 0; } @@ -489,22 +586,22 @@ public: return begin()[I]; } - /// \brief Returns the text in the TypedText chunk. + /// Returns the text in the TypedText chunk. const char *getTypedText() const; - /// \brief Retrieve the priority of this code completion result. + /// Retrieve the priority of this code completion result. unsigned getPriority() const { return Priority; } - /// \brief Retrieve the availability of this code completion result. + /// Retrieve the availability of this code completion result. unsigned getAvailability() const { return Availability; } - /// \brief Retrieve the number of annotations for this code completion result. + /// Retrieve the number of annotations for this code completion result. unsigned getAnnotationCount() const; - /// \brief Retrieve the annotation string specified by \c AnnotationNr. + /// Retrieve the annotation string specified by \c AnnotationNr. const char *getAnnotation(unsigned AnnotationNr) const; - - /// \brief Retrieve the name of the parent context. + + /// Retrieve the name of the parent context. StringRef getParentContextName() const { return ParentName; } @@ -512,20 +609,20 @@ public: const char *getBriefComment() const { return BriefComment; } - - /// \brief Retrieve a string representation of the code completion string, + + /// Retrieve a string representation of the code completion string, /// which is mainly useful for debugging. std::string getAsString() const; }; -/// \brief An allocator used specifically for the purpose of code completion. +/// An allocator used specifically for the purpose of code completion. class CodeCompletionAllocator : public llvm::BumpPtrAllocator { public: - /// \brief Copy the given string into this allocator. + /// Copy the given string into this allocator. const char *CopyString(const Twine &String); }; -/// \brief Allocator for a cached set of global code completions. +/// Allocator for a cached set of global code completions. class GlobalCodeCompletionAllocator : public CodeCompletionAllocator {}; class CodeCompletionTUInfo { @@ -540,6 +637,7 @@ public: std::shared_ptr<GlobalCodeCompletionAllocator> getAllocatorRef() const { return AllocatorRef; } + CodeCompletionAllocator &getAllocator() const { assert(AllocatorRef); return *AllocatorRef; @@ -548,30 +646,32 @@ public: StringRef getParentName(const DeclContext *DC); }; -} // end namespace clang +} // namespace clang namespace llvm { - template <> struct isPodLike<clang::CodeCompletionString::Chunk> { - static const bool value = true; - }; -} + +template <> struct isPodLike<clang::CodeCompletionString::Chunk> { + static const bool value = true; +}; + +} // namespace llvm namespace clang { -/// \brief A builder class used to construct new code-completion strings. +/// A builder class used to construct new code-completion strings. class CodeCompletionBuilder { public: - typedef CodeCompletionString::Chunk Chunk; + using Chunk = CodeCompletionString::Chunk; private: CodeCompletionAllocator &Allocator; CodeCompletionTUInfo &CCTUInfo; - unsigned Priority; - CXAvailabilityKind Availability; + unsigned Priority = 0; + CXAvailabilityKind Availability = CXAvailability_Available; StringRef ParentName; - const char *BriefComment; - - /// \brief The chunks stored in this string. + const char *BriefComment = nullptr; + + /// The chunks stored in this string. SmallVector<Chunk, 4> Chunks; SmallVector<const char *, 2> Annotations; @@ -579,203 +679,237 @@ private: public: CodeCompletionBuilder(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo) - : Allocator(Allocator), CCTUInfo(CCTUInfo), - Priority(0), Availability(CXAvailability_Available), - BriefComment(nullptr) { } + : Allocator(Allocator), CCTUInfo(CCTUInfo) {} CodeCompletionBuilder(CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, unsigned Priority, CXAvailabilityKind Availability) - : Allocator(Allocator), CCTUInfo(CCTUInfo), - Priority(Priority), Availability(Availability), - BriefComment(nullptr) { } + : Allocator(Allocator), CCTUInfo(CCTUInfo), Priority(Priority), + Availability(Availability) {} - /// \brief Retrieve the allocator into which the code completion + /// Retrieve the allocator into which the code completion /// strings should be allocated. CodeCompletionAllocator &getAllocator() const { return Allocator; } CodeCompletionTUInfo &getCodeCompletionTUInfo() const { return CCTUInfo; } - /// \brief Take the resulting completion string. + /// Take the resulting completion string. /// /// This operation can only be performed once. CodeCompletionString *TakeString(); - /// \brief Add a new typed-text chunk. + /// Add a new typed-text chunk. void AddTypedTextChunk(const char *Text); - /// \brief Add a new text chunk. + /// Add a new text chunk. void AddTextChunk(const char *Text); - /// \brief Add a new optional chunk. + /// Add a new optional chunk. void AddOptionalChunk(CodeCompletionString *Optional); - /// \brief Add a new placeholder chunk. + /// Add a new placeholder chunk. void AddPlaceholderChunk(const char *Placeholder); - /// \brief Add a new informative chunk. + /// Add a new informative chunk. void AddInformativeChunk(const char *Text); - /// \brief Add a new result-type chunk. + /// Add a new result-type chunk. void AddResultTypeChunk(const char *ResultType); - /// \brief Add a new current-parameter chunk. + /// Add a new current-parameter chunk. void AddCurrentParameterChunk(const char *CurrentParameter); - /// \brief Add a new chunk. + /// Add a new chunk. void AddChunk(CodeCompletionString::ChunkKind CK, const char *Text = ""); void AddAnnotation(const char *A) { Annotations.push_back(A); } - /// \brief Add the parent context information to this code completion. + /// Add the parent context information to this code completion. void addParentContext(const DeclContext *DC); const char *getBriefComment() const { return BriefComment; } void addBriefComment(StringRef Comment); - + StringRef getParentName() const { return ParentName; } }; -/// \brief Captures a result of code completion. +/// Captures a result of code completion. class CodeCompletionResult { public: - /// \brief Describes the kind of result generated. + /// Describes the kind of result generated. enum ResultKind { - RK_Declaration = 0, ///< Refers to a declaration - RK_Keyword, ///< Refers to a keyword or symbol. - RK_Macro, ///< Refers to a macro - RK_Pattern ///< Refers to a precomputed pattern. + /// Refers to a declaration. + RK_Declaration = 0, + + /// Refers to a keyword or symbol. + RK_Keyword, + + /// Refers to a macro. + RK_Macro, + + /// Refers to a precomputed pattern. + RK_Pattern }; - /// \brief When Kind == RK_Declaration or RK_Pattern, the declaration we are + /// When Kind == RK_Declaration or RK_Pattern, the declaration we are /// referring to. In the latter case, the declaration might be NULL. - const NamedDecl *Declaration; + const NamedDecl *Declaration = nullptr; union { - /// \brief When Kind == RK_Keyword, the string representing the keyword + /// When Kind == RK_Keyword, the string representing the keyword /// or symbol's spelling. const char *Keyword; - /// \brief When Kind == RK_Pattern, the code-completion string that + /// When Kind == RK_Pattern, the code-completion string that /// describes the completion text to insert. CodeCompletionString *Pattern; - /// \brief When Kind == RK_Macro, the identifier that refers to a macro. + /// When Kind == RK_Macro, the identifier that refers to a macro. const IdentifierInfo *Macro; }; - /// \brief The priority of this particular code-completion result. + /// The priority of this particular code-completion result. unsigned Priority; - /// \brief Specifies which parameter (of a function, Objective-C method, + /// Specifies which parameter (of a function, Objective-C method, /// macro, etc.) we should start with when formatting the result. - unsigned StartParameter; + unsigned StartParameter = 0; - /// \brief The kind of result stored here. + /// The kind of result stored here. ResultKind Kind; - /// \brief The cursor kind that describes this result. + /// The cursor kind that describes this result. CXCursorKind CursorKind; - /// \brief The availability of this result. - CXAvailabilityKind Availability; + /// The availability of this result. + CXAvailabilityKind Availability = CXAvailability_Available; - /// \brief Whether this result is hidden by another name. + /// Fix-its that *must* be applied before inserting the text for the + /// corresponding completion. + /// + /// By default, CodeCompletionBuilder only returns completions with empty + /// fix-its. Extra completions with non-empty fix-its should be explicitly + /// requested by setting CompletionOptions::IncludeFixIts. + /// + /// For the clients to be able to compute position of the cursor after + /// applying fix-its, the following conditions are guaranteed to hold for + /// RemoveRange of the stored fix-its: + /// - Ranges in the fix-its are guaranteed to never contain the completion + /// point (or identifier under completion point, if any) inside them, except + /// at the start or at the end of the range. + /// - If a fix-it range starts or ends with completion point (or starts or + /// ends after the identifier under completion point), it will contain at + /// least one character. It allows to unambiguously recompute completion + /// point after applying the fix-it. + /// + /// The intuition is that provided fix-its change code around the identifier + /// we complete, but are not allowed to touch the identifier itself or the + /// completion point. One example of completions with corrections are the ones + /// replacing '.' with '->' and vice versa: + /// + /// std::unique_ptr<std::vector<int>> vec_ptr; + /// In 'vec_ptr.^', one of the completions is 'push_back', it requires + /// replacing '.' with '->'. + /// In 'vec_ptr->^', one of the completions is 'release', it requires + /// replacing '->' with '.'. + std::vector<FixItHint> FixIts; + + /// Whether this result is hidden by another name. bool Hidden : 1; - /// \brief Whether this result was found via lookup into a base class. + /// Whether this result was found via lookup into a base class. bool QualifierIsInformative : 1; - /// \brief Whether this declaration is the beginning of a + /// Whether this declaration is the beginning of a /// nested-name-specifier and, therefore, should be followed by '::'. bool StartsNestedNameSpecifier : 1; - /// \brief Whether all parameters (of a function, Objective-C + /// Whether all parameters (of a function, Objective-C /// method, etc.) should be considered "informative". bool AllParametersAreInformative : 1; - /// \brief Whether we're completing a declaration of the given entity, + /// Whether we're completing a declaration of the given entity, /// rather than a use of that entity. bool DeclaringEntity : 1; - /// \brief If the result should have a nested-name-specifier, this is it. + /// If the result should have a nested-name-specifier, this is it. /// When \c QualifierIsInformative, the nested-name-specifier is /// informative rather than required. - NestedNameSpecifier *Qualifier; + NestedNameSpecifier *Qualifier = nullptr; - /// \brief Build a result that refers to a declaration. - CodeCompletionResult(const NamedDecl *Declaration, - unsigned Priority, + /// If this Decl was unshadowed by using declaration, this can store a + /// pointer to the UsingShadowDecl which was used in the unshadowing process. + /// This information can be used to uprank CodeCompletionResults / which have + /// corresponding `using decl::qualified::name;` nearby. + const UsingShadowDecl *ShadowDecl = nullptr; + + /// Build a result that refers to a declaration. + CodeCompletionResult(const NamedDecl *Declaration, unsigned Priority, NestedNameSpecifier *Qualifier = nullptr, bool QualifierIsInformative = false, - bool Accessible = true) - : Declaration(Declaration), Priority(Priority), - StartParameter(0), Kind(RK_Declaration), - Availability(CXAvailability_Available), Hidden(false), - QualifierIsInformative(QualifierIsInformative), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(Qualifier) { + bool Accessible = true, + std::vector<FixItHint> FixIts = std::vector<FixItHint>()) + : Declaration(Declaration), Priority(Priority), Kind(RK_Declaration), + FixIts(std::move(FixIts)), Hidden(false), + QualifierIsInformative(QualifierIsInformative), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false), Qualifier(Qualifier) { + // FIXME: Add assert to check FixIts range requirements. computeCursorKindAndAvailability(Accessible); } - /// \brief Build a result that refers to a keyword or symbol. + /// Build a result that refers to a keyword or symbol. CodeCompletionResult(const char *Keyword, unsigned Priority = CCP_Keyword) - : Declaration(nullptr), Keyword(Keyword), Priority(Priority), - StartParameter(0), Kind(RK_Keyword), CursorKind(CXCursor_NotImplemented), - Availability(CXAvailability_Available), Hidden(false), - QualifierIsInformative(0), StartsNestedNameSpecifier(false), - AllParametersAreInformative(false), DeclaringEntity(false), - Qualifier(nullptr) {} - - /// \brief Build a result that refers to a macro. + : Keyword(Keyword), Priority(Priority), Kind(RK_Keyword), + CursorKind(CXCursor_NotImplemented), Hidden(false), + QualifierIsInformative(false), StartsNestedNameSpecifier(false), + AllParametersAreInformative(false), DeclaringEntity(false) {} + + /// Build a result that refers to a macro. CodeCompletionResult(const IdentifierInfo *Macro, unsigned Priority = CCP_Macro) - : Declaration(nullptr), Macro(Macro), Priority(Priority), StartParameter(0), - Kind(RK_Macro), CursorKind(CXCursor_MacroDefinition), - Availability(CXAvailability_Available), Hidden(false), - QualifierIsInformative(0), StartsNestedNameSpecifier(false), - AllParametersAreInformative(false), DeclaringEntity(false), - Qualifier(nullptr) {} - - /// \brief Build a result that refers to a pattern. + : Macro(Macro), Priority(Priority), Kind(RK_Macro), + CursorKind(CXCursor_MacroDefinition), Hidden(false), + QualifierIsInformative(false), StartsNestedNameSpecifier(false), + AllParametersAreInformative(false), DeclaringEntity(false) {} + + /// Build a result that refers to a pattern. CodeCompletionResult(CodeCompletionString *Pattern, unsigned Priority = CCP_CodePattern, CXCursorKind CursorKind = CXCursor_NotImplemented, CXAvailabilityKind Availability = CXAvailability_Available, const NamedDecl *D = nullptr) - : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0), - Kind(RK_Pattern), CursorKind(CursorKind), Availability(Availability), - Hidden(false), QualifierIsInformative(0), - StartsNestedNameSpecifier(false), AllParametersAreInformative(false), - DeclaringEntity(false), Qualifier(nullptr) - { - } + : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern), + CursorKind(CursorKind), Availability(Availability), Hidden(false), + QualifierIsInformative(false), StartsNestedNameSpecifier(false), + AllParametersAreInformative(false), DeclaringEntity(false) {} - /// \brief Build a result that refers to a pattern with an associated + /// Build a result that refers to a pattern with an associated /// declaration. CodeCompletionResult(CodeCompletionString *Pattern, const NamedDecl *D, unsigned Priority) - : Declaration(D), Pattern(Pattern), Priority(Priority), StartParameter(0), - Kind(RK_Pattern), Availability(CXAvailability_Available), Hidden(false), - QualifierIsInformative(false), StartsNestedNameSpecifier(false), - AllParametersAreInformative(false), DeclaringEntity(false), - Qualifier(nullptr) { + : Declaration(D), Pattern(Pattern), Priority(Priority), Kind(RK_Pattern), + Hidden(false), QualifierIsInformative(false), + StartsNestedNameSpecifier(false), AllParametersAreInformative(false), + DeclaringEntity(false) { computeCursorKindAndAvailability(); - } - - /// \brief Retrieve the declaration stored in this result. + } + + /// Retrieve the declaration stored in this result. This might be nullptr if + /// Kind is RK_Pattern. const NamedDecl *getDeclaration() const { - assert(Kind == RK_Declaration && "Not a declaration result"); + assert(((Kind == RK_Declaration) || (Kind == RK_Pattern)) && + "Not a declaration or pattern result"); return Declaration; } - /// \brief Retrieve the keyword stored in this result. + /// Retrieve the keyword stored in this result. const char *getKeyword() const { assert(Kind == RK_Keyword && "Not a keyword result"); return Keyword; } - /// \brief Create a new code-completion string that describes how to insert + /// Create a new code-completion string that describes how to insert /// this result into a program. /// /// \param S The semantic analysis that created the result. @@ -793,8 +927,15 @@ public: CodeCompletionAllocator &Allocator, CodeCompletionTUInfo &CCTUInfo, bool IncludeBriefComments); - - /// \brief Retrieve the name that should be used to order a result. + /// Creates a new code-completion string for the macro result. Similar to the + /// above overloads, except this only requires preprocessor information. + /// The result kind must be `RK_Macro`. + CodeCompletionString * + CreateCodeCompletionStringForMacro(Preprocessor &PP, + CodeCompletionAllocator &Allocator, + CodeCompletionTUInfo &CCTUInfo); + + /// Retrieve the name that should be used to order a result. /// /// If the name needs to be constructed as a string, that string will be /// saved into Saved and the returned StringRef will refer to it. @@ -821,80 +962,81 @@ inline bool operator>=(const CodeCompletionResult &X, return !(X < Y); } - raw_ostream &operator<<(raw_ostream &OS, const CodeCompletionString &CCS); -/// \brief Abstract interface for a consumer of code-completion +/// Abstract interface for a consumer of code-completion /// information. class CodeCompleteConsumer { protected: const CodeCompleteOptions CodeCompleteOpts; - /// \brief Whether the output format for the code-completion consumer is + /// Whether the output format for the code-completion consumer is /// binary. bool OutputIsBinary; public: class OverloadCandidate { public: - /// \brief Describes the type of overload candidate. + /// Describes the type of overload candidate. enum CandidateKind { - /// \brief The candidate is a function declaration. + /// The candidate is a function declaration. CK_Function, - /// \brief The candidate is a function template. + + /// The candidate is a function template. CK_FunctionTemplate, - /// \brief The "candidate" is actually a variable, expression, or block + + /// The "candidate" is actually a variable, expression, or block /// for which we only have a function prototype. CK_FunctionType }; private: - /// \brief The kind of overload candidate. + /// The kind of overload candidate. CandidateKind Kind; union { - /// \brief The function overload candidate, available when + /// The function overload candidate, available when /// Kind == CK_Function. FunctionDecl *Function; - /// \brief The function template overload candidate, available when + /// The function template overload candidate, available when /// Kind == CK_FunctionTemplate. FunctionTemplateDecl *FunctionTemplate; - /// \brief The function type that describes the entity being called, + /// The function type that describes the entity being called, /// when Kind == CK_FunctionType. const FunctionType *Type; }; public: OverloadCandidate(FunctionDecl *Function) - : Kind(CK_Function), Function(Function) { } + : Kind(CK_Function), Function(Function) {} OverloadCandidate(FunctionTemplateDecl *FunctionTemplateDecl) - : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) { } + : Kind(CK_FunctionTemplate), FunctionTemplate(FunctionTemplateDecl) {} OverloadCandidate(const FunctionType *Type) - : Kind(CK_FunctionType), Type(Type) { } + : Kind(CK_FunctionType), Type(Type) {} - /// \brief Determine the kind of overload candidate. + /// Determine the kind of overload candidate. CandidateKind getKind() const { return Kind; } - /// \brief Retrieve the function overload candidate or the templated + /// Retrieve the function overload candidate or the templated /// function declaration for a function template. FunctionDecl *getFunction() const; - /// \brief Retrieve the function template overload candidate. + /// Retrieve the function template overload candidate. FunctionTemplateDecl *getFunctionTemplate() const { assert(getKind() == CK_FunctionTemplate && "Not a function template"); return FunctionTemplate; } - /// \brief Retrieve the function type of the entity, regardless of how the + /// Retrieve the function type of the entity, regardless of how the /// function is stored. const FunctionType *getFunctionType() const; - /// \brief Create a new code-completion string that describes the function + /// Create a new code-completion string that describes the function /// signature of this overload candidate. CodeCompletionString *CreateSignatureString(unsigned CurrentArg, Sema &S, @@ -905,43 +1047,52 @@ public: CodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts, bool OutputIsBinary) - : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary) - { } + : CodeCompleteOpts(CodeCompleteOpts), OutputIsBinary(OutputIsBinary) {} - /// \brief Whether the code-completion consumer wants to see macros. + /// Whether the code-completion consumer wants to see macros. bool includeMacros() const { return CodeCompleteOpts.IncludeMacros; } - /// \brief Whether the code-completion consumer wants to see code patterns. + /// Whether the code-completion consumer wants to see code patterns. bool includeCodePatterns() const { return CodeCompleteOpts.IncludeCodePatterns; } - /// \brief Whether to include global (top-level) declaration results. + /// Whether to include global (top-level) declaration results. bool includeGlobals() const { return CodeCompleteOpts.IncludeGlobals; } - /// \brief Whether to include declarations in namespace contexts (including + /// Whether to include declarations in namespace contexts (including /// the global namespace). If this is false, `includeGlobals()` will be /// ignored. bool includeNamespaceLevelDecls() const { return CodeCompleteOpts.IncludeNamespaceLevelDecls; } - /// \brief Whether to include brief documentation comments within the set of + /// Whether to include brief documentation comments within the set of /// code completions returned. bool includeBriefComments() const { return CodeCompleteOpts.IncludeBriefComments; } - /// \brief Determine whether the output of this consumer is binary. + /// Whether to include completion items with small fix-its, e.g. change + /// '.' to '->' on member access, etc. + bool includeFixIts() const { return CodeCompleteOpts.IncludeFixIts; } + + /// Hint whether to load data from the external AST in order to provide + /// full results. If false, declarations from the preamble may be omitted. + bool loadExternal() const { + return CodeCompleteOpts.LoadExternal; + } + + /// Determine whether the output of this consumer is binary. bool isOutputBinary() const { return OutputIsBinary; } - /// \brief Deregisters and destroys this code-completion consumer. + /// Deregisters and destroys this code-completion consumer. virtual ~CodeCompleteConsumer(); /// \name Code-completion filtering - /// \brief Check if the result should be filtered out. + /// Check if the result should be filtered out. virtual bool isResultFilteredOut(StringRef Filter, CodeCompletionResult Results) { return false; @@ -949,11 +1100,11 @@ public: /// \name Code-completion callbacks //@{ - /// \brief Process the finalized code-completion results. + /// Process the finalized code-completion results. virtual void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, CodeCompletionResult *Results, - unsigned NumResults) { } + unsigned NumResults) {} /// \param S the semantic-analyzer object for which code-completion is being /// done. @@ -965,33 +1116,50 @@ public: /// \param NumCandidates the number of overload candidates virtual void ProcessOverloadCandidates(Sema &S, unsigned CurrentArg, OverloadCandidate *Candidates, - unsigned NumCandidates) { } + unsigned NumCandidates) {} //@} - /// \brief Retrieve the allocator that will be used to allocate + /// Retrieve the allocator that will be used to allocate /// code completion strings. virtual CodeCompletionAllocator &getAllocator() = 0; virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() = 0; }; -/// \brief A simple code-completion consumer that prints the results it +/// Get the documentation comment used to produce +/// CodeCompletionString::BriefComment for RK_Declaration. +const RawComment *getCompletionComment(const ASTContext &Ctx, + const NamedDecl *Decl); + +/// Get the documentation comment used to produce +/// CodeCompletionString::BriefComment for RK_Pattern. +const RawComment *getPatternCompletionComment(const ASTContext &Ctx, + const NamedDecl *Decl); + +/// Get the documentation comment used to produce +/// CodeCompletionString::BriefComment for OverloadCandidate. +const RawComment * +getParameterComment(const ASTContext &Ctx, + const CodeCompleteConsumer::OverloadCandidate &Result, + unsigned ArgIndex); + +/// A simple code-completion consumer that prints the results it /// receives in a simple format. class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { - /// \brief The raw output stream. + /// The raw output stream. raw_ostream &OS; CodeCompletionTUInfo CCTUInfo; public: - /// \brief Create a new printing code-completion consumer that prints its + /// Create a new printing code-completion consumer that prints its /// results to the given raw output stream. PrintingCodeCompleteConsumer(const CodeCompleteOptions &CodeCompleteOpts, raw_ostream &OS) : CodeCompleteConsumer(CodeCompleteOpts, false), OS(OS), CCTUInfo(std::make_shared<GlobalCodeCompletionAllocator>()) {} - /// \brief Prints the finalized code-completion results. + /// Prints the finalized code-completion results. void ProcessCodeCompleteResults(Sema &S, CodeCompletionContext Context, CodeCompletionResult *Results, unsigned NumResults) override; @@ -1009,6 +1177,6 @@ public: CodeCompletionTUInfo &getCodeCompletionTUInfo() override { return CCTUInfo; } }; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_SEMA_CODECOMPLETECONSUMER_H diff --git a/include/clang/Sema/CodeCompleteOptions.h b/include/clang/Sema/CodeCompleteOptions.h index 091d8ca60505e..1d3bbb4e585d7 100644 --- a/include/clang/Sema/CodeCompleteOptions.h +++ b/include/clang/Sema/CodeCompleteOptions.h @@ -35,9 +35,18 @@ public: /// Show brief documentation comments in code completion results. unsigned IncludeBriefComments : 1; + /// Hint whether to load data from the external AST to provide full results. + /// If false, namespace-level declarations from the preamble may be omitted. + unsigned LoadExternal : 1; + + /// Include results after corrections (small fix-its), e.g. change '.' to '->' + /// on member access, etc. + unsigned IncludeFixIts : 1; + CodeCompleteOptions() : IncludeMacros(0), IncludeCodePatterns(0), IncludeGlobals(1), - IncludeNamespaceLevelDecls(1), IncludeBriefComments(0) {} + IncludeNamespaceLevelDecls(1), IncludeBriefComments(0), + LoadExternal(1), IncludeFixIts(0) {} }; } // namespace clang diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 760a04d3c8d2e..83d5ab2cff85d 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines the classes used to store parsed information about +/// This file defines the classes used to store parsed information about /// declaration-specifiers and declarators. /// /// \verbatim @@ -29,8 +29,8 @@ #include "clang/Basic/OperatorKinds.h" #include "clang/Basic/Specifiers.h" #include "clang/Lex/Token.h" -#include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" @@ -48,7 +48,7 @@ namespace clang { class Declarator; struct TemplateIdAnnotation; -/// \brief Represents a C++ nested-name-specifier or a global scope specifier. +/// Represents a C++ nested-name-specifier or a global scope specifier. /// /// These can be in 3 states: /// 1) Not present, identified by isEmpty() @@ -72,12 +72,12 @@ public: SourceLocation getBeginLoc() const { return Range.getBegin(); } SourceLocation getEndLoc() const { return Range.getEnd(); } - /// \brief Retrieve the representation of the nested-name-specifier. + /// Retrieve the representation of the nested-name-specifier. NestedNameSpecifier *getScopeRep() const { return Builder.getRepresentation(); } - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'type::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -91,7 +91,7 @@ public: void Extend(ASTContext &Context, SourceLocation TemplateKWLoc, TypeLoc TL, SourceLocation ColonColonLoc); - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'identifier::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -105,7 +105,7 @@ public: void Extend(ASTContext &Context, IdentifierInfo *Identifier, SourceLocation IdentifierLoc, SourceLocation ColonColonLoc); - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -119,7 +119,7 @@ public: void Extend(ASTContext &Context, NamespaceDecl *Namespace, SourceLocation NamespaceLoc, SourceLocation ColonColonLoc); - /// \brief Extend the current nested-name-specifier by another + /// Extend the current nested-name-specifier by another /// nested-name-specifier component of the form 'namespace-alias::'. /// /// \param Context The AST context in which this nested-name-specifier @@ -134,11 +134,11 @@ public: void Extend(ASTContext &Context, NamespaceAliasDecl *Alias, SourceLocation AliasLoc, SourceLocation ColonColonLoc); - /// \brief Turn this (empty) nested-name-specifier into the global + /// 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' + /// Turns this (empty) nested-name-specifier into '__super' /// nested-name-specifier. /// /// \param Context The AST context in which this nested-name-specifier @@ -154,7 +154,7 @@ public: void MakeSuper(ASTContext &Context, CXXRecordDecl *RD, SourceLocation SuperLoc, SourceLocation ColonColonLoc); - /// \brief Make a new nested-name-specifier from incomplete source-location + /// Make a new nested-name-specifier from incomplete source-location /// information. /// /// FIXME: This routine should be used very, very rarely, in cases where we @@ -163,18 +163,18 @@ public: void MakeTrivial(ASTContext &Context, NestedNameSpecifier *Qualifier, SourceRange R); - /// \brief Adopt an existing nested-name-specifier (with source-range + /// Adopt an existing nested-name-specifier (with source-range /// information). void Adopt(NestedNameSpecifierLoc Other); - /// \brief Retrieve a nested-name-specifier with location information, copied + /// Retrieve a nested-name-specifier with location information, copied /// into the given AST context. /// /// \param Context The context into which this nested-name-specifier will be /// copied. NestedNameSpecifierLoc getWithLocInContext(ASTContext &Context) const; - /// \brief Retrieve the location of the name in the last qualifier + /// Retrieve the location of the name in the last qualifier /// in this nested name specifier. /// /// For example, the location of \c bar @@ -195,7 +195,7 @@ public: /// A scope specifier is present, and it refers to a real scope. bool isValid() const { return isNotEmpty() && getScopeRep() != nullptr; } - /// \brief Indicate that this nested-name-specifier is invalid. + /// Indicate that this nested-name-specifier is invalid. void SetInvalid(SourceRange R) { assert(R.isValid() && "Must have a valid source range"); if (Range.getBegin().isInvalid()) @@ -213,21 +213,21 @@ public: Builder.Clear(); } - /// \brief Retrieve the data associated with the source-location information. + /// Retrieve the data associated with the source-location information. char *location_data() const { return Builder.getBuffer().first; } - /// \brief Retrieve the size of the data associated with source-location + /// Retrieve the size of the data associated with source-location /// information. unsigned location_size() const { return Builder.getBuffer().second; } }; -/// \brief Captures information about "declaration specifiers". +/// Captures information about "declaration specifiers". /// /// "Declaration specifiers" encompasses storage-class-specifiers, /// type-specifiers, type-qualifiers, and function-specifiers. class DeclSpec { public: - /// \brief storage-class-specifier + /// storage-class-specifier /// \note The order of these enumerators is important for diagnostics. enum SCS { SCS_unspecified = 0, @@ -273,6 +273,7 @@ public: static const TST TST_void = clang::TST_void; static const TST TST_char = clang::TST_char; static const TST TST_wchar = clang::TST_wchar; + static const TST TST_char8 = clang::TST_char8; static const TST TST_char16 = clang::TST_char16; static const TST TST_char32 = clang::TST_char32; static const TST TST_int = clang::TST_int; @@ -281,6 +282,8 @@ public: static const TST TST_float = clang::TST_float; static const TST TST_double = clang::TST_double; static const TST TST_float16 = clang::TST_Float16; + static const TST TST_accum = clang::TST_Accum; + static const TST TST_fract = clang::TST_Fract; static const TST TST_float128 = clang::TST_float128; static const TST TST_bool = clang::TST_bool; static const TST TST_decimal32 = clang::TST_decimal32; @@ -326,6 +329,7 @@ public: PQ_TypeSpecifier = 2, PQ_TypeQualifier = 4, PQ_FunctionSpecifier = 8 + // FIXME: Attributes should be included here. }; private: @@ -344,6 +348,7 @@ private: unsigned TypeAltiVecBool : 1; unsigned TypeSpecOwned : 1; unsigned TypeSpecPipe : 1; + unsigned TypeSpecSat : 1; // type-qualifiers unsigned TypeQualifiers : 5; // Bitwise OR of TQ. @@ -379,7 +384,7 @@ private: SourceLocation StorageClassSpecLoc, ThreadStorageClassSpecLoc; SourceRange TSWRange; - SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc; + SourceLocation TSCLoc, TSSLoc, TSTLoc, AltiVecLoc, TSSatLoc; /// TSTNameLoc - If TypeSpecType is any of class, enum, struct, union, /// typename, then this is the location of the named type (if present); /// otherwise, it is the same as TSTLoc. Hence, the pair TSTLoc and @@ -428,6 +433,7 @@ public: TypeAltiVecBool(false), TypeSpecOwned(false), TypeSpecPipe(false), + TypeSpecSat(false), TypeQualifiers(TQ_unspecified), FS_inline_specified(false), FS_forceinline_specified(false), @@ -481,6 +487,7 @@ public: bool isTypeSpecOwned() const { return TypeSpecOwned; } bool isTypeRep() const { return isTypeRep((TST) TypeSpecType); } bool isTypeSpecPipe() const { return TypeSpecPipe; } + bool isTypeSpecSat() const { return TypeSpecSat; } ParsedType getRepAsType() const { assert(isTypeRep((TST) TypeSpecType) && "DeclSpec does not store a type"); @@ -507,6 +514,7 @@ public: SourceLocation getTypeSpecSignLoc() const { return TSSLoc; } SourceLocation getTypeSpecTypeLoc() const { return TSTLoc; } SourceLocation getAltiVecLoc() const { return AltiVecLoc; } + SourceLocation getTypeSpecSatLoc() const { return TSSatLoc; } SourceLocation getTypeSpecTypeNameLoc() const { assert(isDeclRep((TST) TypeSpecType) || TypeSpecType == TST_typename); @@ -523,7 +531,7 @@ public: bool hasTagDefinition() const; - /// \brief Turn a type-specifier-type into a string like "_Bool" or "union". + /// Turn a type-specifier-type into a string like "_Bool" or "union". static const char *getSpecifierName(DeclSpec::TST T, const PrintingPolicy &Policy); static const char *getSpecifierName(DeclSpec::TQ Q); @@ -544,7 +552,7 @@ public: SourceLocation getUnalignedSpecLoc() const { return TQ_unalignedLoc; } SourceLocation getPipeLoc() const { return TQ_pipeLoc; } - /// \brief Clear out all of the type qualifiers. + /// Clear out all of the type qualifiers. void ClearTypeQualifiers() { TypeQualifiers = 0; TQ_constLoc = SourceLocation(); @@ -585,7 +593,7 @@ public: FS_noreturnLoc = SourceLocation(); } - /// \brief Return true if any type-specifier has been found. + /// Return true if any type-specifier has been found. bool hasTypeSpecifier() const { return getTypeSpecType() != DeclSpec::TST_unspecified || getTypeSpecWidth() != DeclSpec::TSW_unspecified || @@ -593,7 +601,7 @@ public: getTypeSpecSign() != DeclSpec::TSS_unspecified; } - /// \brief Return a bitmask of which flavors of specifiers this + /// Return a bitmask of which flavors of specifiers this /// DeclSpec includes. unsigned getParsedSpecifiers() const; @@ -659,6 +667,8 @@ public: bool SetTypePipe(bool isPipe, SourceLocation Loc, const char *&PrevSpec, unsigned &DiagID, const PrintingPolicy &Policy); + bool SetTypeSpecSat(SourceLocation Loc, const char *&PrevSpec, + unsigned &DiagID); bool SetTypeSpecError(); void UpdateDeclRep(Decl *Rep) { assert(isDeclRep((TST) TypeSpecType)); @@ -712,7 +722,7 @@ public: return Attrs.getPool(); } - /// \brief Concatenates two attribute lists. + /// Concatenates two attribute lists. /// /// The GCC attribute syntax allows for the following: /// @@ -729,8 +739,8 @@ public: /// int __attribute__((may_alias)) __attribute__((aligned(16))) var; /// \endcode /// - void addAttributes(AttributeList *AL) { - Attrs.addAll(AL); + void addAttributes(ParsedAttributesView &AL) { + Attrs.addAll(AL.begin(), AL.end()); } bool hasAttributes() const { return !Attrs.empty(); } @@ -754,13 +764,13 @@ public: ObjCDeclSpec *getObjCQualifiers() const { return ObjCQualifiers; } void setObjCQualifiers(ObjCDeclSpec *quals) { ObjCQualifiers = quals; } - /// \brief Checks if this DeclSpec can stand alone, without a Declarator. + /// Checks if this DeclSpec can stand alone, without a Declarator. /// /// Only tag declspecs can stand alone. bool isMissingDeclaratorOk(); }; -/// \brief Captures information about "declaration specifiers" specific to +/// Captures information about "declaration specifiers" specific to /// Objective-C. class ObjCDeclSpec { public: @@ -882,42 +892,45 @@ private: }; -/// \brief Represents a C++ unqualified-id that has been parsed. +/// Describes the kind of unqualified-id parsed. +enum class UnqualifiedIdKind { + /// An identifier. + IK_Identifier, + /// An overloaded operator name, e.g., operator+. + IK_OperatorFunctionId, + /// A conversion function name, e.g., operator int. + IK_ConversionFunctionId, + /// A user-defined literal name, e.g., operator "" _i. + IK_LiteralOperatorId, + /// A constructor name. + IK_ConstructorName, + /// A constructor named via a template-id. + IK_ConstructorTemplateId, + /// A destructor name. + IK_DestructorName, + /// A template-id, e.g., f<int>. + IK_TemplateId, + /// An implicit 'self' parameter + IK_ImplicitSelfParam, + /// A deduction-guide name (a template-name) + IK_DeductionGuideName +}; + +/// Represents a C++ unqualified-id that has been parsed. class UnqualifiedId { private: UnqualifiedId(const UnqualifiedId &Other) = delete; const UnqualifiedId &operator=(const UnqualifiedId &) = delete; public: - /// \brief Describes the kind of unqualified-id parsed. - enum IdKind { - /// \brief An identifier. - IK_Identifier, - /// \brief An overloaded operator name, e.g., operator+. - IK_OperatorFunctionId, - /// \brief A conversion function name, e.g., operator int. - IK_ConversionFunctionId, - /// \brief A user-defined literal name, e.g., operator "" _i. - IK_LiteralOperatorId, - /// \brief A constructor name. - IK_ConstructorName, - /// \brief A constructor named via a template-id. - IK_ConstructorTemplateId, - /// \brief A destructor name. - IK_DestructorName, - /// \brief A template-id, e.g., f<int>. - IK_TemplateId, - /// \brief An implicit 'self' parameter - IK_ImplicitSelfParam, - /// \brief A deduction-guide name (a template-name) - IK_DeductionGuideName - } Kind; + /// Describes the kind of unqualified-id parsed. + UnqualifiedIdKind Kind; struct OFI { - /// \brief The kind of overloaded operator. + /// The kind of overloaded operator. OverloadedOperatorKind Operator; - /// \brief The source locations of the individual tokens that name + /// The source locations of the individual tokens that name /// the operator, e.g., the "new", "[", and "]" tokens in /// operator new []. /// @@ -927,78 +940,79 @@ public: unsigned SymbolLocations[3]; }; - /// \brief Anonymous union that holds extra data associated with the + /// Anonymous union that holds extra data associated with the /// parsed unqualified-id. union { - /// \brief When Kind == IK_Identifier, the parsed identifier, or when + /// When Kind == IK_Identifier, the parsed identifier, or when /// Kind == IK_UserLiteralId, the identifier suffix. IdentifierInfo *Identifier; - /// \brief When Kind == IK_OperatorFunctionId, the overloaded operator + /// When Kind == IK_OperatorFunctionId, the overloaded operator /// that we parsed. struct OFI OperatorFunctionId; - /// \brief When Kind == IK_ConversionFunctionId, the type that the + /// When Kind == IK_ConversionFunctionId, the type that the /// conversion function names. UnionParsedType ConversionFunctionId; - /// \brief When Kind == IK_ConstructorName, the class-name of the type + /// When Kind == IK_ConstructorName, the class-name of the type /// whose constructor is being referenced. UnionParsedType ConstructorName; - /// \brief When Kind == IK_DestructorName, the type referred to by the + /// When Kind == IK_DestructorName, the type referred to by the /// class-name. UnionParsedType DestructorName; - /// \brief When Kind == IK_DeductionGuideName, the parsed template-name. + /// When Kind == IK_DeductionGuideName, the parsed template-name. UnionParsedTemplateTy TemplateName; - /// \brief When Kind == IK_TemplateId or IK_ConstructorTemplateId, + /// When Kind == IK_TemplateId or IK_ConstructorTemplateId, /// the template-id annotation that contains the template name and /// template arguments. TemplateIdAnnotation *TemplateId; }; - /// \brief The location of the first token that describes this unqualified-id, + /// The location of the first token that describes this unqualified-id, /// which will be the location of the identifier, "operator" keyword, /// tilde (for a destructor), or the template name of a template-id. SourceLocation StartLocation; - /// \brief The location of the last token that describes this unqualified-id. + /// The location of the last token that describes this unqualified-id. SourceLocation EndLocation; - - UnqualifiedId() : Kind(IK_Identifier), Identifier(nullptr) { } - /// \brief Clear out this unqualified-id, setting it to default (invalid) + UnqualifiedId() + : Kind(UnqualifiedIdKind::IK_Identifier), Identifier(nullptr) {} + + /// Clear out this unqualified-id, setting it to default (invalid) /// state. void clear() { - Kind = IK_Identifier; + Kind = UnqualifiedIdKind::IK_Identifier; Identifier = nullptr; StartLocation = SourceLocation(); EndLocation = SourceLocation(); } - /// \brief Determine whether this unqualified-id refers to a valid name. + /// Determine whether this unqualified-id refers to a valid name. bool isValid() const { return StartLocation.isValid(); } - /// \brief Determine whether this unqualified-id refers to an invalid name. + /// Determine whether this unqualified-id refers to an invalid name. bool isInvalid() const { return !isValid(); } - /// \brief Determine what kind of name we have. - IdKind getKind() const { return Kind; } - void setKind(IdKind kind) { Kind = kind; } + /// Determine what kind of name we have. + UnqualifiedIdKind getKind() const { return Kind; } + void setKind(UnqualifiedIdKind kind) { Kind = kind; } - /// \brief Specify that this unqualified-id was parsed as an identifier. + /// Specify that this unqualified-id was parsed as an identifier. /// /// \param Id the parsed identifier. /// \param IdLoc the location of the parsed identifier. void setIdentifier(const IdentifierInfo *Id, SourceLocation IdLoc) { - Kind = IK_Identifier; + Kind = UnqualifiedIdKind::IK_Identifier; Identifier = const_cast<IdentifierInfo *>(Id); StartLocation = EndLocation = IdLoc; } - /// \brief Specify that this unqualified-id was parsed as an + /// Specify that this unqualified-id was parsed as an /// operator-function-id. /// /// \param OperatorLoc the location of the 'operator' keyword. @@ -1011,7 +1025,7 @@ public: OverloadedOperatorKind Op, SourceLocation SymbolLocations[3]); - /// \brief Specify that this unqualified-id was parsed as a + /// Specify that this unqualified-id was parsed as a /// conversion-function-id. /// /// \param OperatorLoc the location of the 'operator' keyword. @@ -1022,13 +1036,13 @@ public: void setConversionFunctionId(SourceLocation OperatorLoc, ParsedType Ty, SourceLocation EndLoc) { - Kind = IK_ConversionFunctionId; + Kind = UnqualifiedIdKind::IK_ConversionFunctionId; StartLocation = OperatorLoc; EndLocation = EndLoc; ConversionFunctionId = Ty; } - /// \brief Specific that this unqualified-id was parsed as a + /// Specific that this unqualified-id was parsed as a /// literal-operator-id. /// /// \param Id the parsed identifier. @@ -1038,13 +1052,13 @@ public: /// \param IdLoc the location of the identifier. void setLiteralOperatorId(const IdentifierInfo *Id, SourceLocation OpLoc, SourceLocation IdLoc) { - Kind = IK_LiteralOperatorId; + Kind = UnqualifiedIdKind::IK_LiteralOperatorId; Identifier = const_cast<IdentifierInfo *>(Id); StartLocation = OpLoc; EndLocation = IdLoc; } - /// \brief Specify that this unqualified-id was parsed as a constructor name. + /// Specify that this unqualified-id was parsed as a constructor name. /// /// \param ClassType the class type referred to by the constructor name. /// @@ -1054,13 +1068,13 @@ public: void setConstructorName(ParsedType ClassType, SourceLocation ClassNameLoc, SourceLocation EndLoc) { - Kind = IK_ConstructorName; + Kind = UnqualifiedIdKind::IK_ConstructorName; StartLocation = ClassNameLoc; EndLocation = EndLoc; ConstructorName = ClassType; } - /// \brief Specify that this unqualified-id was parsed as a + /// Specify that this unqualified-id was parsed as a /// template-id that names a constructor. /// /// \param TemplateId the template-id annotation that describes the parsed @@ -1068,7 +1082,7 @@ public: /// \p TemplateId and will free it on destruction. void setConstructorTemplateId(TemplateIdAnnotation *TemplateId); - /// \brief Specify that this unqualified-id was parsed as a destructor name. + /// Specify that this unqualified-id was parsed as a destructor name. /// /// \param TildeLoc the location of the '~' that introduces the destructor /// name. @@ -1077,32 +1091,32 @@ public: void setDestructorName(SourceLocation TildeLoc, ParsedType ClassType, SourceLocation EndLoc) { - Kind = IK_DestructorName; + Kind = UnqualifiedIdKind::IK_DestructorName; StartLocation = TildeLoc; EndLocation = EndLoc; DestructorName = ClassType; } - /// \brief Specify that this unqualified-id was parsed as a template-id. + /// Specify that this unqualified-id was parsed as a template-id. /// /// \param TemplateId the template-id annotation that describes the parsed /// template-id. This UnqualifiedId instance will take ownership of the /// \p TemplateId and will free it on destruction. void setTemplateId(TemplateIdAnnotation *TemplateId); - /// \brief Specify that this unqualified-id was parsed as a template-name for + /// Specify that this unqualified-id was parsed as a template-name for /// a deduction-guide. /// /// \param Template The parsed template-name. /// \param TemplateLoc The location of the parsed template-name. void setDeductionGuideName(ParsedTemplateTy Template, SourceLocation TemplateLoc) { - Kind = IK_DeductionGuideName; + Kind = UnqualifiedIdKind::IK_DeductionGuideName; TemplateName = Template; StartLocation = EndLocation = TemplateLoc; } - /// \brief Return the source range that covers this unqualified-id. + /// Return the source range that covers this unqualified-id. SourceRange getSourceRange() const LLVM_READONLY { return SourceRange(StartLocation, EndLocation); } @@ -1110,10 +1124,10 @@ public: SourceLocation getLocEnd() const LLVM_READONLY { return EndLocation; } }; -/// \brief A set of tokens that has been cached for later parsing. +/// A set of tokens that has been cached for later parsing. typedef SmallVector<Token, 4> CachedTokens; -/// \brief One instance of this struct is used for each type in a +/// One instance of this struct is used for each type in a /// declarator that is parsed. /// /// This is intended to be a small value object. @@ -1133,11 +1147,9 @@ struct DeclaratorChunk { return SourceRange(Loc, EndLoc); } - struct TypeInfoCommon { - AttributeList *AttrList; - }; + ParsedAttributesView AttrList; - struct PointerTypeInfo : TypeInfoCommon { + struct PointerTypeInfo { /// The type qualifiers: const/volatile/restrict/unaligned/atomic. unsigned TypeQuals : 5; @@ -1160,7 +1172,7 @@ struct DeclaratorChunk { } }; - struct ReferenceTypeInfo : TypeInfoCommon { + struct ReferenceTypeInfo { /// The type qualifier: restrict. [GNU] C++ extension bool HasRestrict : 1; /// True if this is an lvalue reference, false if it's an rvalue reference. @@ -1169,7 +1181,7 @@ struct DeclaratorChunk { } }; - struct ArrayTypeInfo : TypeInfoCommon { + struct ArrayTypeInfo { /// The type qualifiers for the array: /// const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; @@ -1220,7 +1232,7 @@ struct DeclaratorChunk { SourceRange Range; }; - struct FunctionTypeInfo : TypeInfoCommon { + struct FunctionTypeInfo { /// hasPrototype - This is true if the function had at least one typed /// parameter. If the function is () or (a,b,c), then it has no prototype, /// and is treated as a K&R-style function. @@ -1234,7 +1246,7 @@ struct DeclaratorChunk { /// Can this declaration be a constructor-style initializer? unsigned isAmbiguous : 1; - /// \brief Whether the ref-qualifier (if any) is an lvalue reference. + /// Whether the ref-qualifier (if any) is an lvalue reference. /// Otherwise, it's an rvalue reference. unsigned RefQualifierIsLValueRef : 1; @@ -1270,34 +1282,34 @@ struct DeclaratorChunk { /// number of declarations in the function prototype. unsigned NumExceptionsOrDecls; - /// \brief The location of the ref-qualifier, if any. + /// The location of the ref-qualifier, if any. /// /// If this is an invalid location, there is no ref-qualifier. unsigned RefQualifierLoc; - /// \brief The location of the const-qualifier, if any. + /// The location of the const-qualifier, if any. /// /// If this is an invalid location, there is no const-qualifier. unsigned ConstQualifierLoc; - /// \brief The location of the volatile-qualifier, if any. + /// The location of the volatile-qualifier, if any. /// /// If this is an invalid location, there is no volatile-qualifier. unsigned VolatileQualifierLoc; - /// \brief The location of the restrict-qualifier, if any. + /// 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 + /// The location of the 'mutable' qualifer in a lambda-declarator, if /// any. unsigned MutableLoc; - /// \brief The beginning location of the exception specification, if any. + /// The beginning location of the exception specification, if any. unsigned ExceptionSpecLocBeg; - /// \brief The end location of the exception specification, if any. + /// The end location of the exception specification, if any. unsigned ExceptionSpecLocEnd; /// Params - This is a pointer to a new[]'d array of ParamInfo objects that @@ -1306,16 +1318,16 @@ struct DeclaratorChunk { ParamInfo *Params; union { - /// \brief Pointer to a new[]'d array of TypeAndRange objects that + /// Pointer to a new[]'d array of TypeAndRange objects that /// contain the types in the function's dynamic exception specification /// and their locations, if there is one. TypeAndRange *Exceptions; - /// \brief Pointer to the expression in the noexcept-specifier of this + /// 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 + /// Pointer to the cached tokens for an exception-specification /// that has not yet been parsed. CachedTokens *ExceptionSpecTokens; @@ -1325,11 +1337,11 @@ struct DeclaratorChunk { NamedDecl **DeclsInPrototype; }; - /// \brief If HasTrailingReturnType is true, this is the trailing return + /// If HasTrailingReturnType is true, this is the trailing return /// type specified. UnionParsedType TrailingReturnType; - /// \brief Reset the parameter list to having zero parameters. + /// Reset the parameter list to having zero parameters. /// /// This is used in various places for error recovery. void freeParams() { @@ -1343,8 +1355,7 @@ struct DeclaratorChunk { } void destroy() { - if (DeleteParams) - delete[] Params; + freeParams(); switch (getExceptionSpecType()) { default: break; @@ -1390,66 +1401,66 @@ struct DeclaratorChunk { return SourceRange(getExceptionSpecLocBeg(), getExceptionSpecLocEnd()); } - /// \brief Retrieve the location of the ref-qualifier, if any. + /// Retrieve the location of the ref-qualifier, if any. SourceLocation getRefQualifierLoc() const { return SourceLocation::getFromRawEncoding(RefQualifierLoc); } - /// \brief Retrieve the location of the 'const' qualifier, if any. + /// Retrieve the location of the 'const' qualifier, if any. SourceLocation getConstQualifierLoc() const { return SourceLocation::getFromRawEncoding(ConstQualifierLoc); } - /// \brief Retrieve the location of the 'volatile' qualifier, if any. + /// 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. + /// 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. + /// Retrieve the location of the 'mutable' qualifier, if any. SourceLocation getMutableLoc() const { return SourceLocation::getFromRawEncoding(MutableLoc); } - /// \brief Determine whether this function declaration contains a + /// Determine whether this function declaration contains a /// ref-qualifier. bool hasRefQualifier() const { return getRefQualifierLoc().isValid(); } - /// \brief Determine whether this lambda-declarator contains a 'mutable' + /// Determine whether this lambda-declarator contains a 'mutable' /// qualifier. bool hasMutableQualifier() const { return getMutableLoc().isValid(); } - /// \brief Get the type of exception specification this function has. + /// Get the type of exception specification this function has. ExceptionSpecificationType getExceptionSpecType() const { return static_cast<ExceptionSpecificationType>(ExceptionSpecType); } - /// \brief Get the number of dynamic exception specifications. + /// Get the number of dynamic exception specifications. unsigned getNumExceptions() const { assert(ExceptionSpecType != EST_None); return NumExceptionsOrDecls; } - /// \brief Get the non-parameter decls defined within this function + /// Get the non-parameter decls defined within this function /// prototype. Typically these are tag declarations. ArrayRef<NamedDecl *> getDeclsInPrototype() const { assert(ExceptionSpecType == EST_None); return llvm::makeArrayRef(DeclsInPrototype, NumExceptionsOrDecls); } - /// \brief Determine whether this function declarator had a + /// Determine whether this function declarator had a /// trailing-return-type. bool hasTrailingReturnType() const { return HasTrailingReturnType; } - /// \brief Get the trailing-return-type for this function declarator. + /// Get the trailing-return-type for this function declarator. ParsedType getTrailingReturnType() const { return TrailingReturnType; } }; - struct BlockPointerTypeInfo : TypeInfoCommon { + struct BlockPointerTypeInfo { /// For now, sema will catch these as invalid. /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; @@ -1458,7 +1469,7 @@ struct DeclaratorChunk { } }; - struct MemberPointerTypeInfo : TypeInfoCommon { + struct MemberPointerTypeInfo { /// The type qualifiers: const/volatile/restrict/__unaligned/_Atomic. unsigned TypeQuals : 5; // CXXScopeSpec has a constructor, so it can't be a direct member. @@ -1475,15 +1486,14 @@ struct DeclaratorChunk { } }; - struct PipeTypeInfo : TypeInfoCommon { - /// The access writes. - unsigned AccessWrites : 3; + struct PipeTypeInfo { + /// The access writes. + unsigned AccessWrites : 3; - void destroy() {} + void destroy() {} }; union { - TypeInfoCommon Common; PointerTypeInfo Ptr; ReferenceTypeInfo Ref; ArrayTypeInfo Arr; @@ -1506,17 +1516,12 @@ struct DeclaratorChunk { } } - /// \brief If there are attributes applied to this declaratorchunk, return + /// If there are attributes applied to this declaratorchunk, return /// them. - const AttributeList *getAttrs() const { - return Common.AttrList; - } + const ParsedAttributesView &getAttrs() const { return AttrList; } + ParsedAttributesView &getAttrs() { return AttrList; } - AttributeList *&getAttrListRef() { - return Common.AttrList; - } - - /// \brief Return a DeclaratorChunk for a pointer. + /// Return a DeclaratorChunk for a pointer. static DeclaratorChunk getPointer(unsigned TypeQuals, SourceLocation Loc, SourceLocation ConstQualLoc, SourceLocation VolatileQualLoc, @@ -1532,11 +1537,10 @@ struct DeclaratorChunk { I.Ptr.RestrictQualLoc = RestrictQualLoc.getRawEncoding(); I.Ptr.AtomicQualLoc = AtomicQualLoc.getRawEncoding(); I.Ptr.UnalignedQualLoc = UnalignedQualLoc.getRawEncoding(); - I.Ptr.AttrList = nullptr; return I; } - /// \brief Return a DeclaratorChunk for a reference. + /// Return a DeclaratorChunk for a reference. static DeclaratorChunk getReference(unsigned TypeQuals, SourceLocation Loc, bool lvalue) { DeclaratorChunk I; @@ -1544,11 +1548,10 @@ struct DeclaratorChunk { I.Loc = Loc; I.Ref.HasRestrict = (TypeQuals & DeclSpec::TQ_restrict) != 0; I.Ref.LValueRef = lvalue; - I.Ref.AttrList = nullptr; return I; } - /// \brief Return a DeclaratorChunk for an array. + /// Return a DeclaratorChunk for an array. static DeclaratorChunk getArray(unsigned TypeQuals, bool isStatic, bool isStar, Expr *NumElts, SourceLocation LBLoc, SourceLocation RBLoc) { @@ -1556,7 +1559,6 @@ struct DeclaratorChunk { I.Kind = Array; I.Loc = LBLoc; I.EndLoc = RBLoc; - I.Arr.AttrList = nullptr; I.Arr.TypeQuals = TypeQuals; I.Arr.hasStatic = isStatic; I.Arr.isStar = isStar; @@ -1593,25 +1595,23 @@ struct DeclaratorChunk { TypeResult TrailingReturnType = TypeResult()); - /// \brief Return a DeclaratorChunk for a block. + /// Return a DeclaratorChunk for a block. static DeclaratorChunk getBlockPointer(unsigned TypeQuals, SourceLocation Loc) { DeclaratorChunk I; I.Kind = BlockPointer; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } - /// \brief Return a DeclaratorChunk for a block. + /// Return a DeclaratorChunk for a block. static DeclaratorChunk getPipe(unsigned TypeQuals, SourceLocation Loc) { DeclaratorChunk I; I.Kind = Pipe; I.Loc = Loc; I.Cls.TypeQuals = TypeQuals; - I.Cls.AttrList = nullptr; return I; } @@ -1623,19 +1623,17 @@ struct DeclaratorChunk { I.Loc = SS.getBeginLoc(); I.EndLoc = Loc; I.Mem.TypeQuals = TypeQuals; - I.Mem.AttrList = nullptr; new (I.Mem.ScopeMem) CXXScopeSpec(SS); return I; } - /// \brief Return a DeclaratorChunk for a paren. + /// Return a DeclaratorChunk for a paren. static DeclaratorChunk getParen(SourceLocation LParenLoc, SourceLocation RParenLoc) { DeclaratorChunk I; I.Kind = Paren; I.Loc = LParenLoc; I.EndLoc = RParenLoc; - I.Common.AttrList = nullptr; return I; } @@ -1696,7 +1694,7 @@ public: } }; -/// \brief Described the kind of function definition (if any) provided for +/// Described the kind of function definition (if any) provided for /// a function. enum FunctionDefinitionKind { FDK_Declaration, @@ -1705,21 +1703,7 @@ enum FunctionDefinitionKind { FDK_Deleted }; -/// \brief Information about one declarator, including the parsed type -/// information and the identifier. -/// -/// When the declarator is fully formed, this is turned into the appropriate -/// Decl object. -/// -/// Declarators come in two types: normal declarators and abstract declarators. -/// Abstract declarators are used when parsing types, and don't have an -/// identifier. Normal declarators do have ID's. -/// -/// Instances of this class should be a transient object that lives on the -/// stack, not objects that are allocated in large quantities on the heap. -class Declarator { -public: - enum TheContext { +enum class DeclaratorContext { FileContext, // File scope declaration. PrototypeContext, // Within a function prototype. ObjCResultContext, // An ObjC method result type. @@ -1741,19 +1725,36 @@ public: LambdaExprParameterContext, // Lambda-expression parameter declarator. ConversionIdContext, // C++ conversion-type-id. TrailingReturnContext, // C++11 trailing-type-specifier. - TemplateTypeArgContext, // Template type argument. + TrailingReturnVarContext, // C++11 trailing-type-specifier for variable. + TemplateArgContext, // Any template argument (in template argument list). + TemplateTypeArgContext, // Template type argument (in default argument). AliasDeclContext, // C++11 alias-declaration. AliasTemplateContext // C++11 alias-declaration template. - }; +}; + +/// Information about one declarator, including the parsed type +/// information and the identifier. +/// +/// When the declarator is fully formed, this is turned into the appropriate +/// Decl object. +/// +/// Declarators come in two types: normal declarators and abstract declarators. +/// Abstract declarators are used when parsing types, and don't have an +/// identifier. Normal declarators do have ID's. +/// +/// Instances of this class should be a transient object that lives on the +/// stack, not objects that are allocated in large quantities on the heap. +class Declarator { + private: const DeclSpec &DS; CXXScopeSpec SS; UnqualifiedId Name; SourceRange Range; - /// \brief Where we are parsing this declarator. - TheContext Context; + /// Where we are parsing this declarator. + DeclaratorContext Context; /// The C++17 structured binding, if any. This is an alternative to a Name. DecompositionDeclarator BindingGroup; @@ -1776,10 +1777,10 @@ private: /// Actually a FunctionDefinitionKind. unsigned FunctionDefinition : 2; - /// \brief Is this Declarator a redeclaration? + /// Is this Declarator a redeclaration? unsigned Redeclaration : 1; - /// \brief true if the declaration is preceded by \c __extension__. + /// true if the declaration is preceded by \c __extension__. unsigned Extension : 1; /// Indicates whether this is an Objective-C instance variable. @@ -1794,7 +1795,7 @@ private: /// Attrs - Attributes. ParsedAttributes Attrs; - /// \brief The asm label, if specified. + /// The asm label, if specified. Expr *AsmLabel; #ifndef _MSC_VER @@ -1809,18 +1810,18 @@ private: }; #endif - /// \brief If this is the second or subsequent declarator in this declaration, + /// If this is the second or subsequent declarator in this declaration, /// the location of the comma before this declarator. SourceLocation CommaLoc; - /// \brief If provided, the source location of the ellipsis used to describe + /// If provided, the source location of the ellipsis used to describe /// this declarator as a parameter pack. SourceLocation EllipsisLoc; friend struct DeclaratorChunk; public: - Declarator(const DeclSpec &ds, TheContext C) + Declarator(const DeclSpec &ds, DeclaratorContext C) : DS(ds), Range(ds.getSourceRange()), Context(C), InvalidType(DS.getTypeSpecType() == DeclSpec::TST_error), GroupingParens(false), FunctionDefinition(FDK_Declaration), @@ -1851,23 +1852,23 @@ public: const CXXScopeSpec &getCXXScopeSpec() const { return SS; } CXXScopeSpec &getCXXScopeSpec() { return SS; } - /// \brief Retrieve the name specified by this declarator. + /// Retrieve the name specified by this declarator. UnqualifiedId &getName() { return Name; } const DecompositionDeclarator &getDecompositionDeclarator() const { return BindingGroup; } - TheContext getContext() const { return Context; } + DeclaratorContext getContext() const { return Context; } bool isPrototypeContext() const { - return (Context == PrototypeContext || - Context == ObjCParameterContext || - Context == ObjCResultContext || - Context == LambdaExprParameterContext); + return (Context == DeclaratorContext::PrototypeContext || + Context == DeclaratorContext::ObjCParameterContext || + Context == DeclaratorContext::ObjCResultContext || + Context == DeclaratorContext::LambdaExprParameterContext); } - /// \brief Get the source range that spans this declarator. + /// Get the source range that spans this declarator. SourceRange getSourceRange() const LLVM_READONLY { return Range; } SourceLocation getLocStart() const LLVM_READONLY { return Range.getBegin(); } SourceLocation getLocEnd() const LLVM_READONLY { return Range.getEnd(); } @@ -1895,7 +1896,7 @@ public: Range.setEnd(SR.getEnd()); } - /// \brief Reset the contents of this Declarator. + /// Reset the contents of this Declarator. void clear() { SS.clear(); Name.clear(); @@ -1919,32 +1920,34 @@ public: /// parameter lists. bool mayOmitIdentifier() const { switch (Context) { - case FileContext: - case KNRTypeListContext: - case MemberContext: - case BlockContext: - case ForContext: - case InitStmtContext: - case ConditionContext: + case DeclaratorContext::FileContext: + case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::MemberContext: + case DeclaratorContext::BlockContext: + case DeclaratorContext::ForContext: + case DeclaratorContext::InitStmtContext: + case DeclaratorContext::ConditionContext: return false; - case TypeNameContext: - case FunctionalCastContext: - case AliasDeclContext: - case AliasTemplateContext: - case PrototypeContext: - case LambdaExprParameterContext: - case ObjCParameterContext: - case ObjCResultContext: - case TemplateParamContext: - case CXXNewContext: - case CXXCatchContext: - case ObjCCatchContext: - case BlockLiteralContext: - case LambdaExprContext: - case ConversionIdContext: - case TemplateTypeArgContext: - case TrailingReturnContext: + case DeclaratorContext::TypeNameContext: + case DeclaratorContext::FunctionalCastContext: + case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::PrototypeContext: + case DeclaratorContext::LambdaExprParameterContext: + case DeclaratorContext::ObjCParameterContext: + case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::TemplateParamContext: + case DeclaratorContext::CXXNewContext: + case DeclaratorContext::CXXCatchContext: + case DeclaratorContext::ObjCCatchContext: + case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::TemplateArgContext: + case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TrailingReturnContext: + case DeclaratorContext::TrailingReturnVarContext: return true; } llvm_unreachable("unknown context kind!"); @@ -1955,32 +1958,34 @@ public: /// typenames. bool mayHaveIdentifier() const { switch (Context) { - case FileContext: - case KNRTypeListContext: - case MemberContext: - case BlockContext: - case ForContext: - case InitStmtContext: - case ConditionContext: - case PrototypeContext: - case LambdaExprParameterContext: - case TemplateParamContext: - case CXXCatchContext: - case ObjCCatchContext: + case DeclaratorContext::FileContext: + case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::MemberContext: + case DeclaratorContext::BlockContext: + case DeclaratorContext::ForContext: + case DeclaratorContext::InitStmtContext: + case DeclaratorContext::ConditionContext: + case DeclaratorContext::PrototypeContext: + case DeclaratorContext::LambdaExprParameterContext: + case DeclaratorContext::TemplateParamContext: + case DeclaratorContext::CXXCatchContext: + case DeclaratorContext::ObjCCatchContext: return true; - case TypeNameContext: - case FunctionalCastContext: - case CXXNewContext: - case AliasDeclContext: - case AliasTemplateContext: - case ObjCParameterContext: - case ObjCResultContext: - case BlockLiteralContext: - case LambdaExprContext: - case ConversionIdContext: - case TemplateTypeArgContext: - case TrailingReturnContext: + case DeclaratorContext::TypeNameContext: + case DeclaratorContext::FunctionalCastContext: + case DeclaratorContext::CXXNewContext: + case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::ObjCParameterContext: + case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::TemplateArgContext: + case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TrailingReturnContext: + case DeclaratorContext::TrailingReturnVarContext: return false; } llvm_unreachable("unknown context kind!"); @@ -1989,38 +1994,40 @@ public: /// Return true if the context permits a C++17 decomposition declarator. bool mayHaveDecompositionDeclarator() const { switch (Context) { - case FileContext: + case DeclaratorContext::FileContext: // FIXME: It's not clear that the proposal meant to allow file-scope // structured bindings, but it does. - case BlockContext: - case ForContext: - case InitStmtContext: - case ConditionContext: + case DeclaratorContext::BlockContext: + case DeclaratorContext::ForContext: + case DeclaratorContext::InitStmtContext: + case DeclaratorContext::ConditionContext: return true; - case MemberContext: - case PrototypeContext: - case TemplateParamContext: + case DeclaratorContext::MemberContext: + case DeclaratorContext::PrototypeContext: + case DeclaratorContext::TemplateParamContext: // Maybe one day... return false; // These contexts don't allow any kind of non-abstract declarator. - case KNRTypeListContext: - case TypeNameContext: - case FunctionalCastContext: - case AliasDeclContext: - case AliasTemplateContext: - case LambdaExprParameterContext: - case ObjCParameterContext: - case ObjCResultContext: - case CXXNewContext: - case CXXCatchContext: - case ObjCCatchContext: - case BlockLiteralContext: - case LambdaExprContext: - case ConversionIdContext: - case TemplateTypeArgContext: - case TrailingReturnContext: + case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::TypeNameContext: + case DeclaratorContext::FunctionalCastContext: + case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::LambdaExprParameterContext: + case DeclaratorContext::ObjCParameterContext: + case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::CXXNewContext: + case DeclaratorContext::CXXCatchContext: + case DeclaratorContext::ObjCCatchContext: + case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::TemplateArgContext: + case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TrailingReturnContext: + case DeclaratorContext::TrailingReturnVarContext: return false; } llvm_unreachable("unknown context kind!"); @@ -2035,45 +2042,47 @@ public: return false; if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_extern && - Context != FileContext) + Context != DeclaratorContext::FileContext) return false; // Special names can't have direct initializers. - if (Name.getKind() != UnqualifiedId::IK_Identifier) + if (Name.getKind() != UnqualifiedIdKind::IK_Identifier) return false; switch (Context) { - case FileContext: - case BlockContext: - case ForContext: - case InitStmtContext: + case DeclaratorContext::FileContext: + case DeclaratorContext::BlockContext: + case DeclaratorContext::ForContext: + case DeclaratorContext::InitStmtContext: + case DeclaratorContext::TrailingReturnVarContext: return true; - case ConditionContext: + case DeclaratorContext::ConditionContext: // This may not be followed by a direct initializer, but it can't be a // function declaration either, and we'd prefer to perform a tentative // parse in order to produce the right diagnostic. return true; - case KNRTypeListContext: - case MemberContext: - case PrototypeContext: - case LambdaExprParameterContext: - case ObjCParameterContext: - case ObjCResultContext: - case TemplateParamContext: - case CXXCatchContext: - case ObjCCatchContext: - case TypeNameContext: - case FunctionalCastContext: // FIXME - case CXXNewContext: - case AliasDeclContext: - case AliasTemplateContext: - case BlockLiteralContext: - case LambdaExprContext: - case ConversionIdContext: - case TemplateTypeArgContext: - case TrailingReturnContext: + case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::MemberContext: + case DeclaratorContext::PrototypeContext: + case DeclaratorContext::LambdaExprParameterContext: + case DeclaratorContext::ObjCParameterContext: + case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::TemplateParamContext: + case DeclaratorContext::CXXCatchContext: + case DeclaratorContext::ObjCCatchContext: + case DeclaratorContext::TypeNameContext: + case DeclaratorContext::FunctionalCastContext: // FIXME + case DeclaratorContext::CXXNewContext: + case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::TemplateArgContext: + case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TrailingReturnContext: return false; } llvm_unreachable("unknown context kind!"); @@ -2089,8 +2098,8 @@ public: /// special C++ name (constructor, destructor, etc.), or a structured /// binding (which is not exactly a name, but occupies the same position). bool hasName() const { - return Name.getKind() != UnqualifiedId::IK_Identifier || Name.Identifier || - isDecompositionDeclarator(); + return Name.getKind() != UnqualifiedIdKind::IK_Identifier || + Name.Identifier || isDecompositionDeclarator(); } /// Return whether this declarator is a decomposition declarator. @@ -2099,14 +2108,14 @@ public: } IdentifierInfo *getIdentifier() const { - if (Name.getKind() == UnqualifiedId::IK_Identifier) + if (Name.getKind() == UnqualifiedIdKind::IK_Identifier) return Name.Identifier; return nullptr; } SourceLocation getIdentifierLoc() const { return Name.StartLocation; } - /// \brief Set the name of this declarator to be the given identifier. + /// Set the name of this declarator to be the given identifier. void SetIdentifier(IdentifierInfo *Id, SourceLocation IdLoc) { Name.setIdentifier(Id, IdLoc); } @@ -2119,23 +2128,33 @@ public: /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to /// EndLoc, which should be the last token of the chunk. - void AddTypeInfo(const DeclaratorChunk &TI, - ParsedAttributes &attrs, + /// This function takes attrs by R-Value reference because it takes ownership + /// of those attributes from the parameter. + void AddTypeInfo(const DeclaratorChunk &TI, ParsedAttributes &&attrs, SourceLocation EndLoc) { DeclTypeInfo.push_back(TI); - DeclTypeInfo.back().getAttrListRef() = attrs.getList(); + DeclTypeInfo.back().getAttrs().addAll(attrs.begin(), attrs.end()); getAttributePool().takeAllFrom(attrs.getPool()); if (!EndLoc.isInvalid()) SetRangeEnd(EndLoc); } - /// \brief Add a new innermost chunk to this declarator. + /// AddTypeInfo - Add a chunk to this declarator. Also extend the range to + /// EndLoc, which should be the last token of the chunk. + void AddTypeInfo(const DeclaratorChunk &TI, SourceLocation EndLoc) { + DeclTypeInfo.push_back(TI); + + if (!EndLoc.isInvalid()) + SetRangeEnd(EndLoc); + } + + /// Add a new innermost chunk to this declarator. void AddInnermostTypeInfo(const DeclaratorChunk &TI) { DeclTypeInfo.insert(DeclTypeInfo.begin(), TI); } - /// \brief Return the number of types applied to this declarator. + /// Return the number of types applied to this declarator. unsigned getNumTypeObjects() const { return DeclTypeInfo.size(); } /// Return the specified TypeInfo from this declarator. TypeInfo #0 is @@ -2242,7 +2261,7 @@ public: return const_cast<Declarator*>(this)->getFunctionTypeInfo(); } - /// \brief Determine whether the declaration that will be produced from + /// Determine whether the declaration that will be produced from /// this declaration will be a function. /// /// A declaration can declare a function even if the declarator itself @@ -2250,39 +2269,41 @@ public: /// type. This routine checks for both cases. bool isDeclarationOfFunction() const; - /// \brief Return true if this declaration appears in a context where a + /// Return true if this declaration appears in a context where a /// function declarator would be a function declaration. bool isFunctionDeclarationContext() const { if (getDeclSpec().getStorageClassSpec() == DeclSpec::SCS_typedef) return false; switch (Context) { - case FileContext: - case MemberContext: - case BlockContext: - case ForContext: - case InitStmtContext: + case DeclaratorContext::FileContext: + case DeclaratorContext::MemberContext: + case DeclaratorContext::BlockContext: + case DeclaratorContext::ForContext: + case DeclaratorContext::InitStmtContext: return true; - case ConditionContext: - case KNRTypeListContext: - case TypeNameContext: - case FunctionalCastContext: - case AliasDeclContext: - case AliasTemplateContext: - case PrototypeContext: - case LambdaExprParameterContext: - case ObjCParameterContext: - case ObjCResultContext: - case TemplateParamContext: - case CXXNewContext: - case CXXCatchContext: - case ObjCCatchContext: - case BlockLiteralContext: - case LambdaExprContext: - case ConversionIdContext: - case TemplateTypeArgContext: - case TrailingReturnContext: + case DeclaratorContext::ConditionContext: + case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::TypeNameContext: + case DeclaratorContext::FunctionalCastContext: + case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::PrototypeContext: + case DeclaratorContext::LambdaExprParameterContext: + case DeclaratorContext::ObjCParameterContext: + case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::TemplateParamContext: + case DeclaratorContext::CXXNewContext: + case DeclaratorContext::CXXCatchContext: + case DeclaratorContext::ObjCCatchContext: + case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::TemplateArgContext: + case DeclaratorContext::TemplateTypeArgContext: + case DeclaratorContext::TrailingReturnContext: + case DeclaratorContext::TrailingReturnVarContext: return false; } llvm_unreachable("unknown context kind!"); @@ -2292,39 +2313,44 @@ public: /// expression could appear. bool isExpressionContext() const { switch (Context) { - case FileContext: - case KNRTypeListContext: - case MemberContext: - case TypeNameContext: // FIXME: sizeof(...) permits an expression. - case FunctionalCastContext: - case AliasDeclContext: - case AliasTemplateContext: - case PrototypeContext: - case LambdaExprParameterContext: - case ObjCParameterContext: - case ObjCResultContext: - case TemplateParamContext: - case CXXNewContext: - case CXXCatchContext: - case ObjCCatchContext: - case BlockLiteralContext: - case LambdaExprContext: - case ConversionIdContext: - case TrailingReturnContext: + case DeclaratorContext::FileContext: + case DeclaratorContext::KNRTypeListContext: + case DeclaratorContext::MemberContext: + + // FIXME: sizeof(...) permits an expression. + case DeclaratorContext::TypeNameContext: + + case DeclaratorContext::FunctionalCastContext: + case DeclaratorContext::AliasDeclContext: + case DeclaratorContext::AliasTemplateContext: + case DeclaratorContext::PrototypeContext: + case DeclaratorContext::LambdaExprParameterContext: + case DeclaratorContext::ObjCParameterContext: + case DeclaratorContext::ObjCResultContext: + case DeclaratorContext::TemplateParamContext: + case DeclaratorContext::CXXNewContext: + case DeclaratorContext::CXXCatchContext: + case DeclaratorContext::ObjCCatchContext: + case DeclaratorContext::BlockLiteralContext: + case DeclaratorContext::LambdaExprContext: + case DeclaratorContext::ConversionIdContext: + case DeclaratorContext::TrailingReturnContext: + case DeclaratorContext::TrailingReturnVarContext: + case DeclaratorContext::TemplateTypeArgContext: return false; - case BlockContext: - case ForContext: - case InitStmtContext: - case ConditionContext: - case TemplateTypeArgContext: + case DeclaratorContext::BlockContext: + case DeclaratorContext::ForContext: + case DeclaratorContext::InitStmtContext: + case DeclaratorContext::ConditionContext: + case DeclaratorContext::TemplateArgContext: return true; } llvm_unreachable("unknown context kind!"); } - /// \brief Return true if a function declarator at this position would be a + /// Return true if a function declarator at this position would be a /// function declaration. bool isFunctionDeclaratorAFunctionDeclaration() const { if (!isFunctionDeclarationContext()) @@ -2337,7 +2363,7 @@ public: return true; } - /// \brief Determine whether a trailing return type was written (at any + /// Determine whether a trailing return type was written (at any /// level) within this declarator. bool hasTrailingReturnType() const { for (const auto &Chunk : type_objects()) @@ -2363,29 +2389,25 @@ public: SetRangeEnd(lastLoc); } - const AttributeList *getAttributes() const { return Attrs.getList(); } - AttributeList *getAttributes() { return Attrs.getList(); } - - AttributeList *&getAttrListRef() { return Attrs.getListRef(); } + const ParsedAttributes &getAttributes() const { return Attrs; } + ParsedAttributes &getAttributes() { return Attrs; } /// hasAttributes - do we contain any attributes? bool hasAttributes() const { - if (getAttributes() || getDeclSpec().hasAttributes()) return true; + if (!getAttributes().empty() || getDeclSpec().hasAttributes()) + return true; for (unsigned i = 0, e = getNumTypeObjects(); i != e; ++i) - if (getTypeObject(i).getAttrs()) + if (!getTypeObject(i).getAttrs().empty()) return true; return false; } - /// \brief Return a source range list of C++11 attributes associated + /// Return a source range list of C++11 attributes associated /// with the declarator. void getCXX11AttributeRanges(SmallVectorImpl<SourceRange> &Ranges) { - AttributeList *AttrList = Attrs.getList(); - while (AttrList) { - if (AttrList->isCXX11Attribute()) - Ranges.push_back(AttrList->getRange()); - AttrList = AttrList->getNext(); - } + for (const ParsedAttr &AL : Attrs) + if (AL.isCXX11Attribute()) + Ranges.push_back(AL.getRange()); } void setAsmLabel(Expr *E) { AsmLabel = E; } @@ -2430,7 +2452,8 @@ public: /// Returns true if this declares a real member and not a friend. bool isFirstDeclarationOfMember() { - return getContext() == MemberContext && !getDeclSpec().isFriendSpecified(); + return getContext() == DeclaratorContext::MemberContext && + !getDeclSpec().isFriendSpecified(); } /// Returns true if this declares a static member. This cannot be called on a @@ -2445,16 +2468,17 @@ public: bool isRedeclaration() const { return Redeclaration; } }; -/// \brief This little struct is used to capture information about +/// This little struct is used to capture information about /// structure field declarators, which is basically just a bitfield size. struct FieldDeclarator { Declarator D; Expr *BitfieldSize; explicit FieldDeclarator(const DeclSpec &DS) - : D(DS, Declarator::MemberContext), BitfieldSize(nullptr) { } + : D(DS, DeclaratorContext::MemberContext), + BitfieldSize(nullptr) {} }; -/// \brief Represents a C++11 virt-specifier-seq. +/// Represents a C++11 virt-specifier-seq. class VirtSpecifiers { public: enum Specifier { @@ -2504,9 +2528,9 @@ enum class LambdaCaptureInitKind { ListInit //!< [a{b}] }; -/// \brief Represents a complete lambda introducer. +/// Represents a complete lambda introducer. struct LambdaIntroducer { - /// \brief An individual capture in a lambda introducer. + /// An individual capture in a lambda introducer. struct LambdaCapture { LambdaCaptureKind Kind; SourceLocation Loc; @@ -2515,12 +2539,16 @@ struct LambdaIntroducer { LambdaCaptureInitKind InitKind; ExprResult Init; ParsedType InitCaptureType; + SourceRange ExplicitRange; + LambdaCapture(LambdaCaptureKind Kind, SourceLocation Loc, IdentifierInfo *Id, SourceLocation EllipsisLoc, LambdaCaptureInitKind InitKind, ExprResult Init, - ParsedType InitCaptureType) + ParsedType InitCaptureType, + SourceRange ExplicitRange) : Kind(Kind), Loc(Loc), Id(Id), EllipsisLoc(EllipsisLoc), - InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType) {} + InitKind(InitKind), Init(Init), InitCaptureType(InitCaptureType), + ExplicitRange(ExplicitRange) {} }; SourceRange Range; @@ -2531,16 +2559,17 @@ struct LambdaIntroducer { LambdaIntroducer() : Default(LCD_None) {} - /// \brief Append a capture in a lambda introducer. + /// Append a capture in a lambda introducer. void addCapture(LambdaCaptureKind Kind, SourceLocation Loc, IdentifierInfo* Id, SourceLocation EllipsisLoc, LambdaCaptureInitKind InitKind, ExprResult Init, - ParsedType InitCaptureType) { + ParsedType InitCaptureType, + SourceRange ExplicitRange) { Captures.push_back(LambdaCapture(Kind, Loc, Id, EllipsisLoc, InitKind, Init, - InitCaptureType)); + InitCaptureType, ExplicitRange)); } }; diff --git a/include/clang/Sema/DelayedDiagnostic.h b/include/clang/Sema/DelayedDiagnostic.h index d65dbf0cd34e0..76aa4546d749a 100644 --- a/include/clang/Sema/DelayedDiagnostic.h +++ b/include/clang/Sema/DelayedDiagnostic.h @@ -1,4 +1,4 @@ -//===--- DelayedDiagnostic.h - Delayed declarator diagnostics ---*- C++ -*-===// +//===- DelayedDiagnostic.h - Delayed declarator diagnostics -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -6,9 +6,9 @@ // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// -/// +// /// \file -/// \brief Defines the classes clang::DelayedDiagnostic and +/// Defines the classes clang::DelayedDiagnostic and /// clang::AccessedEntity. /// /// DelayedDiangostic is used to record diagnostics that are being @@ -16,15 +16,34 @@ /// diagnostics -- notably deprecation and access control -- are suppressed /// based on semantic properties of the parsed declaration that aren't known /// until it is fully parsed. -/// +// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H #define LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstddef> +#include <utility> namespace clang { + +class ObjCInterfaceDecl; +class ObjCPropertyDecl; + namespace sema { /// A declaration being accessed, together with information about how @@ -39,16 +58,14 @@ public: /// The target is the base class. enum BaseNonce { Base }; - bool isMemberAccess() const { return IsMember; } - AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator, MemberNonce _, CXXRecordDecl *NamingClass, DeclAccessPair FoundDecl, QualType BaseObjectType) - : Access(FoundDecl.getAccess()), IsMember(true), - Target(FoundDecl.getDecl()), NamingClass(NamingClass), - BaseObjectType(BaseObjectType), Diag(0, Allocator) { + : Access(FoundDecl.getAccess()), IsMember(true), + Target(FoundDecl.getDecl()), NamingClass(NamingClass), + BaseObjectType(BaseObjectType), Diag(0, Allocator) { } AccessedEntity(PartialDiagnostic::StorageAllocator &Allocator, @@ -56,11 +73,10 @@ public: CXXRecordDecl *BaseClass, CXXRecordDecl *DerivedClass, AccessSpecifier Access) - : Access(Access), IsMember(false), - Target(BaseClass), - NamingClass(DerivedClass), - Diag(0, Allocator) { - } + : Access(Access), IsMember(false), Target(BaseClass), + NamingClass(DerivedClass), Diag(0, Allocator) {} + + bool isMemberAccess() const { return IsMember; } bool isQuiet() const { return Diag.getDiagID() == 0; } @@ -123,7 +139,7 @@ public: void Destroy(); static DelayedDiagnostic makeAvailability(AvailabilityResult AR, - SourceLocation Loc, + ArrayRef<SourceLocation> Locs, const NamedDecl *ReferringDecl, const NamedDecl *OffendingDecl, const ObjCInterfaceDecl *UnknownObjCClass, @@ -131,7 +147,6 @@ public: StringRef Msg, bool ObjCPropertyAccess); - static DelayedDiagnostic makeAccess(SourceLocation Loc, const AccessedEntity &Entity) { DelayedDiagnostic DD; @@ -179,6 +194,12 @@ public: return StringRef(AvailabilityData.Message, AvailabilityData.MessageLen); } + ArrayRef<SourceLocation> getAvailabilitySelectorLocs() const { + assert(Kind == Availability && "Not an availability diagnostic."); + return llvm::makeArrayRef(AvailabilityData.SelectorLocs, + AvailabilityData.NumSelectorLocs); + } + AvailabilityResult getAvailabilityResult() const { assert(Kind == Availability && "Not an availability diagnostic."); return AvailabilityData.AR; @@ -216,7 +237,6 @@ public: } private: - struct AD { const NamedDecl *ReferringDecl; const NamedDecl *OffendingDecl; @@ -224,6 +244,8 @@ private: const ObjCPropertyDecl *ObjCProperty; const char *Message; size_t MessageLen; + SourceLocation *SelectorLocs; + size_t NumSelectorLocs; AvailabilityResult AR; bool ObjCPropertyAccess; }; @@ -243,25 +265,22 @@ private: }; }; -/// \brief A collection of diagnostics which were delayed. +/// A collection of diagnostics which were delayed. class DelayedDiagnosticPool { const DelayedDiagnosticPool *Parent; SmallVector<DelayedDiagnostic, 4> Diagnostics; - DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete; - void operator=(const DelayedDiagnosticPool &) = delete; public: DelayedDiagnosticPool(const DelayedDiagnosticPool *parent) : Parent(parent) {} - ~DelayedDiagnosticPool() { - for (SmallVectorImpl<DelayedDiagnostic>::iterator - i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i) - i->Destroy(); - } + + DelayedDiagnosticPool(const DelayedDiagnosticPool &) = delete; + DelayedDiagnosticPool &operator=(const DelayedDiagnosticPool &) = delete; DelayedDiagnosticPool(DelayedDiagnosticPool &&Other) - : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) { + : Parent(Other.Parent), Diagnostics(std::move(Other.Diagnostics)) { Other.Diagnostics.clear(); } + DelayedDiagnosticPool &operator=(DelayedDiagnosticPool &&Other) { Parent = Other.Parent; Diagnostics = std::move(Other.Diagnostics); @@ -269,6 +288,12 @@ public: return *this; } + ~DelayedDiagnosticPool() { + for (SmallVectorImpl<DelayedDiagnostic>::iterator + i = Diagnostics.begin(), e = Diagnostics.end(); i != e; ++i) + i->Destroy(); + } + const DelayedDiagnosticPool *getParent() const { return Parent; } /// Does this pool, or any of its ancestors, contain any diagnostics? @@ -293,13 +318,14 @@ public: pool.Diagnostics.clear(); } - typedef SmallVectorImpl<DelayedDiagnostic>::const_iterator pool_iterator; + using pool_iterator = SmallVectorImpl<DelayedDiagnostic>::const_iterator; + pool_iterator pool_begin() const { return Diagnostics.begin(); } pool_iterator pool_end() const { return Diagnostics.end(); } bool pool_empty() const { return Diagnostics.empty(); } }; -} +} // namespace clang /// Add a diagnostic to the current delay pool. inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) { @@ -307,7 +333,6 @@ inline void Sema::DelayedDiagnostics::add(const sema::DelayedDiagnostic &diag) { CurPool->add(diag); } +} // namespace clang -} - -#endif +#endif // LLVM_CLANG_SEMA_DELAYEDDIAGNOSTIC_H diff --git a/include/clang/Sema/ExternalSemaSource.h b/include/clang/Sema/ExternalSemaSource.h index c5cb7b12b3f18..42754b33e2df2 100644 --- a/include/clang/Sema/ExternalSemaSource.h +++ b/include/clang/Sema/ExternalSemaSource.h @@ -39,7 +39,7 @@ class ValueDecl; class VarDecl; struct LateParsedTemplate; -/// \brief A simple structure that captures a vtable use for the purposes of +/// A simple structure that captures a vtable use for the purposes of /// the \c ExternalSemaSource. struct ExternalVTableUse { CXXRecordDecl *Record; @@ -47,7 +47,7 @@ struct ExternalVTableUse { bool DefinitionRequired; }; -/// \brief An abstract interface that should be implemented by +/// An abstract interface that should be implemented by /// external AST sources that also provide information for semantic /// analysis. class ExternalSemaSource : public ExternalASTSource { @@ -58,15 +58,15 @@ public: ~ExternalSemaSource() override; - /// \brief Initialize the semantic source with the Sema instance + /// Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. virtual void InitializeSema(Sema &S) {} - /// \brief Inform the semantic consumer that Sema is no longer available. + /// Inform the semantic consumer that Sema is no longer available. virtual void ForgetSema() {} - /// \brief Load the contents of the global method pool for a given + /// Load the contents of the global method pool for a given /// selector. virtual void ReadMethodPool(Selector Sel); @@ -74,12 +74,12 @@ public: /// selector if necessary. virtual void updateOutOfDateSelector(Selector Sel); - /// \brief Load the set of namespaces that are known to the external source, + /// Load the set of namespaces that are known to the external source, /// which will be used during typo correction. virtual void ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces); - /// \brief Load the set of used but not defined functions or variables with + /// Load the set of used but not defined functions or variables with /// internal linkage, or used but not defined internal functions. virtual void ReadUndefinedButUsed(llvm::MapVector<NamedDecl *, SourceLocation> &Undefined); @@ -87,7 +87,7 @@ public: virtual void ReadMismatchingDeleteExpressions(llvm::MapVector< FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> &); - /// \brief Do last resort, unqualified lookup on a LookupResult that + /// Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. /// /// \param R a LookupResult that is being recovered. @@ -97,7 +97,7 @@ public: /// \return true to tell Sema to recover using the LookupResult. virtual bool LookupUnqualified(LookupResult &R, Scope *S) { return false; } - /// \brief Read the set of tentative definitions known to the external Sema + /// Read the set of tentative definitions known to the external Sema /// source. /// /// The external source should append its own tentative definitions to the @@ -107,7 +107,7 @@ public: virtual void ReadTentativeDefinitions( SmallVectorImpl<VarDecl *> &TentativeDefs) {} - /// \brief Read the set of unused file-scope declarations known to the + /// Read the set of unused file-scope declarations known to the /// external Sema source. /// /// The external source should append its own unused, filed-scope to the @@ -117,7 +117,7 @@ public: virtual void ReadUnusedFileScopedDecls( SmallVectorImpl<const DeclaratorDecl *> &Decls) {} - /// \brief Read the set of delegating constructors known to the + /// Read the set of delegating constructors known to the /// external Sema source. /// /// The external source should append its own delegating constructors to the @@ -127,7 +127,7 @@ public: virtual void ReadDelegatingConstructors( SmallVectorImpl<CXXConstructorDecl *> &Decls) {} - /// \brief Read the set of ext_vector type declarations known to the + /// Read the set of ext_vector type declarations known to the /// external Sema source. /// /// The external source should append its own ext_vector type declarations to @@ -136,7 +136,7 @@ public: /// introduce the same declarations repeatedly. virtual void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl *> &Decls) {} - /// \brief Read the set of potentially unused typedefs known to the source. + /// 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 @@ -145,7 +145,7 @@ public: virtual void ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) {} - /// \brief Read the set of referenced selectors known to the + /// Read the set of referenced selectors known to the /// external Sema source. /// /// The external source should append its own referenced selectors to the @@ -155,7 +155,7 @@ public: virtual void ReadReferencedSelectors( SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) {} - /// \brief Read the set of weak, undeclared identifiers known to the + /// Read the set of weak, undeclared identifiers known to the /// external Sema source. /// /// The external source should append its own weak, undeclared identifiers to @@ -165,14 +165,14 @@ public: virtual void ReadWeakUndeclaredIdentifiers( SmallVectorImpl<std::pair<IdentifierInfo *, WeakInfo> > &WI) {} - /// \brief Read the set of used vtables known to the external Sema source. + /// Read the set of used vtables known to the external Sema source. /// /// The external source should append its own used vtables to the given /// vector. Note that this routine may be invoked multiple times; the external /// source should take care not to introduce the same vtables repeatedly. virtual void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) {} - /// \brief Read the set of pending instantiations known to the external + /// Read the set of pending instantiations known to the external /// Sema source. /// /// The external source should append its own pending instantiations to the @@ -183,7 +183,7 @@ public: SmallVectorImpl<std::pair<ValueDecl *, SourceLocation> > &Pending) {} - /// \brief Read the set of late parsed template functions for this source. + /// Read the set of late parsed template functions for this source. /// /// The external source should insert its own late parsed template functions /// into the map. Note that this routine may be invoked multiple times; the @@ -209,7 +209,7 @@ public: return TypoCorrection(); } - /// \brief Produces a diagnostic note if the external source contains a + /// Produces a diagnostic note if the external source contains a /// complete definition for \p T. /// /// \param Loc the location at which a complete type was required but not diff --git a/include/clang/Sema/IdentifierResolver.h b/include/clang/Sema/IdentifierResolver.h index 382fe80bea7da..ea6c3df74af0b 100644 --- a/include/clang/Sema/IdentifierResolver.h +++ b/include/clang/Sema/IdentifierResolver.h @@ -15,16 +15,20 @@ #ifndef LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H #define LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H -#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/SmallVector.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <iterator> namespace clang { -class ASTContext; class Decl; -class DeclContext; class DeclarationName; -class ExternalPreprocessorSource; +class DeclContext; +class IdentifierInfo; +class LangOptions; class NamedDecl; class Preprocessor; class Scope; @@ -33,17 +37,16 @@ class Scope; /// scopes. It manages the shadowing chains of declaration names and /// implements efficient decl lookup based on a declaration name. class IdentifierResolver { - /// IdDeclInfo - Keeps track of information about decls associated /// to a particular declaration name. IdDeclInfos are lazily /// constructed and assigned to a declaration name the first time a /// decl with that declaration name is shadowed in some scope. class IdDeclInfo { public: - typedef SmallVector<NamedDecl*, 2> DeclsTy; + using DeclsTy = SmallVector<NamedDecl *, 2>; - inline DeclsTy::iterator decls_begin() { return Decls.begin(); } - inline DeclsTy::iterator decls_end() { return Decls.end(); } + DeclsTy::iterator decls_begin() { return Decls.begin(); } + DeclsTy::iterator decls_end() { return Decls.end(); } void AddDecl(NamedDecl *D) { Decls.push_back(D); } @@ -51,7 +54,7 @@ class IdentifierResolver { /// The decl must already be part of the decl chain. void RemoveDecl(NamedDecl *D); - /// \brief Insert the given declaration at the given position in the list. + /// Insert the given declaration at the given position in the list. void InsertDecl(DeclsTy::iterator Pos, NamedDecl *D) { Decls.insert(Pos, D); } @@ -61,30 +64,32 @@ class IdentifierResolver { }; public: - /// iterator - Iterate over the decls of a specified declaration name. /// It will walk or not the parent declaration contexts depending on how /// it was instantiated. class iterator { public: - typedef NamedDecl * value_type; - typedef NamedDecl * reference; - typedef NamedDecl * pointer; - typedef std::input_iterator_tag iterator_category; - typedef std::ptrdiff_t difference_type; + friend class IdentifierResolver; + + using value_type = NamedDecl *; + using reference = NamedDecl *; + using pointer = NamedDecl *; + using iterator_category = std::input_iterator_tag; + using difference_type = std::ptrdiff_t; /// Ptr - There are 2 forms that 'Ptr' represents: /// 1) A single NamedDecl. (Ptr & 0x1 == 0) /// 2) A IdDeclInfo::DeclsTy::iterator that traverses only the decls of the /// same declaration context. (Ptr & 0x1 == 0x1) - uintptr_t Ptr; - typedef IdDeclInfo::DeclsTy::iterator BaseIter; + uintptr_t Ptr = 0; + using BaseIter = IdDeclInfo::DeclsTy::iterator; /// A single NamedDecl. (Ptr & 0x1 == 0) iterator(NamedDecl *D) { Ptr = reinterpret_cast<uintptr_t>(D); assert((Ptr & 0x1) == 0 && "Invalid Ptr!"); } + /// A IdDeclInfo::DeclsTy::iterator that walks or not the parent declaration /// contexts depending on 'LookInParentCtx'. iterator(BaseIter I) { @@ -98,11 +103,10 @@ public: return reinterpret_cast<BaseIter>(Ptr & ~0x1); } - friend class IdentifierResolver; - void incrementSlowCase(); + public: - iterator() : Ptr(0) {} + iterator() = default; NamedDecl *operator*() const { if (isIterator()) @@ -128,6 +132,9 @@ public: } }; + explicit IdentifierResolver(Preprocessor &PP); + ~IdentifierResolver(); + /// begin - Returns an iterator for decls with the name 'Name'. iterator begin(DeclarationName Name); @@ -156,11 +163,11 @@ public: /// The decl must already be part of the decl chain. void RemoveDecl(NamedDecl *D); - /// \brief Insert the given declaration after the given iterator + /// Insert the given declaration after the given iterator /// position. void InsertDeclAfter(iterator Pos, NamedDecl *D); - /// \brief Try to add the given declaration to the top level scope, if it + /// Try to add the given declaration to the top level scope, if it /// (or a redeclaration of it) hasn't already been added. /// /// \param D The externally-produced declaration to add. @@ -170,9 +177,6 @@ public: /// \returns true if the declaration was added, false otherwise. bool tryAddTopLevelDecl(NamedDecl *D, DeclarationName Name); - explicit IdentifierResolver(Preprocessor &PP); - ~IdentifierResolver(); - private: const LangOptions &LangOpt; Preprocessor &PP; @@ -193,11 +197,10 @@ private: assert((reinterpret_cast<uintptr_t>(Ptr) & 0x1) == 1 && "Ptr not a IdDeclInfo* !"); return reinterpret_cast<IdDeclInfo*>( - reinterpret_cast<uintptr_t>(Ptr) & ~0x1 - ); + reinterpret_cast<uintptr_t>(Ptr) & ~0x1); } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_IDENTIFIERRESOLVER_H diff --git a/include/clang/Sema/Initialization.h b/include/clang/Sema/Initialization.h index bd07b9ea9aeeb..7a510f391bda4 100644 --- a/include/clang/Sema/Initialization.h +++ b/include/clang/Sema/Initialization.h @@ -1,4 +1,4 @@ -//===--- Initialization.h - Semantic Analysis for Initializers --*- C++ -*-===// +//===- Initialization.h - Semantic Analysis for Initializers ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -10,85 +10,115 @@ // This file provides supporting data types for initialization of objects. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SEMA_INITIALIZATION_H #define LLVM_CLANG_SEMA_INITIALIZATION_H #include "clang/AST/ASTContext.h" #include "clang/AST/Attr.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" #include "clang/AST/Type.h" -#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/Overload.h" #include "clang/Sema/Ownership.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Casting.h" #include <cassert> +#include <cstdint> +#include <string> namespace clang { - + +class APValue; class CXXBaseSpecifier; -class DeclaratorDecl; -class DeclaratorInfo; -class FieldDecl; -class FunctionDecl; -class ParmVarDecl; -class Sema; -class TypeLoc; -class VarDecl; +class CXXConstructorDecl; class ObjCMethodDecl; - -/// \brief Describes an entity that is being initialized. -class InitializedEntity { +class Sema; + +/// Describes an entity that is being initialized. +class alignas(8) InitializedEntity { public: - /// \brief Specifies the kind of entity being initialized. + /// Specifies the kind of entity being initialized. enum EntityKind { - /// \brief The entity being initialized is a variable. + /// The entity being initialized is a variable. EK_Variable, - /// \brief The entity being initialized is a function parameter. + + /// The entity being initialized is a function parameter. EK_Parameter, - /// \brief The entity being initialized is the result of a function call. + + /// The entity being initialized is the result of a function call. EK_Result, - /// \brief The entity being initialized is an exception object that + + /// The entity being initialized is the result of a statement expression. + EK_StmtExprResult, + + /// The entity being initialized is an exception object that /// is being thrown. EK_Exception, - /// \brief The entity being initialized is a non-static data member + + /// The entity being initialized is a non-static data member /// subobject. EK_Member, - /// \brief The entity being initialized is an element of an array. + + /// The entity being initialized is an element of an array. EK_ArrayElement, - /// \brief The entity being initialized is an object (or array of + + /// The entity being initialized is an object (or array of /// objects) allocated via new. EK_New, - /// \brief The entity being initialized is a temporary object. + + /// The entity being initialized is a temporary object. EK_Temporary, - /// \brief The entity being initialized is a base member subobject. + + /// The entity being initialized is a base member subobject. EK_Base, - /// \brief The initialization is being done by a delegating constructor. + + /// The initialization is being done by a delegating constructor. EK_Delegating, - /// \brief The entity being initialized is an element of a vector. + + /// The entity being initialized is an element of a vector. /// or vector. EK_VectorElement, - /// \brief The entity being initialized is a field of block descriptor for + + /// The entity being initialized is a field of block descriptor for /// the copied-in c++ object. EK_BlockElement, + /// The entity being initialized is a field of block descriptor for the /// copied-in lambda object that's used in the lambda to block conversion. EK_LambdaToBlockConversionBlockElement, - /// \brief The entity being initialized is the real or imaginary part of a + + /// The entity being initialized is the real or imaginary part of a /// complex number. EK_ComplexElement, - /// \brief The entity being initialized is the field that captures a + + /// The entity being initialized is the field that captures a /// variable in a lambda. EK_LambdaCapture, - /// \brief The entity being initialized is the initializer for a compound + + /// The entity being initialized is the initializer for a compound /// literal. EK_CompoundLiteralInit, - /// \brief The entity being implicitly initialized back to the formal + + /// The entity being implicitly initialized back to the formal /// result type. EK_RelatedResult, - /// \brief The entity being initialized is a function parameter; function + + /// The entity being initialized is a function parameter; function /// is member of group of audited CF APIs. EK_Parameter_CF_Audited, - /// \brief The entity being initialized is a structured binding of a + + /// The entity being initialized is a structured binding of a /// decomposition declaration. EK_Binding, @@ -96,75 +126,79 @@ public: // enum as an index for its first %select. When modifying this list, // that diagnostic text needs to be updated as well. }; - + private: - /// \brief The kind of entity being initialized. + /// The kind of entity being initialized. EntityKind Kind; - /// \brief If non-NULL, the parent entity in which this + /// If non-NULL, the parent entity in which this /// initialization occurs. - const InitializedEntity *Parent; + const InitializedEntity *Parent = nullptr; - /// \brief The type of the object or reference being initialized. + /// The type of the object or reference being initialized. QualType Type; - /// \brief The mangling number for the next reference temporary to be created. - mutable unsigned ManglingNumber; + /// The mangling number for the next reference temporary to be created. + mutable unsigned ManglingNumber = 0; struct LN { - /// \brief When Kind == EK_Result, EK_Exception, EK_New, the + /// When Kind == EK_Result, EK_Exception, EK_New, the /// location of the 'return', 'throw', or 'new' keyword, /// respectively. When Kind == EK_Temporary, the location where /// the temporary is being created. unsigned Location; - /// \brief Whether the entity being initialized may end up using the + /// Whether the entity being initialized may end up using the /// named return value optimization (NRVO). bool NRVO; }; struct VD { - /// \brief The VarDecl, FieldDecl, or BindingDecl being initialized. + /// The VarDecl, FieldDecl, or BindingDecl being initialized. ValueDecl *VariableOrMember; - /// \brief When Kind == EK_Member, whether this is an implicit member + /// When Kind == EK_Member, whether this is an implicit member /// initialization in a copy or move constructor. These can perform array /// copies. bool IsImplicitFieldInit; + + /// When Kind == EK_Member, whether this is the initial initialization + /// check for a default member initializer. + bool IsDefaultMemberInit; }; struct C { - /// \brief The name of the variable being captured by an EK_LambdaCapture. + /// The name of the variable being captured by an EK_LambdaCapture. IdentifierInfo *VarID; - /// \brief The source location at which the capture occurs. + /// The source location at which the capture occurs. unsigned Location; }; union { - /// \brief When Kind == EK_Variable, EK_Member or EK_Binding, the variable. + /// When Kind == EK_Variable, EK_Member or EK_Binding, the variable. VD Variable; - /// \brief When Kind == EK_RelatedResult, the ObjectiveC method where + /// When Kind == EK_RelatedResult, the ObjectiveC method where /// result type was implicitly changed to accommodate ARC semantics. ObjCMethodDecl *MethodDecl; - /// \brief When Kind == EK_Parameter, the ParmVarDecl, with the + /// When Kind == EK_Parameter, the ParmVarDecl, with the /// low bit indicating whether the parameter is "consumed". uintptr_t Parameter; - /// \brief When Kind == EK_Temporary or EK_CompoundLiteralInit, the type + /// When Kind == EK_Temporary or EK_CompoundLiteralInit, the type /// source information for the temporary. TypeSourceInfo *TypeInfo; struct LN LocAndNRVO; - /// \brief When Kind == EK_Base, the base specifier that provides the + /// When Kind == EK_Base, the base specifier that provides the /// base class. The lower bit specifies whether the base is an inherited /// virtual base. uintptr_t Base; - /// \brief When Kind == EK_ArrayElement, EK_VectorElement, or + /// When Kind == EK_ArrayElement, EK_VectorElement, or /// EK_ComplexElement, the index of the array or vector element being /// initialized. unsigned Index; @@ -172,57 +206,52 @@ private: struct C Capture; }; - InitializedEntity() : ManglingNumber(0) {} + InitializedEntity() = default; - /// \brief Create the initialization entity for a variable. + /// Create the initialization entity for a variable. InitializedEntity(VarDecl *Var, EntityKind EK = EK_Variable) - : Kind(EK), Parent(nullptr), Type(Var->getType()), - ManglingNumber(0), Variable{Var, false} { } + : Kind(EK), Type(Var->getType()), Variable{Var, false, false} {} - /// \brief Create the initialization entity for the result of a + /// Create the initialization entity for the result of a /// function, throwing an object, performing an explicit cast, or /// initializing a parameter for which there is no declaration. InitializedEntity(EntityKind Kind, SourceLocation Loc, QualType Type, bool NRVO = false) - : Kind(Kind), Parent(nullptr), Type(Type), ManglingNumber(0) - { + : Kind(Kind), Type(Type) { LocAndNRVO.Location = Loc.getRawEncoding(); LocAndNRVO.NRVO = NRVO; } - /// \brief Create the initialization entity for a member subobject. + /// Create the initialization entity for a member subobject. InitializedEntity(FieldDecl *Member, const InitializedEntity *Parent, - bool Implicit) - : Kind(EK_Member), Parent(Parent), Type(Member->getType()), - ManglingNumber(0), Variable{Member, Implicit} { - } + bool Implicit, bool DefaultMemberInit) + : Kind(EK_Member), Parent(Parent), Type(Member->getType()), + Variable{Member, Implicit, DefaultMemberInit} {} - /// \brief Create the initialization entity for an array element. + /// Create the initialization entity for an array element. InitializedEntity(ASTContext &Context, unsigned Index, const InitializedEntity &Parent); - /// \brief Create the initialization entity for a lambda capture. + /// Create the initialization entity for a lambda capture. InitializedEntity(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc) - : Kind(EK_LambdaCapture), Parent(nullptr), Type(FieldType), - ManglingNumber(0) - { + : Kind(EK_LambdaCapture), Type(FieldType) { Capture.VarID = VarID; Capture.Location = Loc.getRawEncoding(); } public: - /// \brief Create the initialization entity for a variable. + /// Create the initialization entity for a variable. static InitializedEntity InitializeVariable(VarDecl *Var) { return InitializedEntity(Var); } - /// \brief Create the initialization entity for a parameter. + /// Create the initialization entity for a parameter. static InitializedEntity InitializeParameter(ASTContext &Context, const ParmVarDecl *Parm) { return InitializeParameter(Context, Parm, Parm->getType()); } - /// \brief Create the initialization entity for a parameter, but use + /// Create the initialization entity for a parameter, but use /// another type. static InitializedEntity InitializeParameter(ASTContext &Context, const ParmVarDecl *Parm, @@ -240,7 +269,7 @@ public: return Entity; } - /// \brief Create the initialization entity for a parameter that is + /// Create the initialization entity for a parameter that is /// only known by its type. static InitializedEntity InitializeParameter(ASTContext &Context, QualType Type, @@ -253,12 +282,17 @@ public: return Entity; } - /// \brief Create the initialization entity for the result of a function. + /// Create the initialization entity for the result of a function. static InitializedEntity InitializeResult(SourceLocation ReturnLoc, QualType Type, bool NRVO) { return InitializedEntity(EK_Result, ReturnLoc, Type, NRVO); } + static InitializedEntity InitializeStmtExprResult(SourceLocation ReturnLoc, + QualType Type) { + return InitializedEntity(EK_StmtExprResult, ReturnLoc, Type); + } + static InitializedEntity InitializeBlock(SourceLocation BlockVarLoc, QualType Type, bool NRVO) { return InitializedEntity(EK_BlockElement, BlockVarLoc, Type, NRVO); @@ -270,28 +304,28 @@ public: BlockVarLoc, Type, NRVO); } - /// \brief Create the initialization entity for an exception object. + /// Create the initialization entity for an exception object. static InitializedEntity InitializeException(SourceLocation ThrowLoc, QualType Type, bool NRVO) { return InitializedEntity(EK_Exception, ThrowLoc, Type, NRVO); } - /// \brief Create the initialization entity for an object allocated via new. + /// Create the initialization entity for an object allocated via new. static InitializedEntity InitializeNew(SourceLocation NewLoc, QualType Type) { return InitializedEntity(EK_New, NewLoc, Type); } - /// \brief Create the initialization entity for a temporary. + /// Create the initialization entity for a temporary. static InitializedEntity InitializeTemporary(QualType Type) { return InitializeTemporary(nullptr, Type); } - /// \brief Create the initialization entity for a temporary. + /// Create the initialization entity for a temporary. static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo) { return InitializeTemporary(TypeInfo, TypeInfo->getType()); } - /// \brief Create the initialization entity for a temporary. + /// Create the initialization entity for a temporary. static InitializedEntity InitializeTemporary(TypeSourceInfo *TypeInfo, QualType Type) { InitializedEntity Result(EK_Temporary, SourceLocation(), Type); @@ -299,7 +333,7 @@ public: return Result; } - /// \brief Create the initialization entity for a related result. + /// Create the initialization entity for a related result. static InitializedEntity InitializeRelatedResult(ObjCMethodDecl *MD, QualType Type) { InitializedEntity Result(EK_RelatedResult, SourceLocation(), Type); @@ -307,54 +341,59 @@ public: return Result; } - - /// \brief Create the initialization entity for a base class subobject. + /// Create the initialization entity for a base class subobject. static InitializedEntity InitializeBase(ASTContext &Context, const CXXBaseSpecifier *Base, bool IsInheritedVirtualBase, const InitializedEntity *Parent = nullptr); - /// \brief Create the initialization entity for a delegated constructor. + /// Create the initialization entity for a delegated constructor. static InitializedEntity InitializeDelegation(QualType Type) { return InitializedEntity(EK_Delegating, SourceLocation(), Type); } - - /// \brief Create the initialization entity for a member subobject. + + /// Create the initialization entity for a member subobject. static InitializedEntity InitializeMember(FieldDecl *Member, const InitializedEntity *Parent = nullptr, bool Implicit = false) { - return InitializedEntity(Member, Parent, Implicit); + return InitializedEntity(Member, Parent, Implicit, false); } - - /// \brief Create the initialization entity for a member subobject. + + /// Create the initialization entity for a member subobject. static InitializedEntity InitializeMember(IndirectFieldDecl *Member, const InitializedEntity *Parent = nullptr, bool Implicit = false) { - return InitializedEntity(Member->getAnonField(), Parent, Implicit); + return InitializedEntity(Member->getAnonField(), Parent, Implicit, false); } - /// \brief Create the initialization entity for an array element. + /// Create the initialization entity for a default member initializer. + static InitializedEntity + InitializeMemberFromDefaultMemberInitializer(FieldDecl *Member) { + return InitializedEntity(Member, nullptr, false, true); + } + + /// Create the initialization entity for an array element. static InitializedEntity InitializeElement(ASTContext &Context, unsigned Index, const InitializedEntity &Parent) { return InitializedEntity(Context, Index, Parent); } - /// \brief Create the initialization entity for a structured binding. + /// Create the initialization entity for a structured binding. static InitializedEntity InitializeBinding(VarDecl *Binding) { return InitializedEntity(Binding, EK_Binding); } - /// \brief Create the initialization entity for a lambda capture. + /// Create the initialization entity for a lambda capture. static InitializedEntity InitializeLambdaCapture(IdentifierInfo *VarID, QualType FieldType, SourceLocation Loc) { return InitializedEntity(VarID, FieldType, Loc); } - /// \brief Create the entity for a compound literal initializer. + /// Create the entity for a compound literal initializer. static InitializedEntity InitializeCompoundLiteralInit(TypeSourceInfo *TSI) { InitializedEntity Result(EK_CompoundLiteralInit, SourceLocation(), TSI->getType()); @@ -362,19 +401,18 @@ public: return Result; } - - /// \brief Determine the kind of initialization. + /// Determine the kind of initialization. EntityKind getKind() const { return Kind; } - /// \brief Retrieve the parent of the entity being initialized, when + /// Retrieve the parent of the entity being initialized, when /// the initialization itself is occurring within the context of a /// larger initialization. const InitializedEntity *getParent() const { return Parent; } - /// \brief Retrieve type being initialized. + /// Retrieve type being initialized. QualType getType() const { return Type; } - /// \brief Retrieve complete type-source information for the object being + /// Retrieve complete type-source information for the object being /// constructed, if known. TypeSourceInfo *getTypeSourceInfo() const { if (Kind == EK_Temporary || Kind == EK_CompoundLiteralInit) @@ -383,17 +421,17 @@ public: return nullptr; } - /// \brief Retrieve the name of the entity being initialized. + /// Retrieve the name of the entity being initialized. DeclarationName getName() const; - /// \brief Retrieve the variable, parameter, or field being + /// Retrieve the variable, parameter, or field being /// initialized. ValueDecl *getDecl() const; - /// \brief Retrieve the ObjectiveC method being initialized. + /// Retrieve the ObjectiveC method being initialized. ObjCMethodDecl *getMethodDecl() const { return MethodDecl; } - /// \brief Determine whether this initialization allows the named return + /// Determine whether this initialization allows the named return /// value optimization, which also applies to thrown objects. bool allowsNRVO() const; @@ -401,71 +439,81 @@ public: return (getKind() == EK_Parameter || getKind() == EK_Parameter_CF_Audited); } - /// \brief Determine whether this initialization consumes the + + /// Determine whether this initialization consumes the /// parameter. bool isParameterConsumed() const { assert(isParameterKind() && "Not a parameter"); return (Parameter & 1); } - /// \brief Retrieve the base specifier. + /// Retrieve the base specifier. const CXXBaseSpecifier *getBaseSpecifier() const { assert(getKind() == EK_Base && "Not a base specifier"); return reinterpret_cast<const CXXBaseSpecifier *>(Base & ~0x1); } - /// \brief Return whether the base is an inherited virtual base. + /// Return whether the base is an inherited virtual base. bool isInheritedVirtualBase() const { assert(getKind() == EK_Base && "Not a base specifier"); return Base & 0x1; } - /// \brief Determine whether this is an array new with an unknown bound. + /// Determine whether this is an array new with an unknown bound. bool isVariableLengthArrayNew() const { return getKind() == EK_New && dyn_cast_or_null<IncompleteArrayType>( getType()->getAsArrayTypeUnsafe()); } - /// \brief Is this the implicit initialization of a member of a class from + /// Is this the implicit initialization of a member of a class from /// a defaulted constructor? bool isImplicitMemberInitializer() const { return getKind() == EK_Member && Variable.IsImplicitFieldInit; } - /// \brief Determine the location of the 'return' keyword when initializing + /// Is this the default member initializer of a member (specified inside + /// the class definition)? + bool isDefaultMemberInitializer() const { + return getKind() == EK_Member && Variable.IsDefaultMemberInit; + } + + /// Determine the location of the 'return' keyword when initializing /// the result of a function call. SourceLocation getReturnLoc() const { assert(getKind() == EK_Result && "No 'return' location!"); return SourceLocation::getFromRawEncoding(LocAndNRVO.Location); } - /// \brief Determine the location of the 'throw' keyword when initializing + /// Determine the location of the 'throw' keyword when initializing /// an exception object. SourceLocation getThrowLoc() const { assert(getKind() == EK_Exception && "No 'throw' location!"); return SourceLocation::getFromRawEncoding(LocAndNRVO.Location); } - /// \brief If this is an array, vector, or complex number element, get the + /// If this is an array, vector, or complex number element, get the /// element's index. unsigned getElementIndex() const { assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement || getKind() == EK_ComplexElement); return Index; } - /// \brief If this is already the initializer for an array or vector + + /// If this is already the initializer for an array or vector /// element, sets the element index. void setElementIndex(unsigned Index) { assert(getKind() == EK_ArrayElement || getKind() == EK_VectorElement || getKind() == EK_ComplexElement); this->Index = Index; } - /// \brief For a lambda capture, return the capture's name. + + /// For a lambda capture, return the capture's name. StringRef getCapturedVarName() const { assert(getKind() == EK_LambdaCapture && "Not a lambda capture!"); return Capture.VarID->getName(); } - /// \brief Determine the location of the capture when initializing + + /// Determine the location of the capture when initializing /// field from a captured variable in a lambda. SourceLocation getCaptureLoc() const { assert(getKind() == EK_LambdaCapture && "Not a lambda capture!"); @@ -486,51 +534,70 @@ private: unsigned dumpImpl(raw_ostream &OS) const; }; -/// \brief Describes the kind of initialization being performed, along with +/// Describes the kind of initialization being performed, along with /// location information for tokens related to the initialization (equal sign, /// parentheses). class InitializationKind { public: - /// \brief The kind of initialization being performed. + /// The kind of initialization being performed. enum InitKind { - IK_Direct, ///< Direct initialization - IK_DirectList, ///< Direct list-initialization - IK_Copy, ///< Copy initialization - IK_Default, ///< Default initialization - IK_Value ///< Value initialization + /// Direct initialization + IK_Direct, + + /// Direct list-initialization + IK_DirectList, + + /// Copy initialization + IK_Copy, + + /// Default initialization + IK_Default, + + /// Value initialization + IK_Value }; private: - /// \brief The context of the initialization. + /// The context of the initialization. enum InitContext { - IC_Normal, ///< Normal context - IC_ExplicitConvs, ///< Normal context, but allows explicit conversion funcs - IC_Implicit, ///< Implicit context (value initialization) - IC_StaticCast, ///< Static cast context - IC_CStyleCast, ///< C-style cast context - IC_FunctionalCast ///< Functional cast context + /// Normal context + IC_Normal, + + /// Normal context, but allows explicit conversion functionss + IC_ExplicitConvs, + + /// Implicit context (value initialization) + IC_Implicit, + + /// Static cast context + IC_StaticCast, + + /// C-style cast context + IC_CStyleCast, + + /// Functional cast context + IC_FunctionalCast }; - /// \brief The kind of initialization being performed. + /// The kind of initialization being performed. InitKind Kind : 8; - /// \brief The context of the initialization. + /// The context of the initialization. InitContext Context : 8; - /// \brief The source locations involved in the initialization. + /// The source locations involved in the initialization. SourceLocation Locations[3]; InitializationKind(InitKind Kind, InitContext Context, SourceLocation Loc1, SourceLocation Loc2, SourceLocation Loc3) - : Kind(Kind), Context(Context) - { + : Kind(Kind), Context(Context) { Locations[0] = Loc1; Locations[1] = Loc2; Locations[2] = Loc3; } public: - /// \brief Create a direct initialization. + /// Create a direct initialization. static InitializationKind CreateDirect(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc) { @@ -539,18 +606,25 @@ public: } static InitializationKind CreateDirectList(SourceLocation InitLoc) { - return InitializationKind(IK_DirectList, IC_Normal, - InitLoc, InitLoc, InitLoc); + return InitializationKind(IK_DirectList, IC_Normal, InitLoc, InitLoc, + InitLoc); } - /// \brief Create a direct initialization due to a cast that isn't a C-style + static InitializationKind CreateDirectList(SourceLocation InitLoc, + SourceLocation LBraceLoc, + SourceLocation RBraceLoc) { + return InitializationKind(IK_DirectList, IC_Normal, InitLoc, LBraceLoc, + RBraceLoc); + } + + /// Create a direct initialization due to a cast that isn't a C-style /// or functional cast. static InitializationKind CreateCast(SourceRange TypeRange) { return InitializationKind(IK_Direct, IC_StaticCast, TypeRange.getBegin(), TypeRange.getBegin(), TypeRange.getEnd()); } - /// \brief Create a direct initialization for a C-style cast. + /// Create a direct initialization for a C-style cast. static InitializationKind CreateCStyleCast(SourceLocation StartLoc, SourceRange TypeRange, bool InitList) { @@ -561,7 +635,7 @@ public: TypeRange.getEnd()); } - /// \brief Create a direct initialization for a functional cast. + /// Create a direct initialization for a functional cast. static InitializationKind CreateFunctionalCast(SourceRange TypeRange, bool InitList) { return InitializationKind(InitList ? IK_DirectList : IK_Direct, @@ -569,7 +643,7 @@ public: TypeRange.getBegin(), TypeRange.getEnd()); } - /// \brief Create a copy initialization. + /// Create a copy initialization. static InitializationKind CreateCopy(SourceLocation InitLoc, SourceLocation EqualLoc, bool AllowExplicitConvs = false) { @@ -578,12 +652,12 @@ public: InitLoc, EqualLoc, EqualLoc); } - /// \brief Create a default initialization. + /// Create a default initialization. static InitializationKind CreateDefault(SourceLocation InitLoc) { return InitializationKind(IK_Default, IC_Normal, InitLoc, InitLoc, InitLoc); } - /// \brief Create a value initialization. + /// Create a value initialization. static InitializationKind CreateValue(SourceLocation InitLoc, SourceLocation LParenLoc, SourceLocation RParenLoc, @@ -592,55 +666,56 @@ public: InitLoc, LParenLoc, RParenLoc); } - /// \brief Create an initialization from an initializer (which, for direct + /// Create an initialization from an initializer (which, for direct /// initialization from a parenthesized list, will be a ParenListExpr). static InitializationKind CreateForInit(SourceLocation Loc, bool DirectInit, Expr *Init) { if (!Init) return CreateDefault(Loc); if (!DirectInit) return CreateCopy(Loc, Init->getLocStart()); - if (isa<InitListExpr>(Init)) return CreateDirectList(Loc); + if (isa<InitListExpr>(Init)) + return CreateDirectList(Loc, Init->getLocStart(), Init->getLocEnd()); return CreateDirect(Loc, Init->getLocStart(), Init->getLocEnd()); } - /// \brief Determine the initialization kind. + /// Determine the initialization kind. InitKind getKind() const { return Kind; } - /// \brief Determine whether this initialization is an explicit cast. + /// Determine whether this initialization is an explicit cast. bool isExplicitCast() const { return Context >= IC_StaticCast; } - /// \brief Determine whether this initialization is a C-style cast. + /// Determine whether this initialization is a C-style cast. bool isCStyleOrFunctionalCast() const { return Context >= IC_CStyleCast; } - /// \brief Determine whether this is a C-style cast. + /// Determine whether this is a C-style cast. bool isCStyleCast() const { return Context == IC_CStyleCast; } - /// \brief Determine whether this is a functional-style cast. + /// Determine whether this is a functional-style cast. bool isFunctionalCast() const { return Context == IC_FunctionalCast; } - /// \brief Determine whether this initialization is an implicit + /// Determine whether this initialization is an implicit /// value-initialization, e.g., as occurs during aggregate /// initialization. bool isImplicitValueInit() const { return Context == IC_Implicit; } - /// \brief Retrieve the location at which initialization is occurring. + /// Retrieve the location at which initialization is occurring. SourceLocation getLocation() const { return Locations[0]; } - /// \brief Retrieve the source range that covers the initialization. + /// Retrieve the source range that covers the initialization. SourceRange getRange() const { return SourceRange(Locations[0], Locations[2]); } - /// \brief Retrieve the location of the equal sign for copy initialization + /// Retrieve the location of the equal sign for copy initialization /// (if present). SourceLocation getEqualLoc() const { assert(Kind == IK_Copy && "Only copy initialization has an '='"); @@ -649,143 +724,188 @@ public: bool isCopyInit() const { return Kind == IK_Copy; } - /// \brief Retrieve whether this initialization allows the use of explicit + /// Retrieve whether this initialization allows the use of explicit /// constructors. bool AllowExplicit() const { return !isCopyInit(); } - /// \brief Retrieve whether this initialization allows the use of explicit + /// Retrieve whether this initialization allows the use of explicit /// conversion functions when binding a reference. If the reference is the /// first parameter in a copy or move constructor, such conversions are /// permitted even though we are performing copy-initialization. bool allowExplicitConversionFunctionsInRefBinding() const { return !isCopyInit() || Context == IC_ExplicitConvs; } + + /// Determine whether this initialization has a source range containing the + /// locations of open and closing parentheses or braces. + bool hasParenOrBraceRange() const { + return Kind == IK_Direct || Kind == IK_Value || Kind == IK_DirectList; + } - /// \brief Retrieve the source range containing the locations of the open - /// and closing parentheses for value and direct initializations. - SourceRange getParenRange() const { - assert((Kind == IK_Direct || Kind == IK_Value) && - "Only direct- and value-initialization have parentheses"); + /// Retrieve the source range containing the locations of the open + /// and closing parentheses or braces for value, direct, and direct list + /// initializations. + SourceRange getParenOrBraceRange() const { + assert(hasParenOrBraceRange() && "Only direct, value, and direct-list " + "initialization have parentheses or " + "braces"); return SourceRange(Locations[1], Locations[2]); } }; -/// \brief Describes the sequence of initializations required to initialize +/// Describes the sequence of initializations required to initialize /// a given object or reference with a set of arguments. class InitializationSequence { public: - /// \brief Describes the kind of initialization sequence computed. + /// Describes the kind of initialization sequence computed. enum SequenceKind { - /// \brief A failed initialization sequence. The failure kind tells what + /// A failed initialization sequence. The failure kind tells what /// happened. FailedSequence = 0, - /// \brief A dependent initialization, which could not be + /// A dependent initialization, which could not be /// type-checked due to the presence of dependent types or /// dependently-typed expressions. DependentSequence, - /// \brief A normal sequence. + /// A normal sequence. NormalSequence }; - /// \brief Describes the kind of a particular step in an initialization + /// Describes the kind of a particular step in an initialization /// sequence. enum StepKind { - /// \brief Resolve the address of an overloaded function to a specific + /// Resolve the address of an overloaded function to a specific /// function declaration. SK_ResolveAddressOfOverloadedFunction, - /// \brief Perform a derived-to-base cast, producing an rvalue. + + /// Perform a derived-to-base cast, producing an rvalue. SK_CastDerivedToBaseRValue, - /// \brief Perform a derived-to-base cast, producing an xvalue. + + /// Perform a derived-to-base cast, producing an xvalue. SK_CastDerivedToBaseXValue, - /// \brief Perform a derived-to-base cast, producing an lvalue. + + /// Perform a derived-to-base cast, producing an lvalue. SK_CastDerivedToBaseLValue, - /// \brief Reference binding to an lvalue. + + /// Reference binding to an lvalue. SK_BindReference, - /// \brief Reference binding to a temporary. + + /// Reference binding to a temporary. SK_BindReferenceToTemporary, - /// \brief An optional copy of a temporary object to another + + /// An optional copy of a temporary object to another /// temporary object, which is permitted (but not required) by /// C++98/03 but not C++0x. SK_ExtraneousCopyToTemporary, - /// \brief Direct-initialization from a reference-related object in the + + /// Direct-initialization from a reference-related object in the /// final stage of class copy-initialization. SK_FinalCopy, - /// \brief Perform a user-defined conversion, either via a conversion + + /// Perform a user-defined conversion, either via a conversion /// function or via a constructor. SK_UserConversion, - /// \brief Perform a qualification conversion, producing an rvalue. + + /// Perform a qualification conversion, producing an rvalue. SK_QualificationConversionRValue, - /// \brief Perform a qualification conversion, producing an xvalue. + + /// Perform a qualification conversion, producing an xvalue. SK_QualificationConversionXValue, - /// \brief Perform a qualification conversion, producing an lvalue. + + /// Perform a qualification conversion, producing an lvalue. SK_QualificationConversionLValue, - /// \brief Perform a conversion adding _Atomic to a type. + + /// Perform a conversion adding _Atomic to a type. SK_AtomicConversion, - /// \brief Perform a load from a glvalue, producing an rvalue. + + /// Perform a load from a glvalue, producing an rvalue. SK_LValueToRValue, - /// \brief Perform an implicit conversion sequence. + + /// Perform an implicit conversion sequence. SK_ConversionSequence, - /// \brief Perform an implicit conversion sequence without narrowing. + + /// Perform an implicit conversion sequence without narrowing. SK_ConversionSequenceNoNarrowing, - /// \brief Perform list-initialization without a constructor. + + /// Perform list-initialization without a constructor. SK_ListInitialization, - /// \brief Unwrap the single-element initializer list for a reference. + + /// Unwrap the single-element initializer list for a reference. SK_UnwrapInitList, - /// \brief Rewrap the single-element initializer list for a reference. + + /// Rewrap the single-element initializer list for a reference. SK_RewrapInitList, - /// \brief Perform initialization via a constructor. + + /// Perform initialization via a constructor. SK_ConstructorInitialization, - /// \brief Perform initialization via a constructor, taking arguments from + + /// Perform initialization via a constructor, taking arguments from /// a single InitListExpr. SK_ConstructorInitializationFromList, - /// \brief Zero-initialize the object + + /// Zero-initialize the object SK_ZeroInitialization, - /// \brief C assignment + + /// C assignment SK_CAssignment, - /// \brief Initialization by string + + /// Initialization by string SK_StringInit, - /// \brief An initialization that "converts" an Objective-C object + + /// An initialization that "converts" an Objective-C object /// (not a point to an object) to another Objective-C object type. SK_ObjCObjectConversion, - /// \brief Array indexing for initialization by elementwise copy. + + /// Array indexing for initialization by elementwise copy. SK_ArrayLoopIndex, - /// \brief Array initialization by elementwise copy. + + /// Array initialization by elementwise copy. SK_ArrayLoopInit, - /// \brief Array initialization (from an array rvalue). + + /// Array initialization (from an array rvalue). SK_ArrayInit, - /// \brief Array initialization (from an array rvalue) as a GNU extension. + + /// Array initialization (from an array rvalue) as a GNU extension. SK_GNUArrayInit, - /// \brief Array initialization from a parenthesized initializer list. + + /// Array initialization from a parenthesized initializer list. /// This is a GNU C++ extension. SK_ParenthesizedArrayInit, - /// \brief Pass an object by indirect copy-and-restore. + + /// Pass an object by indirect copy-and-restore. SK_PassByIndirectCopyRestore, - /// \brief Pass an object by indirect restore. + + /// Pass an object by indirect restore. SK_PassByIndirectRestore, - /// \brief Produce an Objective-C object pointer. + + /// Produce an Objective-C object pointer. SK_ProduceObjCObject, - /// \brief Construct a std::initializer_list from an initializer list. + + /// Construct a std::initializer_list from an initializer list. SK_StdInitializerList, - /// \brief Perform initialization via a constructor taking a single + + /// Perform initialization via a constructor taking a single /// std::initializer_list argument. SK_StdInitializerListConstructorCall, - /// \brief Initialize an OpenCL sampler from an integer. + + /// Initialize an OpenCL sampler from an integer. SK_OCLSamplerInit, - /// \brief Initialize queue_t from 0. + + /// Initialize queue_t from 0. SK_OCLZeroQueue, - /// \brief Passing zero to a function where OpenCL event_t is expected. + + /// Passing zero to a function where OpenCL event_t is expected. SK_OCLZeroEvent }; - /// \brief A single step in the initialization sequence. + /// A single step in the initialization sequence. class Step { public: - /// \brief The kind of conversion or initialization step we are taking. + /// The kind of conversion or initialization step we are taking. StepKind Kind; - // \brief The type that results from this initialization. + // The type that results from this initialization. QualType Type; struct F { @@ -795,7 +915,7 @@ public: }; union { - /// \brief When Kind == SK_ResolvedOverloadedFunction or Kind == + /// When Kind == SK_ResolvedOverloadedFunction or Kind == /// SK_UserConversion, the function that the expression should be /// resolved to or the conversion function to call, respectively. /// When Kind == SK_ConstructorInitialization or SK_ListConstruction, @@ -807,11 +927,11 @@ public: /// For construct decls, the naming class is the target type. struct F Function; - /// \brief When Kind = SK_ConversionSequence, the implicit conversion + /// When Kind = SK_ConversionSequence, the implicit conversion /// sequence. ImplicitConversionSequence *ICS; - /// \brief When Kind = SK_RewrapInitList, the syntactic form of the + /// When Kind = SK_RewrapInitList, the syntactic form of the /// wrapping list. InitListExpr *WrappingSyntacticList; }; @@ -820,114 +940,154 @@ public: }; private: - /// \brief The kind of initialization sequence computed. + /// The kind of initialization sequence computed. enum SequenceKind SequenceKind; - /// \brief Steps taken by this initialization. + /// Steps taken by this initialization. SmallVector<Step, 4> Steps; public: - /// \brief Describes why initialization failed. + /// Describes why initialization failed. enum FailureKind { - /// \brief Too many initializers provided for a reference. + /// Too many initializers provided for a reference. FK_TooManyInitsForReference, - /// \brief Reference initialized from a parenthesized initializer list. + + /// Reference initialized from a parenthesized initializer list. FK_ParenthesizedListInitForReference, - /// \brief Array must be initialized with an initializer list. + + /// Array must be initialized with an initializer list. FK_ArrayNeedsInitList, - /// \brief Array must be initialized with an initializer list or a + + /// Array must be initialized with an initializer list or a /// string literal. FK_ArrayNeedsInitListOrStringLiteral, - /// \brief Array must be initialized with an initializer list or a + + /// Array must be initialized with an initializer list or a /// wide string literal. FK_ArrayNeedsInitListOrWideStringLiteral, - /// \brief Initializing a wide char array with narrow string literal. + + /// Initializing a wide char array with narrow string literal. FK_NarrowStringIntoWideCharArray, - /// \brief Initializing char array with wide string literal. + + /// Initializing char array with wide string literal. FK_WideStringIntoCharArray, - /// \brief Initializing wide char array with incompatible wide string + + /// Initializing wide char array with incompatible wide string /// literal. FK_IncompatWideStringIntoWideChar, - /// \brief Array type mismatch. + + /// Initializing char8_t array with plain string literal. + FK_PlainStringIntoUTF8Char, + + /// Initializing char array with UTF-8 string literal. + FK_UTF8StringIntoPlainChar, + + /// Array type mismatch. FK_ArrayTypeMismatch, - /// \brief Non-constant array initializer + + /// Non-constant array initializer FK_NonConstantArrayInit, - /// \brief Cannot resolve the address of an overloaded function. + + /// Cannot resolve the address of an overloaded function. FK_AddressOfOverloadFailed, - /// \brief Overloading due to reference initialization failed. + + /// Overloading due to reference initialization failed. FK_ReferenceInitOverloadFailed, - /// \brief Non-const lvalue reference binding to a temporary. + + /// Non-const lvalue reference binding to a temporary. FK_NonConstLValueReferenceBindingToTemporary, - /// \brief Non-const lvalue reference binding to a bit-field. + + /// Non-const lvalue reference binding to a bit-field. FK_NonConstLValueReferenceBindingToBitfield, - /// \brief Non-const lvalue reference binding to a vector element. + + /// Non-const lvalue reference binding to a vector element. FK_NonConstLValueReferenceBindingToVectorElement, - /// \brief Non-const lvalue reference binding to an lvalue of unrelated + + /// Non-const lvalue reference binding to an lvalue of unrelated /// type. FK_NonConstLValueReferenceBindingToUnrelated, - /// \brief Rvalue reference binding to an lvalue. + + /// Rvalue reference binding to an lvalue. FK_RValueReferenceBindingToLValue, - /// \brief Reference binding drops qualifiers. + + /// Reference binding drops qualifiers. FK_ReferenceInitDropsQualifiers, - /// \brief Reference binding failed. + + /// Reference binding failed. FK_ReferenceInitFailed, - /// \brief Implicit conversion failed. + + /// Implicit conversion failed. FK_ConversionFailed, - /// \brief Implicit conversion failed. + + /// Implicit conversion failed. FK_ConversionFromPropertyFailed, - /// \brief Too many initializers for scalar + + /// Too many initializers for scalar FK_TooManyInitsForScalar, - /// \brief Scalar initialized from a parenthesized initializer list. + + /// Scalar initialized from a parenthesized initializer list. FK_ParenthesizedListInitForScalar, - /// \brief Reference initialization from an initializer list + + /// Reference initialization from an initializer list FK_ReferenceBindingToInitList, - /// \brief Initialization of some unused destination type with an + + /// Initialization of some unused destination type with an /// initializer list. FK_InitListBadDestinationType, - /// \brief Overloading for a user-defined conversion failed. + + /// Overloading for a user-defined conversion failed. FK_UserConversionOverloadFailed, - /// \brief Overloading for initialization by constructor failed. + + /// Overloading for initialization by constructor failed. FK_ConstructorOverloadFailed, - /// \brief Overloading for list-initialization by constructor failed. + + /// Overloading for list-initialization by constructor failed. FK_ListConstructorOverloadFailed, - /// \brief Default-initialization of a 'const' object. + + /// Default-initialization of a 'const' object. FK_DefaultInitOfConst, - /// \brief Initialization of an incomplete type. + + /// Initialization of an incomplete type. FK_Incomplete, - /// \brief Variable-length array must not have an initializer. + + /// Variable-length array must not have an initializer. FK_VariableLengthArrayHasInitializer, - /// \brief List initialization failed at some point. + + /// List initialization failed at some point. FK_ListInitializationFailed, - /// \brief Initializer has a placeholder type which cannot be + + /// Initializer has a placeholder type which cannot be /// resolved by initialization. FK_PlaceholderType, - /// \brief Trying to take the address of a function that doesn't support + + /// Trying to take the address of a function that doesn't support /// having its address taken. FK_AddressOfUnaddressableFunction, - /// \brief List-copy-initialization chose an explicit constructor. + + /// List-copy-initialization chose an explicit constructor. FK_ExplicitConstructor, }; private: - /// \brief The reason why initialization failed. + /// The reason why initialization failed. FailureKind Failure; - /// \brief The failed result of overload resolution. + /// The failed result of overload resolution. OverloadingResult FailedOverloadResult; - /// \brief The candidate set created when initialization failed. + /// The candidate set created when initialization failed. OverloadCandidateSet FailedCandidateSet; - /// \brief The incomplete type that caused a failure. + /// The incomplete type that caused a failure. QualType FailedIncompleteType; - /// \brief The fixit that needs to be applied to make this initialization + /// The fixit that needs to be applied to make this initialization /// succeed. std::string ZeroInitializationFixit; SourceLocation ZeroInitializationFixitLoc; public: - /// \brief Call for initializations are invalid but that would be valid + /// Call for initializations are invalid but that would be valid /// zero initialzations if Fixit was applied. void SetZeroInitializationFixit(const std::string& Fixit, SourceLocation L) { ZeroInitializationFixit = Fixit; @@ -935,13 +1095,12 @@ public: } private: - - /// \brief Prints a follow-up note that highlights the location of + /// Prints a follow-up note that highlights the location of /// the initialized entity, if it's remote. void PrintInitLocationNote(Sema &S, const InitializedEntity &Entity); public: - /// \brief Try to perform initialization of the given entity, creating a + /// Try to perform initialization of the given entity, creating a /// record of the steps required to perform the initialization. /// /// The generated initialization sequence will either contain enough @@ -972,7 +1131,7 @@ public: ~InitializationSequence(); - /// \brief Perform the actual initialization of the given entity based on + /// Perform the actual initialization of the given entity based on /// the computed initialization sequence. /// /// \param S the semantic analysis object. @@ -999,7 +1158,7 @@ public: MultiExprArg Args, QualType *ResultType = nullptr); - /// \brief Diagnose an potentially-invalid initialization sequence. + /// Diagnose an potentially-invalid initialization sequence. /// /// \returns true if the initialization sequence was ill-formed, /// false otherwise. @@ -1008,37 +1167,39 @@ public: const InitializationKind &Kind, ArrayRef<Expr *> Args); - /// \brief Determine the kind of initialization sequence computed. + /// Determine the kind of initialization sequence computed. enum SequenceKind getKind() const { return SequenceKind; } - /// \brief Set the kind of sequence computed. + /// Set the kind of sequence computed. void setSequenceKind(enum SequenceKind SK) { SequenceKind = SK; } - /// \brief Determine whether the initialization sequence is valid. + /// Determine whether the initialization sequence is valid. explicit operator bool() const { return !Failed(); } - /// \brief Determine whether the initialization sequence is invalid. + /// Determine whether the initialization sequence is invalid. bool Failed() const { return SequenceKind == FailedSequence; } - typedef SmallVectorImpl<Step>::const_iterator step_iterator; + using step_iterator = SmallVectorImpl<Step>::const_iterator; + step_iterator step_begin() const { return Steps.begin(); } step_iterator step_end() const { return Steps.end(); } - typedef llvm::iterator_range<step_iterator> step_range; + using step_range = llvm::iterator_range<step_iterator>; + step_range steps() const { return {step_begin(), step_end()}; } - /// \brief Determine whether this initialization is a direct reference + /// Determine whether this initialization is a direct reference /// binding (C++ [dcl.init.ref]). bool isDirectReferenceBinding() const; - /// \brief Determine whether this initialization failed due to an ambiguity. + /// Determine whether this initialization failed due to an ambiguity. bool isAmbiguous() const; - /// \brief Determine whether this initialization is direct call to a + /// Determine whether this initialization is direct call to a /// constructor. bool isConstructorInitialization() const; - /// \brief Returns whether the last step in this initialization sequence is a + /// Returns whether the last step in this initialization sequence is a /// narrowing conversion, defined by C++0x [dcl.init.list]p7. /// /// If this function returns true, *isInitializerConstant will be set to @@ -1049,7 +1210,7 @@ public: bool *isInitializerConstant, APValue *ConstantValue) const; - /// \brief Add a new step in the initialization that resolves the address + /// Add a new step in the initialization that resolves the address /// of an overloaded function to a specific function declaration. /// /// \param Function the function to which the overloaded function reference @@ -1058,7 +1219,7 @@ public: DeclAccessPair Found, bool HadMultipleCandidates); - /// \brief Add a new step in the initialization that performs a derived-to- + /// Add a new step in the initialization that performs a derived-to- /// base cast. /// /// \param BaseType the base type to which we will be casting. @@ -1068,14 +1229,14 @@ public: void AddDerivedToBaseCastStep(QualType BaseType, ExprValueKind Category); - /// \brief Add a new step binding a reference to an object. + /// Add a new step binding a reference to an object. /// /// \param BindingTemporary True if we are binding a reference to a temporary /// object (thereby extending its lifetime); false if we are binding to an /// lvalue or an lvalue treated as an rvalue. void AddReferenceBindingStep(QualType T, bool BindingTemporary); - /// \brief Add a new step that makes an extraneous copy of the input + /// Add a new step that makes an extraneous copy of the input /// to a temporary of the same class type. /// /// This extraneous copy only occurs during reference binding in @@ -1087,40 +1248,40 @@ public: /// \param T The type of the temporary being created. void AddExtraneousCopyToTemporary(QualType T); - /// \brief Add a new step that makes a copy of the input to an object of + /// Add a new step that makes a copy of the input to an object of /// the given type, as the final step in class copy-initialization. void AddFinalCopy(QualType T); - /// \brief Add a new step invoking a conversion function, which is either + /// Add a new step invoking a conversion function, which is either /// a constructor or a conversion function. void AddUserConversionStep(FunctionDecl *Function, DeclAccessPair FoundDecl, QualType T, bool HadMultipleCandidates); - /// \brief Add a new step that performs a qualification conversion to the + /// Add a new step that performs a qualification conversion to the /// given type. void AddQualificationConversionStep(QualType Ty, ExprValueKind Category); - /// \brief Add a new step that performs conversion from non-atomic to atomic + /// Add a new step that performs conversion from non-atomic to atomic /// type. void AddAtomicConversionStep(QualType Ty); - /// \brief Add a new step that performs a load of the given type. + /// Add a new step that performs a load of the given type. /// /// Although the term "LValueToRValue" is conventional, this applies to both /// lvalues and xvalues. void AddLValueToRValueStep(QualType Ty); - /// \brief Add a new step that applies an implicit conversion sequence. + /// Add a new step that applies an implicit conversion sequence. void AddConversionSequenceStep(const ImplicitConversionSequence &ICS, QualType T, bool TopLevelOfInitList = false); - /// \brief Add a list-initialization step. + /// Add a list-initialization step. void AddListInitializationStep(QualType T); - /// \brief Add a constructor-initialization step. + /// Add a constructor-initialization step. /// /// \param FromInitList The constructor call is syntactically an initializer /// list. @@ -1131,59 +1292,59 @@ public: bool HadMultipleCandidates, bool FromInitList, bool AsInitList); - /// \brief Add a zero-initialization step. + /// Add a zero-initialization step. void AddZeroInitializationStep(QualType T); - /// \brief Add a C assignment step. + /// Add a C assignment step. // // FIXME: It isn't clear whether this should ever be needed; // ideally, we would handle everything needed in C in the common // path. However, that isn't the case yet. void AddCAssignmentStep(QualType T); - /// \brief Add a string init step. + /// Add a string init step. void AddStringInitStep(QualType T); - /// \brief Add an Objective-C object conversion step, which is + /// Add an Objective-C object conversion step, which is /// always a no-op. void AddObjCObjectConversionStep(QualType T); - /// \brief Add an array initialization loop step. + /// Add an array initialization loop step. void AddArrayInitLoopStep(QualType T, QualType EltTy); - /// \brief Add an array initialization step. + /// Add an array initialization step. void AddArrayInitStep(QualType T, bool IsGNUExtension); - /// \brief Add a parenthesized array initialization step. + /// Add a parenthesized array initialization step. void AddParenthesizedArrayInitStep(QualType T); - /// \brief Add a step to pass an object by indirect copy-restore. + /// Add a step to pass an object by indirect copy-restore. void AddPassByIndirectCopyRestoreStep(QualType T, bool shouldCopy); - /// \brief Add a step to "produce" an Objective-C object (by + /// Add a step to "produce" an Objective-C object (by /// retaining it). void AddProduceObjCObjectStep(QualType T); - /// \brief Add a step to construct a std::initializer_list object from an + /// Add a step to construct a std::initializer_list object from an /// initializer list. void AddStdInitializerListConstructionStep(QualType T); - /// \brief Add a step to initialize an OpenCL sampler from an integer + /// Add a step to initialize an OpenCL sampler from an integer /// constant. void AddOCLSamplerInitStep(QualType T); - /// \brief Add a step to initialize an OpenCL event_t from a NULL + /// Add a step to initialize an OpenCL event_t from a NULL /// constant. void AddOCLZeroEventStep(QualType T); - /// \brief Add a step to initialize an OpenCL queue_t from 0. + /// Add a step to initialize an OpenCL queue_t from 0. void AddOCLZeroQueueStep(QualType T); - /// \brief Add steps to unwrap a initializer list for a reference around a + /// Add steps to unwrap a initializer list for a reference around a /// single element and rewrap it at the end. void RewrapReferenceInitList(QualType T, InitListExpr *Syntactic); - /// \brief Note that this initialization sequence failed. + /// Note that this initialization sequence failed. void SetFailed(FailureKind Failure) { SequenceKind = FailedSequence; this->Failure = Failure; @@ -1191,44 +1352,44 @@ public: "Incomplete type failure requires a type!"); } - /// \brief Note that this initialization sequence failed due to failed + /// Note that this initialization sequence failed due to failed /// overload resolution. void SetOverloadFailure(FailureKind Failure, OverloadingResult Result); - /// \brief Retrieve a reference to the candidate set when overload + /// Retrieve a reference to the candidate set when overload /// resolution fails. OverloadCandidateSet &getFailedCandidateSet() { return FailedCandidateSet; } - /// \brief Get the overloading result, for when the initialization + /// Get the overloading result, for when the initialization /// sequence failed due to a bad overload. OverloadingResult getFailedOverloadResult() const { return FailedOverloadResult; } - /// \brief Note that this initialization sequence failed due to an + /// Note that this initialization sequence failed due to an /// incomplete type. void setIncompleteTypeFailure(QualType IncompleteType) { FailedIncompleteType = IncompleteType; SetFailed(FK_Incomplete); } - /// \brief Determine why initialization failed. + /// Determine why initialization failed. FailureKind getFailureKind() const { assert(Failed() && "Not an initialization failure!"); return Failure; } - /// \brief Dump a representation of this initialization sequence to + /// Dump a representation of this initialization sequence to /// the given stream, for debugging purposes. void dump(raw_ostream &OS) const; - /// \brief Dump a representation of this initialization sequence to + /// Dump a representation of this initialization sequence to /// standard error, for debugging purposes. void dump() const; }; -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_SEMA_INITIALIZATION_H diff --git a/include/clang/Sema/Lookup.h b/include/clang/Sema/Lookup.h index 546df8842a356..c06952064dd9e 100644 --- a/include/clang/Sema/Lookup.h +++ b/include/clang/Sema/Lookup.h @@ -1,4 +1,4 @@ -//===--- Lookup.h - Classes for name lookup ---------------------*- C++ -*-===// +//===- Lookup.h - Classes for name lookup -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,14 +15,29 @@ #ifndef LLVM_CLANG_SEMA_LOOKUP_H #define LLVM_CLANG_SEMA_LOOKUP_H +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Type.h" +#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" +#include "clang/Basic/SourceLocation.h" +#include "clang/Basic/Specifiers.h" #include "clang/Sema/Sema.h" - +#include "llvm/ADT/MapVector.h" #include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <utility> namespace clang { -/// @brief Represents the results of name lookup. +class CXXBasePaths; + +/// Represents the results of name lookup. /// /// An instance of the LookupResult class captures the results of a /// single name lookup, which can return no result (nothing found), @@ -32,28 +47,28 @@ namespace clang { class LookupResult { public: enum LookupResultKind { - /// @brief No entity found met the criteria. + /// No entity found met the criteria. NotFound = 0, - /// @brief No entity found met the criteria within the current + /// No entity found met the criteria within the current /// instantiation,, but there were dependent base classes of the /// current instantiation that could not be searched. NotFoundInCurrentInstantiation, - /// @brief Name lookup found a single declaration that met the + /// Name lookup found a single declaration that met the /// criteria. getFoundDecl() will return this declaration. Found, - /// @brief Name lookup found a set of overloaded functions that + /// Name lookup found a set of overloaded functions that /// met the criteria. FoundOverloaded, - /// @brief Name lookup found an unresolvable value declaration + /// Name lookup found an unresolvable value declaration /// and cannot yet complete. This only happens in C++ dependent /// contexts with dependent using declarations. FoundUnresolvedValue, - /// @brief Name lookup results in an ambiguity; use + /// Name lookup results in an ambiguity; use /// getAmbiguityKind to figure out what kind of ambiguity /// we have. Ambiguous @@ -126,25 +141,15 @@ public: Temporary }; - typedef UnresolvedSetImpl::iterator iterator; + using iterator = UnresolvedSetImpl::iterator; LookupResult(Sema &SemaRef, const DeclarationNameInfo &NameInfo, Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) - : ResultKind(NotFound), - Paths(nullptr), - NamingClass(nullptr), - SemaPtr(&SemaRef), - NameInfo(NameInfo), - LookupKind(LookupKind), - IDNS(0), - Redecl(Redecl != Sema::NotForRedeclaration), - ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), - HideTags(true), - Diagnose(Redecl == Sema::NotForRedeclaration), - AllowHidden(false), - Shadowed(false) - { + : SemaPtr(&SemaRef), NameInfo(NameInfo), LookupKind(LookupKind), + Redecl(Redecl != Sema::NotForRedeclaration), + ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), + Diagnose(Redecl == Sema::NotForRedeclaration) { configure(); } @@ -154,20 +159,10 @@ public: LookupResult(Sema &SemaRef, DeclarationName Name, SourceLocation NameLoc, Sema::LookupNameKind LookupKind, Sema::RedeclarationKind Redecl = Sema::NotForRedeclaration) - : ResultKind(NotFound), - Paths(nullptr), - NamingClass(nullptr), - SemaPtr(&SemaRef), - NameInfo(Name, NameLoc), - LookupKind(LookupKind), - IDNS(0), - Redecl(Redecl != Sema::NotForRedeclaration), - ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), - HideTags(true), - Diagnose(Redecl == Sema::NotForRedeclaration), - AllowHidden(false), - Shadowed(false) - { + : SemaPtr(&SemaRef), NameInfo(Name, NameLoc), LookupKind(LookupKind), + Redecl(Redecl != Sema::NotForRedeclaration), + ExternalRedecl(Redecl == Sema::ForExternalRedeclaration), + Diagnose(Redecl == Sema::NotForRedeclaration) { configure(); } @@ -175,20 +170,10 @@ public: /// using the information from another result. Diagnostics are always /// disabled. LookupResult(TemporaryToken _, const LookupResult &Other) - : ResultKind(NotFound), - Paths(nullptr), - NamingClass(nullptr), - SemaPtr(Other.SemaPtr), - NameInfo(Other.NameInfo), - LookupKind(Other.LookupKind), - IDNS(Other.IDNS), - Redecl(Other.Redecl), - ExternalRedecl(Other.ExternalRedecl), - HideTags(Other.HideTags), - Diagnose(false), - AllowHidden(Other.AllowHidden), - Shadowed(false) - {} + : SemaPtr(Other.SemaPtr), NameInfo(Other.NameInfo), + LookupKind(Other.LookupKind), IDNS(Other.IDNS), Redecl(Other.Redecl), + ExternalRedecl(Other.ExternalRedecl), HideTags(Other.HideTags), + AllowHidden(Other.AllowHidden) {} // FIXME: Remove these deleted methods once the default build includes // -Wdeprecated. @@ -213,6 +198,7 @@ public: Other.Paths = nullptr; Other.Diagnose = false; } + LookupResult &operator=(LookupResult &&Other) { ResultKind = std::move(Other.ResultKind); Ambiguity = std::move(Other.Ambiguity); @@ -246,7 +232,7 @@ public: return NameInfo; } - /// \brief Sets the name info to look up. + /// Sets the name info to look up. void setLookupNameInfo(const DeclarationNameInfo &NameInfo) { this->NameInfo = NameInfo; } @@ -256,7 +242,7 @@ public: return NameInfo.getName(); } - /// \brief Sets the name to look up. + /// Sets the name to look up. void setLookupName(DeclarationName Name) { NameInfo.setName(Name); } @@ -282,13 +268,13 @@ public: Redecl ? Sema::ForVisibleRedeclaration : Sema::NotForRedeclaration; } - /// \brief Specify whether hidden declarations are visible, e.g., + /// Specify whether hidden declarations are visible, e.g., /// for recovery reasons. void setAllowHidden(bool AH) { AllowHidden = AH; } - /// \brief Determine whether this lookup is permitted to see hidden + /// Determine whether this lookup is permitted to see hidden /// declarations, such as those in modules that have not yet been imported. bool isHiddenDeclarationVisible(NamedDecl *ND) const { return AllowHidden || @@ -338,16 +324,16 @@ public: iterator begin() const { return iterator(Decls.begin()); } iterator end() const { return iterator(Decls.end()); } - /// \brief Return true if no decls were found + /// Return true if no decls were found bool empty() const { return Decls.empty(); } - /// \brief Return the base paths structure that's associated with + /// Return the base paths structure that's associated with /// these results, or null if none is. CXXBasePaths *getBasePaths() const { return Paths; } - /// \brief Determine whether the given declaration is visible to the + /// Determine whether the given declaration is visible to the /// program. static bool isVisible(Sema &SemaRef, NamedDecl *D) { // If this declaration is not hidden, it's visible. @@ -359,7 +345,7 @@ public: return isVisibleSlow(SemaRef, D); } - /// \brief Retrieve the accepted (re)declaration of the given declaration, + /// Retrieve the accepted (re)declaration of the given declaration, /// if there is one. NamedDecl *getAcceptableDecl(NamedDecl *D) const { if (!D->isInIdentifierNamespace(IDNS)) @@ -376,18 +362,18 @@ private: NamedDecl *getAcceptableDeclSlow(NamedDecl *D) const; public: - /// \brief Returns the identifier namespace mask for this lookup. + /// Returns the identifier namespace mask for this lookup. unsigned getIdentifierNamespace() const { return IDNS; } - /// \brief Returns whether these results arose from performing a + /// Returns whether these results arose from performing a /// lookup into a class. bool isClassLookup() const { return NamingClass != nullptr; } - /// \brief Returns the 'naming class' for this lookup, i.e. the + /// Returns the 'naming class' for this lookup, i.e. the /// class which was looked into to find these results. /// /// C++0x [class.access.base]p5: @@ -407,72 +393,72 @@ public: return NamingClass; } - /// \brief Sets the 'naming class' for this lookup. + /// Sets the 'naming class' for this lookup. void setNamingClass(CXXRecordDecl *Record) { NamingClass = Record; } - /// \brief Returns the base object type associated with this lookup; + /// Returns the base object type associated with this lookup; /// important for [class.protected]. Most lookups do not have an /// associated base object. QualType getBaseObjectType() const { return BaseObjectType; } - /// \brief Sets the base object type for this lookup. + /// Sets the base object type for this lookup. void setBaseObjectType(QualType T) { BaseObjectType = T; } - /// \brief Add a declaration to these results with its natural access. + /// Add a declaration to these results with its natural access. /// Does not test the acceptance criteria. void addDecl(NamedDecl *D) { addDecl(D, D->getAccess()); } - /// \brief Add a declaration to these results with the given access. + /// Add a declaration to these results with the given access. /// Does not test the acceptance criteria. void addDecl(NamedDecl *D, AccessSpecifier AS) { Decls.addDecl(D, AS); ResultKind = Found; } - /// \brief Add all the declarations from another set of lookup + /// Add all the declarations from another set of lookup /// results. void addAllDecls(const LookupResult &Other) { Decls.append(Other.Decls.begin(), Other.Decls.end()); ResultKind = Found; } - /// \brief Determine whether no result was found because we could not + /// Determine whether no result was found because we could not /// search into dependent base classes of the current instantiation. bool wasNotFoundInCurrentInstantiation() const { return ResultKind == NotFoundInCurrentInstantiation; } - /// \brief Note that while no result was found in the current instantiation, + /// Note that while no result was found in the current instantiation, /// there were dependent base classes that could not be searched. void setNotFoundInCurrentInstantiation() { assert(ResultKind == NotFound && Decls.empty()); ResultKind = NotFoundInCurrentInstantiation; } - /// \brief Determine whether the lookup result was shadowed by some other + /// Determine whether the lookup result was shadowed by some other /// declaration that lookup ignored. bool isShadowed() const { return Shadowed; } - /// \brief Note that we found and ignored a declaration while performing + /// Note that we found and ignored a declaration while performing /// lookup. void setShadowed() { Shadowed = true; } - /// \brief Resolves the result kind of the lookup, possibly hiding + /// Resolves the result kind of the lookup, possibly hiding /// decls. /// /// This should be called in any environment where lookup might /// generate multiple lookup results. void resolveKind(); - /// \brief Re-resolves the result kind of the lookup after a set of + /// Re-resolves the result kind of the lookup after a set of /// removals has been performed. void resolveKindAfterFilter() { if (Decls.empty()) { @@ -512,7 +498,7 @@ public: return dyn_cast<DeclClass>(getFoundDecl()); } - /// \brief Fetch the unique decl found by this lookup. Asserts + /// Fetch the unique decl found by this lookup. Asserts /// that one was found. /// /// This is intended for users who have examined the result kind @@ -529,31 +515,31 @@ public: return *begin(); } - /// \brief Asks if the result is a single tag decl. + /// Asks if the result is a single tag decl. bool isSingleTagDecl() const { return getResultKind() == Found && isa<TagDecl>(getFoundDecl()); } - /// \brief Make these results show that the name was found in + /// Make these results show that the name was found in /// base classes of different types. /// /// The given paths object is copied and invalidated. void setAmbiguousBaseSubobjectTypes(CXXBasePaths &P); - /// \brief Make these results show that the name was found in + /// Make these results show that the name was found in /// distinct base classes of the same type. /// /// The given paths object is copied and invalidated. void setAmbiguousBaseSubobjects(CXXBasePaths &P); - /// \brief Make these results show that the name was found in + /// Make these results show that the name was found in /// different contexts and a tag decl was hidden by an ordinary /// decl in a different context. void setAmbiguousQualifiedTagHiding() { setAmbiguous(AmbiguousTagHiding); } - /// \brief Clears out any current state. + /// Clears out any current state. void clear() { ResultKind = NotFound; Decls.clear(); @@ -563,7 +549,7 @@ public: Shadowed = false; } - /// \brief Clears out any current state and re-initializes for a + /// Clears out any current state and re-initializes for a /// different kind of lookup. void clear(Sema::LookupNameKind Kind) { clear(); @@ -571,7 +557,7 @@ public: configure(); } - /// \brief Change this lookup's redeclaration kind. + /// Change this lookup's redeclaration kind. void setRedeclarationKind(Sema::RedeclarationKind RK) { Redecl = (RK != Sema::NotForRedeclaration); ExternalRedecl = (RK == Sema::ForExternalRedeclaration); @@ -610,7 +596,7 @@ public: return NameInfo.getLoc(); } - /// \brief Get the Sema object that this lookup result is searching + /// Get the Sema object that this lookup result is searching /// with. Sema &getSema() const { return *SemaPtr; } @@ -618,15 +604,14 @@ public: /// filtering out results. The results returned are possibly /// sugared. class Filter { + friend class LookupResult; + LookupResult &Results; LookupResult::iterator I; - bool Changed; - bool CalledDone; + bool Changed = false; + bool CalledDone = false; - friend class LookupResult; - Filter(LookupResult &Results) - : Results(Results), I(Results.begin()), Changed(false), CalledDone(false) - {} + Filter(LookupResult &Results) : Results(Results), I(Results.begin()) {} public: Filter(Filter &&F) @@ -634,6 +619,7 @@ public: CalledDone(F.CalledDone) { F.CalledDone = true; } + ~Filter() { assert(CalledDone && "LookupResult::Filter destroyed without done() call"); @@ -722,11 +708,11 @@ private: static void deletePaths(CXXBasePaths *); // Results. - LookupResultKind ResultKind; + LookupResultKind ResultKind = NotFound; AmbiguityKind Ambiguity; // ill-defined unless ambiguous UnresolvedSet<8> Decls; - CXXBasePaths *Paths; - CXXRecordDecl *NamingClass; + CXXBasePaths *Paths = nullptr; + CXXRecordDecl *NamingClass = nullptr; QualType BaseObjectType; // Parameters. @@ -734,27 +720,27 @@ private: DeclarationNameInfo NameInfo; SourceRange NameContextRange; Sema::LookupNameKind LookupKind; - unsigned IDNS; // set by configure() + unsigned IDNS = 0; // set by configure() bool Redecl; bool ExternalRedecl; - /// \brief True if tag declarations should be hidden if non-tags + /// True if tag declarations should be hidden if non-tags /// are present - bool HideTags; + bool HideTags = true; - bool Diagnose; + bool Diagnose = false; - /// \brief True if we should allow hidden declarations to be 'visible'. - bool AllowHidden; + /// True if we should allow hidden declarations to be 'visible'. + bool AllowHidden = false; - /// \brief True if the found declarations were shadowed by some other + /// True if the found declarations were shadowed by some other /// declaration that we skipped. This only happens when \c LookupKind /// is \c LookupRedeclarationWithLinkage. - bool Shadowed; + bool Shadowed = false; }; -/// \brief Consumes visible declarations found when searching for +/// Consumes visible declarations found when searching for /// all visible names within a given scope or context. /// /// This abstract class is meant to be subclassed by clients of \c @@ -762,15 +748,15 @@ private: /// FoundDecl() function to process declarations as they are found. class VisibleDeclConsumer { public: - /// \brief Destroys the visible declaration consumer. + /// Destroys the visible declaration consumer. virtual ~VisibleDeclConsumer(); - /// \brief Determine whether hidden declarations (from unimported + /// Determine whether hidden declarations (from unimported /// modules) should be given to this consumer. By default, they /// are not included. virtual bool includeHiddenDecls() const; - /// \brief Invoked each time \p Sema::LookupVisibleDecls() finds a + /// Invoked each time \p Sema::LookupVisibleDecls() finds a /// declaration visible from the current scope or context. /// /// \param ND the declaration found. @@ -784,9 +770,15 @@ public: /// class of the context we searched. virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx, bool InBaseClass) = 0; + + /// Callback to inform the client that Sema entered into a new context + /// to find a visible declaration. + // + /// \param Ctx the context which Sema entered. + virtual void EnteredContext(DeclContext *Ctx) {} }; -/// \brief A class for storing results from argument-dependent lookup. +/// A class for storing results from argument-dependent lookup. class ADLResult { private: /// A map from canonical decls to the 'most recent' decl. @@ -807,13 +799,13 @@ public: Decls.erase(cast<NamedDecl>(D->getCanonicalDecl())); } - typedef llvm::mapped_iterator<decltype(Decls)::iterator, select_second> - iterator; + using iterator = + llvm::mapped_iterator<decltype(Decls)::iterator, select_second>; iterator begin() { return iterator(Decls.begin(), select_second()); } iterator end() { return iterator(Decls.end(), select_second()); } }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_LOOKUP_H diff --git a/include/clang/Sema/LoopHint.h b/include/clang/Sema/LoopHint.h index c8b2ee845e590..171435e69bc8a 100644 --- a/include/clang/Sema/LoopHint.h +++ b/include/clang/Sema/LoopHint.h @@ -12,12 +12,12 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" -#include "clang/Sema/AttributeList.h" #include "clang/Sema/Ownership.h" +#include "clang/Sema/ParsedAttr.h" namespace clang { -/// \brief Loop optimization hint for loop and unroll pragmas. +/// Loop optimization hint for loop and unroll pragmas. struct LoopHint { // Source range of the directive. SourceRange Range; diff --git a/include/clang/Sema/MultiplexExternalSemaSource.h b/include/clang/Sema/MultiplexExternalSemaSource.h index 1d681a00552fc..4c242c89f3f4b 100644 --- a/include/clang/Sema/MultiplexExternalSemaSource.h +++ b/include/clang/Sema/MultiplexExternalSemaSource.h @@ -33,7 +33,7 @@ namespace clang { class VarDecl; -/// \brief An abstract interface that should be implemented by +/// An abstract interface that should be implemented by /// external AST sources that also provide information for semantic /// analysis. class MultiplexExternalSemaSource : public ExternalSemaSource { @@ -43,7 +43,7 @@ private: public: - ///\brief Constructs a new multiplexing external sema source and appends the + ///Constructs a new multiplexing external sema source and appends the /// given element to it. /// ///\param[in] s1 - A non-null (old) ExternalSemaSource. @@ -53,7 +53,7 @@ public: ~MultiplexExternalSemaSource() override; - ///\brief Appends new source to the source list. + ///Appends new source to the source list. /// ///\param[in] source - An ExternalSemaSource. /// @@ -63,45 +63,45 @@ public: // ExternalASTSource. //===--------------------------------------------------------------------===// - /// \brief Resolve a declaration ID into a declaration, potentially + /// Resolve a declaration ID into a declaration, potentially /// building a new declaration. Decl *GetExternalDecl(uint32_t ID) override; - /// \brief Complete the redeclaration chain if it's been extended since the + /// Complete the redeclaration chain if it's been extended since the /// previous generation of the AST source. void CompleteRedeclChain(const Decl *D) override; - /// \brief Resolve a selector ID into a selector. + /// Resolve a selector ID into a selector. Selector GetExternalSelector(uint32_t ID) override; - /// \brief Returns the number of selectors known to the external AST + /// Returns the number of selectors known to the external AST /// source. uint32_t GetNumExternalSelectors() override; - /// \brief Resolve the offset of a statement in the decl stream into + /// Resolve the offset of a statement in the decl stream into /// a statement. Stmt *GetExternalDeclStmt(uint64_t Offset) override; - /// \brief Resolve the offset of a set of C++ base specifiers in the decl + /// Resolve the offset of a set of C++ base specifiers in the decl /// stream into an array of specifiers. CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; - /// \brief Resolve a handle to a list of ctor initializers into the list of + /// Resolve a handle to a list of ctor initializers into the list of /// initializers themselves. CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; ExtKind hasExternalDefinitions(const Decl *D) override; - /// \brief Find all declarations with the given name in the + /// Find all declarations with the given name in the /// given context. bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; - /// \brief Ensures that the table of all visible declarations inside this + /// Ensures that the table of all visible declarations inside this /// context is up to date. void completeVisibleDeclsMap(const DeclContext *DC) override; - /// \brief Finds all declarations lexically contained within the given + /// Finds all declarations lexically contained within the given /// DeclContext, after applying an optional filter predicate. /// /// \param IsKindWeWant a predicate function that returns true if the passed @@ -111,17 +111,17 @@ public: llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl<Decl *> &Result) override; - /// \brief Get the decls that are contained in a file in the Offset/Length + /// Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. void FindFileRegionDecls(FileID File, unsigned Offset,unsigned Length, SmallVectorImpl<Decl *> &Decls) override; - /// \brief Gives the external AST source an opportunity to complete + /// Gives the external AST source an opportunity to complete /// an incomplete type. void CompleteType(TagDecl *Tag) override; - /// \brief Gives the external AST source an opportunity to complete an + /// Gives the external AST source an opportunity to complete an /// incomplete Objective-C class. /// /// This routine will only be invoked if the "externally completed" bit is @@ -129,28 +129,32 @@ public: /// \c ObjCInterfaceDecl::setExternallyCompleted(). void CompleteType(ObjCInterfaceDecl *Class) override; - /// \brief Loads comment ranges. + /// Loads comment ranges. void ReadComments() override; - /// \brief Notify ExternalASTSource that we started deserialization of + /// Notify ExternalASTSource that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. void StartedDeserializing() override; - /// \brief Notify ExternalASTSource that we finished the deserialization of + /// Notify ExternalASTSource that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. void FinishedDeserializing() override; - /// \brief Function that will be invoked when we begin parsing a new + /// Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. void StartTranslationUnit(ASTConsumer *Consumer) override; - /// \brief Print any statistics that have been gathered regarding + /// Print any statistics that have been gathered regarding /// the external AST source. void PrintStats() override; - - - /// \brief Perform layout on the given record. + + /// Retrieve the module that corresponds to the given module ID. + Module *getModule(unsigned ID) override; + + bool DeclIsFromPCHWithObjectFile(const Decl *D) override; + + /// Perform layout on the given record. /// /// This routine allows the external AST source to provide an specific /// layout for a record, overriding the layout that would normally be @@ -193,15 +197,15 @@ public: // ExternalSemaSource. //===--------------------------------------------------------------------===// - /// \brief Initialize the semantic source with the Sema instance + /// Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. void InitializeSema(Sema &S) override; - /// \brief Inform the semantic consumer that Sema is no longer available. + /// Inform the semantic consumer that Sema is no longer available. void ForgetSema() override; - /// \brief Load the contents of the global method pool for a given + /// Load the contents of the global method pool for a given /// selector. void ReadMethodPool(Selector Sel) override; @@ -209,12 +213,12 @@ public: /// selector if necessary. void updateOutOfDateSelector(Selector Sel) override; - /// \brief Load the set of namespaces that are known to the external source, + /// Load the set of namespaces that are known to the external source, /// which will be used during typo correction. void ReadKnownNamespaces(SmallVectorImpl<NamespaceDecl*> &Namespaces) override; - /// \brief Load the set of used but not defined functions or variables with + /// Load the set of used but not defined functions or variables with /// internal linkage, or used but not defined inline functions. void ReadUndefinedButUsed( llvm::MapVector<NamedDecl *, SourceLocation> &Undefined) override; @@ -223,7 +227,7 @@ public: FieldDecl *, llvm::SmallVector<std::pair<SourceLocation, bool>, 4>> & Exprs) override; - /// \brief Do last resort, unqualified lookup on a LookupResult that + /// Do last resort, unqualified lookup on a LookupResult that /// Sema cannot find. /// /// \param R a LookupResult that is being recovered. @@ -233,7 +237,7 @@ public: /// \return true to tell Sema to recover using the LookupResult. bool LookupUnqualified(LookupResult &R, Scope *S) override; - /// \brief Read the set of tentative definitions known to the external Sema + /// Read the set of tentative definitions known to the external Sema /// source. /// /// The external source should append its own tentative definitions to the @@ -242,7 +246,7 @@ public: /// introduce the same declarations repeatedly. void ReadTentativeDefinitions(SmallVectorImpl<VarDecl*> &Defs) override; - /// \brief Read the set of unused file-scope declarations known to the + /// Read the set of unused file-scope declarations known to the /// external Sema source. /// /// The external source should append its own unused, filed-scope to the @@ -252,7 +256,7 @@ public: void ReadUnusedFileScopedDecls( SmallVectorImpl<const DeclaratorDecl*> &Decls) override; - /// \brief Read the set of delegating constructors known to the + /// Read the set of delegating constructors known to the /// external Sema source. /// /// The external source should append its own delegating constructors to the @@ -262,7 +266,7 @@ public: void ReadDelegatingConstructors( SmallVectorImpl<CXXConstructorDecl*> &Decls) override; - /// \brief Read the set of ext_vector type declarations known to the + /// Read the set of ext_vector type declarations known to the /// external Sema source. /// /// The external source should append its own ext_vector type declarations to @@ -271,7 +275,7 @@ public: /// introduce the same declarations repeatedly. void ReadExtVectorDecls(SmallVectorImpl<TypedefNameDecl*> &Decls) override; - /// \brief Read the set of potentially unused typedefs known to the source. + /// 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 @@ -280,7 +284,7 @@ public: void ReadUnusedLocalTypedefNameCandidates( llvm::SmallSetVector<const TypedefNameDecl *, 4> &Decls) override; - /// \brief Read the set of referenced selectors known to the + /// Read the set of referenced selectors known to the /// external Sema source. /// /// The external source should append its own referenced selectors to the @@ -290,7 +294,7 @@ public: void ReadReferencedSelectors(SmallVectorImpl<std::pair<Selector, SourceLocation> > &Sels) override; - /// \brief Read the set of weak, undeclared identifiers known to the + /// Read the set of weak, undeclared identifiers known to the /// external Sema source. /// /// The external source should append its own weak, undeclared identifiers to @@ -300,14 +304,14 @@ public: void ReadWeakUndeclaredIdentifiers( SmallVectorImpl<std::pair<IdentifierInfo*, WeakInfo> > &WI) override; - /// \brief Read the set of used vtables known to the external Sema source. + /// Read the set of used vtables known to the external Sema source. /// /// The external source should append its own used vtables to the given /// vector. Note that this routine may be invoked multiple times; the external /// source should take care not to introduce the same vtables repeatedly. void ReadUsedVTables(SmallVectorImpl<ExternalVTableUse> &VTables) override; - /// \brief Read the set of pending instantiations known to the external + /// Read the set of pending instantiations known to the external /// Sema source. /// /// The external source should append its own pending instantiations to the @@ -317,7 +321,7 @@ public: void ReadPendingInstantiations( SmallVectorImpl<std::pair<ValueDecl*, SourceLocation> >& Pending) override; - /// \brief Read the set of late parsed template functions for this source. + /// Read the set of late parsed template functions for this source. /// /// The external source should insert its own late parsed template functions /// into the map. Note that this routine may be invoked multiple times; the @@ -336,7 +340,7 @@ public: bool EnteringContext, const ObjCObjectPointerType *OPT) override; - /// \brief Produces a diagnostic note if one of the attached sources + /// Produces a diagnostic note if one of the attached sources /// contains a complete definition for \p T. Queries the sources in list /// order until the first one claims that a diagnostic was produced. /// diff --git a/include/clang/Sema/ObjCMethodList.h b/include/clang/Sema/ObjCMethodList.h index 80ccd363d2725..d0af4d15fb9f3 100644 --- a/include/clang/Sema/ObjCMethodList.h +++ b/include/clang/Sema/ObjCMethodList.h @@ -21,13 +21,13 @@ namespace clang { class ObjCMethodDecl; -/// \brief a linked list of methods with the same selector name but different +/// a linked list of methods with the same selector name but different /// signatures. struct ObjCMethodList { // 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. + /// 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. + /// The next list object and 2 bits for extra info. llvm::PointerIntPair<ObjCMethodList *, 2> NextAndExtraBits; ObjCMethodList() { } diff --git a/include/clang/Sema/Overload.h b/include/clang/Sema/Overload.h index 05cfe53666ca9..f75faf049625d 100644 --- a/include/clang/Sema/Overload.h +++ b/include/clang/Sema/Overload.h @@ -1,4 +1,4 @@ -//===--- Overload.h - C++ Overloading ---------------------------*- C++ -*-===// +//===- Overload.h - C++ Overloading -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,32 +16,51 @@ #define LLVM_CLANG_SEMA_OVERLOAD_H #include "clang/AST/Decl.h" +#include "clang/AST/DeclAccessPair.h" +#include "clang/AST/DeclBase.h" +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" -#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" -#include "clang/AST/UnresolvedSet.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Sema/SemaFixItUtils.h" #include "clang/Sema/TemplateDeduction.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Support/AlignOf.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <cstddef> +#include <cstdint> +#include <utility> namespace clang { - class ASTContext; - class CXXConstructorDecl; - class CXXConversionDecl; - class FunctionDecl; - class Sema; + +class APValue; +class ASTContext; +class Sema; /// OverloadingResult - Capture the result of performing overload /// resolution. enum OverloadingResult { - OR_Success, ///< Overload resolution succeeded. - OR_No_Viable_Function, ///< No viable function found. - OR_Ambiguous, ///< Ambiguous candidates found. - OR_Deleted ///< Succeeded, but refers to a deleted function. + /// Overload resolution succeeded. + OR_Success, + + /// No viable function found. + OR_No_Viable_Function, + + /// Ambiguous candidates found. + OR_Ambiguous, + + /// Succeeded, but refers to a deleted function. + OR_Deleted }; enum OverloadCandidateDisplayKind { @@ -55,39 +74,95 @@ namespace clang { /// ImplicitConversionKind - The kind of implicit conversion used to /// convert an argument to a parameter's type. The enumerator values - /// match with Table 9 of (C++ 13.3.3.1.1) and are listed such that - /// better conversion kinds have smaller values. + /// match with the table titled 'Conversions' in [over.ics.scs] and are listed + /// such that better conversion kinds have smaller values. enum ImplicitConversionKind { - ICK_Identity = 0, ///< Identity conversion (no conversion) - ICK_Lvalue_To_Rvalue, ///< Lvalue-to-rvalue conversion (C++ 4.1) - ICK_Array_To_Pointer, ///< Array-to-pointer conversion (C++ 4.2) - ICK_Function_To_Pointer, ///< Function-to-pointer (C++ 4.3) - ICK_Function_Conversion, ///< Function pointer conversion (C++17 4.13) - ICK_Qualification, ///< Qualification conversions (C++ 4.4) - ICK_Integral_Promotion, ///< Integral promotions (C++ 4.5) - ICK_Floating_Promotion, ///< Floating point promotions (C++ 4.6) - ICK_Complex_Promotion, ///< Complex promotions (Clang extension) - ICK_Integral_Conversion, ///< Integral conversions (C++ 4.7) - ICK_Floating_Conversion, ///< Floating point conversions (C++ 4.8) - ICK_Complex_Conversion, ///< Complex conversions (C99 6.3.1.6) - ICK_Floating_Integral, ///< Floating-integral conversions (C++ 4.9) - ICK_Pointer_Conversion, ///< Pointer conversions (C++ 4.10) - ICK_Pointer_Member, ///< Pointer-to-member conversions (C++ 4.11) - ICK_Boolean_Conversion, ///< Boolean conversions (C++ 4.12) - ICK_Compatible_Conversion, ///< Conversions between compatible types in C99 - ICK_Derived_To_Base, ///< Derived-to-base (C++ [over.best.ics]) - ICK_Vector_Conversion, ///< Vector conversions - ICK_Vector_Splat, ///< A vector splat from an arithmetic type - ICK_Complex_Real, ///< Complex-real conversions (C99 6.3.1.7) - ICK_Block_Pointer_Conversion, ///< Block Pointer conversions - ICK_TransparentUnionConversion, ///< Transparent Union Conversions - ICK_Writeback_Conversion, ///< Objective-C ARC writeback conversion - ICK_Zero_Event_Conversion, ///< Zero constant to event (OpenCL1.2 6.12.10) - ICK_Zero_Queue_Conversion, ///< Zero constant to queue - ICK_C_Only_Conversion, ///< Conversions allowed in C, but not C++ - ICK_Incompatible_Pointer_Conversion, ///< C-only conversion between pointers - /// with incompatible types - ICK_Num_Conversion_Kinds, ///< The number of conversion kinds + /// Identity conversion (no conversion) + ICK_Identity = 0, + + /// Lvalue-to-rvalue conversion (C++ [conv.lval]) + ICK_Lvalue_To_Rvalue, + + /// Array-to-pointer conversion (C++ [conv.array]) + ICK_Array_To_Pointer, + + /// Function-to-pointer (C++ [conv.array]) + ICK_Function_To_Pointer, + + /// Function pointer conversion (C++17 [conv.fctptr]) + ICK_Function_Conversion, + + /// Qualification conversions (C++ [conv.qual]) + ICK_Qualification, + + /// Integral promotions (C++ [conv.prom]) + ICK_Integral_Promotion, + + /// Floating point promotions (C++ [conv.fpprom]) + ICK_Floating_Promotion, + + /// Complex promotions (Clang extension) + ICK_Complex_Promotion, + + /// Integral conversions (C++ [conv.integral]) + ICK_Integral_Conversion, + + /// Floating point conversions (C++ [conv.double] + ICK_Floating_Conversion, + + /// Complex conversions (C99 6.3.1.6) + ICK_Complex_Conversion, + + /// Floating-integral conversions (C++ [conv.fpint]) + ICK_Floating_Integral, + + /// Pointer conversions (C++ [conv.ptr]) + ICK_Pointer_Conversion, + + /// Pointer-to-member conversions (C++ [conv.mem]) + ICK_Pointer_Member, + + /// Boolean conversions (C++ [conv.bool]) + ICK_Boolean_Conversion, + + /// Conversions between compatible types in C99 + ICK_Compatible_Conversion, + + /// Derived-to-base (C++ [over.best.ics]) + ICK_Derived_To_Base, + + /// Vector conversions + ICK_Vector_Conversion, + + /// A vector splat from an arithmetic type + ICK_Vector_Splat, + + /// Complex-real conversions (C99 6.3.1.7) + ICK_Complex_Real, + + /// Block Pointer conversions + ICK_Block_Pointer_Conversion, + + /// Transparent Union Conversions + ICK_TransparentUnionConversion, + + /// Objective-C ARC writeback conversion + ICK_Writeback_Conversion, + + /// Zero constant to event (OpenCL1.2 6.12.10) + ICK_Zero_Event_Conversion, + + /// Zero constant to queue + ICK_Zero_Queue_Conversion, + + /// Conversions allowed in C, but not C++ + ICK_C_Only_Conversion, + + /// C-only conversion between pointers with incompatible types + ICK_Incompatible_Pointer_Conversion, + + /// The number of conversion kinds + ICK_Num_Conversion_Kinds, }; /// ImplicitConversionRank - The rank of an implicit conversion @@ -95,16 +170,30 @@ namespace clang { /// 13.3.3.1.1) and are listed such that better conversion ranks /// have smaller values. enum ImplicitConversionRank { - ICR_Exact_Match = 0, ///< Exact Match - ICR_Promotion, ///< Promotion - ICR_Conversion, ///< Conversion - ICR_OCL_Scalar_Widening, ///< OpenCL Scalar Widening - ICR_Complex_Real_Conversion, ///< Complex <-> Real conversion - ICR_Writeback_Conversion, ///< ObjC ARC writeback conversion - ICR_C_Conversion, ///< Conversion only allowed in the C standard. - /// (e.g. void* to char*) - ICR_C_Conversion_Extension ///< Conversion not allowed by the C standard, - /// but that we accept as an extension anyway. + /// Exact Match + ICR_Exact_Match = 0, + + /// Promotion + ICR_Promotion, + + /// Conversion + ICR_Conversion, + + /// OpenCL Scalar Widening + ICR_OCL_Scalar_Widening, + + /// Complex <-> Real conversion + ICR_Complex_Real_Conversion, + + /// ObjC ARC writeback conversion + ICR_Writeback_Conversion, + + /// Conversion only allowed in the C standard (e.g. void* to char*). + ICR_C_Conversion, + + /// Conversion not allowed by the C standard, but that we accept as an + /// extension anyway. + ICR_C_Conversion_Extension }; ImplicitConversionRank GetConversionRank(ImplicitConversionKind Kind); @@ -155,12 +244,12 @@ namespace clang { /// or a function conversion. ImplicitConversionKind Third : 8; - /// \brief Whether this is the deprecated conversion of a + /// Whether this is the deprecated conversion of a /// string literal to a pointer to non-const character data /// (C++ 4.2p2). unsigned DeprecatedStringLiteralToCharPtr : 1; - /// \brief Whether the qualification conversion involves a change in the + /// Whether the qualification conversion involves a change in the /// Objective-C lifetime (for automatic reference counting). unsigned QualificationIncludesObjCLifetime : 1; @@ -176,21 +265,21 @@ namespace clang { /// direct binding (C++ [dcl.init.ref]). unsigned DirectBinding : 1; - /// \brief Whether this is an lvalue reference binding (otherwise, it's + /// Whether this is an lvalue reference binding (otherwise, it's /// an rvalue reference binding). unsigned IsLvalueReference : 1; - /// \brief Whether we're binding to a function lvalue. + /// Whether we're binding to a function lvalue. unsigned BindsToFunctionLvalue : 1; - /// \brief Whether we're binding to an rvalue. + /// Whether we're binding to an rvalue. unsigned BindsToRvalue : 1; - /// \brief Whether this binds an implicit object argument to a + /// Whether this binds an implicit object argument to a /// non-static member function without a ref-qualifier. unsigned BindsImplicitObjectArgumentWithoutRefQualifier : 1; - /// \brief Whether this binds a reference to an object with a different + /// Whether this binds a reference to an object with a different /// Objective-C lifetime qualifier. unsigned ObjCLifetimeConversionBinding : 1; @@ -213,10 +302,12 @@ namespace clang { DeclAccessPair FoundCopyConstructor; void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } + void setToType(unsigned Idx, QualType T) { assert(Idx < 3 && "To type index is out of range"); ToTypePtrs[Idx] = T.getAsOpaquePtr(); } + void setAllToTypes(QualType T) { ToTypePtrs[0] = T.getAsOpaquePtr(); ToTypePtrs[1] = ToTypePtrs[0]; @@ -226,6 +317,7 @@ namespace clang { QualType getFromType() const { return QualType::getFromOpaquePtr(FromTypePtr); } + QualType getToType(unsigned Idx) const { assert(Idx < 3 && "To type index is out of range"); return QualType::getFromOpaquePtr(ToTypePtrs[Idx]); @@ -238,9 +330,10 @@ namespace clang { } ImplicitConversionRank getRank() const; - NarrowingKind getNarrowingKind(ASTContext &Context, const Expr *Converted, - APValue &ConstantValue, - QualType &ConstantType) const; + NarrowingKind + getNarrowingKind(ASTContext &Context, const Expr *Converted, + APValue &ConstantValue, QualType &ConstantType, + bool IgnoreFloatToIntegralConversion = false) const; bool isPointerConversionToBool() const; bool isPointerConversionToVoidPointer(ASTContext& Context) const; void dump() const; @@ -249,7 +342,7 @@ namespace clang { /// UserDefinedConversionSequence - Represents a user-defined /// conversion sequence (C++ 13.3.3.1.2). struct UserDefinedConversionSequence { - /// \brief Represents the standard conversion that occurs before + /// Represents the standard conversion that occurs before /// the actual user-defined conversion. /// /// C++11 13.3.3.1.2p1: @@ -284,7 +377,7 @@ namespace clang { /// aggregate initialization from an initializer list. FunctionDecl* ConversionFunction; - /// \brief The declaration that we found via name lookup, which might be + /// The declaration that we found via name lookup, which might be /// the same as \c ConversionFunction or it might be a using declaration /// that refers to \c ConversionFunction. DeclAccessPair FoundConversionFunction; @@ -294,7 +387,8 @@ namespace clang { /// Represents an ambiguous user-defined conversion sequence. struct AmbiguousConversionSequence { - typedef SmallVector<std::pair<NamedDecl*, FunctionDecl*>, 4> ConversionSet; + using ConversionSet = + SmallVector<std::pair<NamedDecl *, FunctionDecl *>, 4>; void *FromTypePtr; void *ToTypePtr; @@ -303,9 +397,11 @@ namespace clang { QualType getFromType() const { return QualType::getFromOpaquePtr(FromTypePtr); } + QualType getToType() const { return QualType::getFromOpaquePtr(ToTypePtr); } + void setFromType(QualType T) { FromTypePtr = T.getAsOpaquePtr(); } void setToType(QualType T) { ToTypePtr = T.getAsOpaquePtr(); } @@ -321,11 +417,13 @@ namespace clang { conversions().push_back(std::make_pair(Found, D)); } - typedef ConversionSet::iterator iterator; + using iterator = ConversionSet::iterator; + iterator begin() { return conversions().begin(); } iterator end() { return conversions().end(); } - typedef ConversionSet::const_iterator const_iterator; + using const_iterator = ConversionSet::const_iterator; + const_iterator begin() const { return conversions().begin(); } const_iterator end() const { return conversions().end(); } @@ -362,6 +460,7 @@ namespace clang { init(K, From->getType(), To); FromExpr = From; } + void init(FailureKind K, QualType From, QualType To) { Kind = K; FromExpr = nullptr; @@ -376,6 +475,7 @@ namespace clang { FromExpr = E; setFromType(E->getType()); } + void setFromType(QualType T) { FromTy = T.getAsOpaquePtr(); } void setToType(QualType T) { ToTy = T.getAsOpaquePtr(); } }; @@ -406,7 +506,7 @@ namespace clang { /// ConversionKind - The kind of implicit conversion sequence. unsigned ConversionKind : 30; - /// \brief Whether the target is really a std::initializer_list, and the + /// Whether the target is really a std::initializer_list, and the /// sequence only represents the worst element conversion. unsigned StdInitializerListElement : 1; @@ -442,13 +542,10 @@ namespace clang { : ConversionKind(Uninitialized), StdInitializerListElement(false) { Standard.setAsIdentityConversion(); } - ~ImplicitConversionSequence() { - destruct(); - } + ImplicitConversionSequence(const ImplicitConversionSequence &Other) - : ConversionKind(Other.ConversionKind), - StdInitializerListElement(Other.StdInitializerListElement) - { + : ConversionKind(Other.ConversionKind), + StdInitializerListElement(Other.StdInitializerListElement) { switch (ConversionKind) { case Uninitialized: break; case StandardConversion: Standard = Other.Standard; break; @@ -460,18 +557,22 @@ namespace clang { } ImplicitConversionSequence & - operator=(const ImplicitConversionSequence &Other) { + operator=(const ImplicitConversionSequence &Other) { destruct(); new (this) ImplicitConversionSequence(Other); return *this; } + ~ImplicitConversionSequence() { + destruct(); + } + Kind getKind() const { assert(isInitialized() && "querying uninitialized conversion"); return Kind(ConversionKind); } - /// \brief Return a ranking of the implicit conversion sequence + /// Return a ranking of the implicit conversion sequence /// kind, where smaller ranks represent better conversion /// sequences. /// @@ -526,6 +627,7 @@ namespace clang { void setStandard() { setKind(StandardConversion); } void setEllipsis() { setKind(EllipsisConversion); } void setUserDefined() { setKind(UserDefinedConversion); } + void setAmbiguous() { if (ConversionKind == AmbiguousConversion) return; ConversionKind = AmbiguousConversion; @@ -539,7 +641,7 @@ namespace clang { Standard.setAllToTypes(T); } - /// \brief Whether the target is really a std::initializer_list, and the + /// Whether the target is really a std::initializer_list, and the /// sequence only represents the worst element conversion. bool isStdInitializerListElement() const { return StdInitializerListElement; @@ -613,12 +715,16 @@ namespace clang { /// This inherited constructor is not viable because it would slice the /// argument. ovl_fail_inhctor_slice, + + /// This candidate was not viable because it is a non-default multiversioned + /// function. + ovl_non_default_multiversion_function, }; /// A list of implicit conversion sequences for the arguments of an /// OverloadCandidate. - typedef llvm::MutableArrayRef<ImplicitConversionSequence> - ConversionSequenceList; + using ConversionSequenceList = + llvm::MutableArrayRef<ImplicitConversionSequence>; /// OverloadCandidate - A single candidate in an overload set (C++ 13.3). struct OverloadCandidate { @@ -669,7 +775,7 @@ namespace clang { /// Actually an OverloadFailureKind. unsigned char FailureKind; - /// \brief The number of call arguments that were explicitly provided, + /// The number of call arguments that were explicitly provided, /// to be used while performing partial ordering of function templates. unsigned ExplicitCallArguments; @@ -726,16 +832,19 @@ namespace clang { enum CandidateSetKind { /// Normal lookup. CSK_Normal, + /// C++ [over.match.oper]: /// Lookup of operator function candidates in a call using operator /// syntax. Candidates that have no parameters of class type will be /// skipped unless there is a parameter of (reference to) enum type and /// the corresponding argument is of the same enum type. CSK_Operator, + /// C++ [over.match.copy]: /// Copy-initialization of an object of class type by user-defined /// conversion. CSK_InitByUserDefinedConversion, + /// C++ [over.match.ctor], [over.match.list] /// Initialization of an object of class type by constructor, /// using either a parenthesized or braced list of arguments. @@ -755,7 +864,7 @@ namespace clang { constexpr static unsigned NumInlineBytes = 24 * sizeof(ImplicitConversionSequence); - unsigned NumInlineBytesUsed; + unsigned NumInlineBytesUsed = 0; llvm::AlignedCharArray<alignof(void *), NumInlineBytes> InlineSpace; /// If we have space, allocates from inline storage. Otherwise, allocates @@ -784,36 +893,36 @@ namespace clang { return reinterpret_cast<T *>(FreeSpaceStart); } - OverloadCandidateSet(const OverloadCandidateSet &) = delete; - void operator=(const OverloadCandidateSet &) = delete; - void destroyCandidates(); public: OverloadCandidateSet(SourceLocation Loc, CandidateSetKind CSK) - : Loc(Loc), Kind(CSK), NumInlineBytesUsed(0) {} + : Loc(Loc), Kind(CSK) {} + OverloadCandidateSet(const OverloadCandidateSet &) = delete; + OverloadCandidateSet &operator=(const OverloadCandidateSet &) = delete; ~OverloadCandidateSet() { destroyCandidates(); } SourceLocation getLocation() const { return Loc; } CandidateSetKind getKind() const { return Kind; } - /// \brief Determine when this overload candidate will be new to the + /// Determine when this overload candidate will be new to the /// overload set. bool isNewCandidate(Decl *F) { return Functions.insert(F->getCanonicalDecl()).second; } - /// \brief Clear out all of the candidates. + /// Clear out all of the candidates. void clear(CandidateSetKind CSK); - typedef SmallVectorImpl<OverloadCandidate>::iterator iterator; + using iterator = SmallVectorImpl<OverloadCandidate>::iterator; + iterator begin() { return Candidates.begin(); } iterator end() { return Candidates.end(); } size_t size() const { return Candidates.size(); } bool empty() const { return Candidates.empty(); } - /// \brief Allocate storage for conversion sequences for NumConversions + /// Allocate storage for conversion sequences for NumConversions /// conversions. ConversionSequenceList allocateConversionSequences(unsigned NumConversions) { @@ -827,7 +936,7 @@ namespace clang { return ConversionSequenceList(Conversions, NumConversions); } - /// \brief Add a new candidate with NumConversions conversion sequence slots + /// Add a new candidate with NumConversions conversion sequence slots /// to the overload set. OverloadCandidate &addCandidate(unsigned NumConversions = 0, ConversionSequenceList Conversions = None) { @@ -865,8 +974,10 @@ namespace clang { DeclAccessPair FoundDecl; CXXConstructorDecl *Constructor; FunctionTemplateDecl *ConstructorTmpl; + explicit operator bool() const { return Constructor; } }; + // FIXME: Add an AddOverloadCandidate / AddTemplateOverloadCandidate overload // that takes one of these. inline ConstructorInfo getConstructorInfo(NamedDecl *ND) { @@ -884,6 +995,7 @@ namespace clang { Info.Constructor = dyn_cast<CXXConstructorDecl>(D); return Info; } -} // end namespace clang + +} // namespace clang #endif // LLVM_CLANG_SEMA_OVERLOAD_H diff --git a/include/clang/Sema/Ownership.h b/include/clang/Sema/Ownership.h index 1e35316fd5dd5..ae2f178df1ec9 100644 --- a/include/clang/Sema/Ownership.h +++ b/include/clang/Sema/Ownership.h @@ -1,4 +1,4 @@ -//===--- Ownership.h - Parser ownership helpers -----------------*- C++ -*-===// +//===- Ownership.h - Parser ownership helpers -------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -17,23 +17,29 @@ #include "clang/AST/Expr.h" #include "clang/Basic/LLVM.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/Support/PointerLikeTypeTraits.h" +#include "llvm/Support/type_traits.h" +#include <cassert> +#include <cstddef> +#include <cstdint> //===----------------------------------------------------------------------===// // OpaquePtr //===----------------------------------------------------------------------===// namespace clang { - class CXXCtorInitializer; - class CXXBaseSpecifier; - class Decl; - class Expr; - class ParsedTemplateArgument; - class QualType; - class Stmt; - class TemplateName; - class TemplateParameterList; - - /// \brief Wrapper for void* pointer. + +class CXXBaseSpecifier; +class CXXCtorInitializer; +class Decl; +class Expr; +class ParsedTemplateArgument; +class QualType; +class Stmt; +class TemplateName; +class TemplateParameterList; + + /// Wrapper for void* pointer. /// \tparam PtrTy Either a pointer type like 'T*' or a type that behaves like /// a pointer. /// @@ -44,16 +50,17 @@ namespace clang { template <class PtrTy> class OpaquePtr { void *Ptr = nullptr; + explicit OpaquePtr(void *Ptr) : Ptr(Ptr) {} - typedef llvm::PointerLikeTypeTraits<PtrTy> Traits; + using Traits = llvm::PointerLikeTypeTraits<PtrTy>; public: OpaquePtr(std::nullptr_t = nullptr) {} static OpaquePtr make(PtrTy P) { OpaquePtr OP; OP.set(P); return OP; } - /// \brief Returns plain pointer to the entity pointed by this wrapper. + /// Returns plain pointer to the entity pointed by this wrapper. /// \tparam PointeeT Type of pointed entity. /// /// It is identical to getPtrAs<PointeeT*>. @@ -61,7 +68,7 @@ namespace clang { return get(); } - /// \brief Returns pointer converted to the specified type. + /// Returns pointer converted to the specified type. /// \tparam PtrT Result pointer type. There must be implicit conversion /// from PtrTy to PtrT. /// @@ -103,26 +110,32 @@ namespace clang { return *this; } }; -} + +} // namespace clang namespace llvm { + template <class T> - struct PointerLikeTypeTraits<clang::OpaquePtr<T> > { + struct PointerLikeTypeTraits<clang::OpaquePtr<T>> { + enum { NumLowBitsAvailable = 0 }; + static inline void *getAsVoidPointer(clang::OpaquePtr<T> P) { // FIXME: Doesn't work? return P.getAs< void >(); return P.getAsOpaquePtr(); } + static inline clang::OpaquePtr<T> getFromVoidPointer(void *P) { return clang::OpaquePtr<T>::getFromOpaquePtr(P); } - enum { NumLowBitsAvailable = 0 }; }; template <class T> - struct isPodLike<clang::OpaquePtr<T> > { static const bool value = true; }; -} + struct isPodLike<clang::OpaquePtr<T>> { static const bool value = true; }; + +} // namespace llvm namespace clang { + // Basic class DiagnosticBuilder; @@ -146,8 +159,7 @@ namespace clang { bool Invalid; public: - ActionResult(bool Invalid = false) - : Val(PtrTy()), Invalid(Invalid) {} + ActionResult(bool Invalid = false) : Val(PtrTy()), Invalid(Invalid) {} ActionResult(PtrTy val) : Val(val), Invalid(false) {} ActionResult(const DiagnosticBuilder &) : Val(PtrTy()), Invalid(true) {} @@ -178,17 +190,20 @@ namespace clang { // A pointer whose low bit is 1 if this result is invalid, 0 // otherwise. uintptr_t PtrWithInvalid; - typedef llvm::PointerLikeTypeTraits<PtrTy> PtrTraits; + + using PtrTraits = llvm::PointerLikeTypeTraits<PtrTy>; + public: ActionResult(bool Invalid = false) - : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) { } + : PtrWithInvalid(static_cast<uintptr_t>(Invalid)) {} ActionResult(PtrTy V) { void *VP = PtrTraits::getAsVoidPointer(V); PtrWithInvalid = reinterpret_cast<uintptr_t>(VP); assert((PtrWithInvalid & 0x01) == 0 && "Badly aligned pointer"); } - ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) { } + + ActionResult(const DiagnosticBuilder &) : PtrWithInvalid(0x01) {} // These two overloads prevent void* -> bool conversions. ActionResult(const void *) = delete; @@ -202,6 +217,7 @@ namespace clang { void *VP = reinterpret_cast<void *>(PtrWithInvalid & ~0x01); return PtrTraits::getFromVoidPointer(VP); } + template <typename T> T *getAs() { return static_cast<T*>(get()); } void set(PtrTy V) { @@ -229,8 +245,8 @@ namespace clang { /// An opaque type for threading parsed type information through the /// parser. - typedef OpaquePtr<QualType> ParsedType; - typedef UnionOpaquePtr<QualType> UnionParsedType; + using ParsedType = OpaquePtr<QualType>; + using UnionParsedType = UnionOpaquePtr<QualType>; // We can re-use the low bit of expression, statement, base, and // member-initializer pointers for the "invalid" flag of @@ -248,21 +264,21 @@ namespace clang { static const bool value = true; }; - typedef ActionResult<Expr*> ExprResult; - typedef ActionResult<Stmt*> StmtResult; - typedef ActionResult<ParsedType> TypeResult; - typedef ActionResult<CXXBaseSpecifier*> BaseResult; - typedef ActionResult<CXXCtorInitializer*> MemInitResult; + using ExprResult = ActionResult<Expr *>; + using StmtResult = ActionResult<Stmt *>; + using TypeResult = ActionResult<ParsedType>; + using BaseResult = ActionResult<CXXBaseSpecifier *>; + using MemInitResult = ActionResult<CXXCtorInitializer *>; - typedef ActionResult<Decl*> DeclResult; - typedef OpaquePtr<TemplateName> ParsedTemplateTy; - typedef UnionOpaquePtr<TemplateName> UnionParsedTemplateTy; + using DeclResult = ActionResult<Decl *>; + using ParsedTemplateTy = OpaquePtr<TemplateName>; + using UnionParsedTemplateTy = UnionOpaquePtr<TemplateName>; - typedef MutableArrayRef<Expr*> MultiExprArg; - typedef MutableArrayRef<Stmt*> MultiStmtArg; - typedef MutableArrayRef<ParsedTemplateArgument> ASTTemplateArgsPtr; - typedef MutableArrayRef<ParsedType> MultiTypeArg; - typedef MutableArrayRef<TemplateParameterList*> MultiTemplateParamsArg; + using MultiExprArg = MutableArrayRef<Expr *>; + using MultiStmtArg = MutableArrayRef<Stmt *>; + using ASTTemplateArgsPtr = MutableArrayRef<ParsedTemplateArgument>; + using MultiTypeArg = MutableArrayRef<ParsedType>; + using MultiTemplateParamsArg = MutableArrayRef<TemplateParameterList *>; inline ExprResult ExprError() { return ExprResult(true); } inline StmtResult StmtError() { return StmtResult(true); } @@ -282,6 +298,7 @@ namespace clang { assert(!R.isInvalid() && "operation was asserted to never fail!"); return R.get(); } -} -#endif +} // namespace clang + +#endif // LLVM_CLANG_SEMA_OWNERSHIP_H diff --git a/include/clang/Sema/AttributeList.h b/include/clang/Sema/ParsedAttr.h index 4e806116c4d9b..3f293247787ca 100644 --- a/include/clang/Sema/AttributeList.h +++ b/include/clang/Sema/ParsedAttr.h @@ -1,4 +1,4 @@ -//===--- AttributeList.h - Parsed attribute sets ----------------*- C++ -*-===// +//======- ParsedAttr.h - Parsed attribute sets ------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file defines the AttributeList class, which is used to collect +// This file defines the ParsedAttr class, which is used to collect // parsed attributes. // //===----------------------------------------------------------------------===// @@ -18,45 +18,54 @@ #include "clang/Basic/AttrSubjectMatchRules.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Sema/Ownership.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/TinyPtrVector.h" #include "llvm/Support/Allocator.h" +#include "llvm/Support/VersionTuple.h" #include <cassert> +#include <cstddef> +#include <cstring> +#include <utility> namespace clang { - class ASTContext; - class IdentifierInfo; - class Expr; -/// \brief Represents information about a change in availability for +class ASTContext; +class Decl; +class Expr; +class IdentifierInfo; +class LangOptions; + +/// Represents information about a change in availability for /// an entity, which is part of the encoding of the 'availability' /// attribute. struct AvailabilityChange { - /// \brief The location of the keyword indicating the kind of change. + /// The location of the keyword indicating the kind of change. SourceLocation KeywordLoc; - /// \brief The version number at which the change occurred. + /// The version number at which the change occurred. VersionTuple Version; - /// \brief The source range covering the version number. + /// The source range covering the version number. SourceRange VersionRange; - /// \brief Determine whether this availability change is valid. + /// Determine whether this availability change is valid. bool isValid() const { return !Version.empty(); } }; namespace { + enum AvailabilitySlot { IntroducedSlot, DeprecatedSlot, ObsoletedSlot, NumAvailabilitySlots }; -/// Describes the trailing object for Availability attribute in AttributeList. +/// Describes the trailing object for Availability attribute in ParsedAttr. struct AvailabilityData { AvailabilityChange Changes[NumAvailabilitySlots]; SourceLocation StrictLoc; const Expr *Replacement; + AvailabilityData(const AvailabilityChange &Introduced, const AvailabilityChange &Deprecated, const AvailabilityChange &Obsoleted, @@ -67,9 +76,10 @@ struct AvailabilityData { Changes[ObsoletedSlot] = Obsoleted; } }; -} -/// \brief Wraps an identifier and optional source location for the identifier. +} // namespace + +/// Wraps an identifier and optional source location for the identifier. struct IdentifierLoc { SourceLocation Loc; IdentifierInfo *Ident; @@ -78,12 +88,12 @@ struct IdentifierLoc { IdentifierInfo *Ident); }; -/// \brief A union of the various pointer types that can be passed to an -/// AttributeList as an argument. -typedef llvm::PointerUnion<Expr*, IdentifierLoc*> ArgsUnion; -typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector; +/// A union of the various pointer types that can be passed to an +/// ParsedAttr as an argument. +using ArgsUnion = llvm::PointerUnion<Expr *, IdentifierLoc *>; +using ArgsVector = llvm::SmallVector<ArgsUnion, 12U>; -/// AttributeList - Represents a syntactic attribute. +/// ParsedAttr - Represents a syntactic attribute. /// /// For a GNU attribute, there are four forms of this construct: /// @@ -92,24 +102,31 @@ typedef llvm::SmallVector<ArgsUnion, 12U> ArgsVector; /// 3: __attribute__(( format(printf, 1, 2) )). ParmName/Args/NumArgs all used. /// 4: __attribute__(( aligned(16) )). ParmName is unused, Args/Num used. /// -class AttributeList { // TODO: This should really be called ParsedAttribute +class ParsedAttr { // TODO: This should really be called ParsedAttribute public: /// The style used to specify an attribute. enum Syntax { /// __attribute__((...)) AS_GNU, + /// [[...]] AS_CXX11, + /// [[...]] AS_C2x, + /// __declspec(...) AS_Declspec, + /// [uuid("...")] class Foo AS_Microsoft, + /// __ptr16, alignas(...), etc. AS_Keyword, + /// #pragma ... AS_Pragma, + // Note TableGen depends on the order above. Do not add or change the order // without adding related code to TableGen/ClangAttrEmitter.cpp. /// Context-sensitive version of a keyword attribute. @@ -159,18 +176,12 @@ private: /// A cached value. mutable unsigned ProcessingCache : 8; - /// \brief The location of the 'unavailable' keyword in an + /// The location of the 'unavailable' keyword in an /// availability attribute. SourceLocation UnavailableLoc; const Expr *MessageExpr; - /// The next attribute in the current position. - AttributeList *NextInPosition; - - /// The next attribute allocated in the current Pool. - AttributeList *NextInPool; - /// Arguments, if any, are stored immediately following the object. ArgsUnion *getArgsBuffer() { return reinterpret_cast<ArgsUnion *>(this + 1); } ArgsUnion const *getArgsBuffer() const { @@ -194,83 +205,43 @@ public: }; struct PropertyData { IdentifierInfo *GetterId, *SetterId; + PropertyData(IdentifierInfo *getterId, IdentifierInfo *setterId) - : GetterId(getterId), SetterId(setterId) {} + : GetterId(getterId), SetterId(setterId) {} }; private: - /// Type tag information is stored immediately following the arguments, if - /// any, at the end of the object. They are mutually exlusive with - /// availability slots. - TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { - return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs); - } - - const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { - return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer() - + NumArgs); - } - - /// The type buffer immediately follows the object and are mutually exclusive - /// with arguments. - ParsedType &getTypeBuffer() { - return *reinterpret_cast<ParsedType *>(this + 1); - } - - const ParsedType &getTypeBuffer() const { - return *reinterpret_cast<const ParsedType *>(this + 1); - } - - /// The property data immediately follows the object is is mutually exclusive - /// with arguments. - PropertyData &getPropertyDataBuffer() { - assert(IsProperty); - return *reinterpret_cast<PropertyData*>(this + 1); - } - - const PropertyData &getPropertyDataBuffer() const { - assert(IsProperty); - return *reinterpret_cast<const PropertyData*>(this + 1); - } - - AttributeList(const AttributeList &) = delete; - void operator=(const AttributeList &) = delete; - void operator delete(void *) = delete; - ~AttributeList() = delete; - - size_t allocated_size() const; + friend class AttributeFactory; + friend class AttributePool; /// Constructor for attributes with expression arguments. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - Syntax syntaxUsed, SourceLocation ellipsisLoc) - : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), - SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), - IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), - HasParsedType(false), HasProcessingCache(false), - NextInPosition(nullptr), NextInPool(nullptr) { + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ArgsUnion *args, unsigned numArgs, Syntax syntaxUsed, + SourceLocation ellipsisLoc) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), EllipsisLoc(ellipsisLoc), NumArgs(numArgs), + SyntaxUsed(syntaxUsed), Invalid(false), UsedAsTypeAttr(false), + IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), + HasParsedType(false), HasProcessingCache(false) { if (numArgs) memcpy(getArgsBuffer(), args, numArgs * sizeof(ArgsUnion)); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } /// Constructor for availability attributes. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Parm, const AvailabilityChange &introduced, - const AvailabilityChange &deprecated, - const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *messageExpr, - Syntax syntaxUsed, SourceLocation strict, - const Expr *replacementExpr) - : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(true), - IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), - HasProcessingCache(false), UnavailableLoc(unavailable), - MessageExpr(messageExpr), NextInPosition(nullptr), NextInPool(nullptr) { + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Parm, const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, SourceLocation unavailable, + const Expr *messageExpr, Syntax syntaxUsed, SourceLocation strict, + const Expr *replacementExpr) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(true), + IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), + HasProcessingCache(false), UnavailableLoc(unavailable), + MessageExpr(messageExpr) { ArgsUnion PVal(Parm); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); new (getAvailabilityData()) AvailabilityData( @@ -279,17 +250,15 @@ private: } /// Constructor for objc_bridge_related attributes. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Parm1, - IdentifierLoc *Parm2, - IdentifierLoc *Parm3, - Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(3), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), - HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Parm1, IdentifierLoc *Parm2, IdentifierLoc *Parm3, + Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), NumArgs(3), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(false), + HasProcessingCache(false) { ArgsUnion *Args = getArgsBuffer(); Args[0] = Parm1; Args[1] = Parm2; @@ -298,15 +267,15 @@ private: } /// Constructor for type_tag_for_datatype attribute. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *ArgKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(1), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), - HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *ArgKind, ParsedType matchingCType, + bool layoutCompatible, bool mustBeNull, Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), NumArgs(1), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(true), IsProperty(false), HasParsedType(false), + HasProcessingCache(false) { ArgsUnion PVal(ArgKind); memcpy(getArgsBuffer(), &PVal, sizeof(ArgsUnion)); TypeTagForDatatypeData &ExtraData = getTypeTagForDatatypeDataSlot(); @@ -317,36 +286,72 @@ private: } /// Constructor for attributes with a single type argument. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, Syntax syntaxUsed) + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ParsedType typeArg, Syntax syntaxUsed) : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), + ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), IsTypeTagForDatatype(false), IsProperty(false), HasParsedType(true), - HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr){ + HasProcessingCache(false) { new (&getTypeBuffer()) ParsedType(typeArg); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } /// Constructor for microsoft __declspec(property) attribute. - AttributeList(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - Syntax syntaxUsed) - : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), - ScopeLoc(scopeLoc), EllipsisLoc(), NumArgs(0), SyntaxUsed(syntaxUsed), - Invalid(false), UsedAsTypeAttr(false), IsAvailability(false), - IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), - HasProcessingCache(false), NextInPosition(nullptr), NextInPool(nullptr) { + ParsedAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + Syntax syntaxUsed) + : AttrName(attrName), ScopeName(scopeName), AttrRange(attrRange), + ScopeLoc(scopeLoc), NumArgs(0), SyntaxUsed(syntaxUsed), Invalid(false), + UsedAsTypeAttr(false), IsAvailability(false), + IsTypeTagForDatatype(false), IsProperty(true), HasParsedType(false), + HasProcessingCache(false) { new (&getPropertyDataBuffer()) PropertyData(getterId, setterId); AttrKind = getKind(getName(), getScopeName(), syntaxUsed); } - friend class AttributePool; - friend class AttributeFactory; + /// Type tag information is stored immediately following the arguments, if + /// any, at the end of the object. They are mutually exclusive with + /// availability slots. + TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() { + return *reinterpret_cast<TypeTagForDatatypeData*>(getArgsBuffer()+NumArgs); + } + const TypeTagForDatatypeData &getTypeTagForDatatypeDataSlot() const { + return *reinterpret_cast<const TypeTagForDatatypeData*>(getArgsBuffer() + + NumArgs); + } + + /// The type buffer immediately follows the object and are mutually exclusive + /// with arguments. + ParsedType &getTypeBuffer() { + return *reinterpret_cast<ParsedType *>(this + 1); + } + const ParsedType &getTypeBuffer() const { + return *reinterpret_cast<const ParsedType *>(this + 1); + } + + /// The property data immediately follows the object is is mutually exclusive + /// with arguments. + PropertyData &getPropertyDataBuffer() { + assert(IsProperty); + return *reinterpret_cast<PropertyData*>(this + 1); + } + const PropertyData &getPropertyDataBuffer() const { + assert(IsProperty); + return *reinterpret_cast<const PropertyData*>(this + 1); + } + + size_t allocated_size() const; public: + ParsedAttr(const ParsedAttr &) = delete; + ParsedAttr &operator=(const ParsedAttr &) = delete; + ~ParsedAttr() = delete; + + void operator delete(void *) = delete; + enum Kind { #define PARSED_ATTR(NAME) AT_##NAME, #include "clang/Sema/AttrParsedAttrList.inc" @@ -377,12 +382,15 @@ public: bool isDeclspecAttribute() const { return SyntaxUsed == AS_Declspec; } bool isMicrosoftAttribute() const { return SyntaxUsed == AS_Microsoft; } + bool isCXX11Attribute() const { return SyntaxUsed == AS_CXX11 || isAlignasAttribute(); } + bool isC2xAttribute() const { return SyntaxUsed == AS_C2x; } + bool isKeywordAttribute() const { return SyntaxUsed == AS_Keyword || SyntaxUsed == AS_ContextSensitiveKeyword; } @@ -395,10 +403,12 @@ public: void setInvalid(bool b = true) const { Invalid = b; } bool hasProcessingCache() const { return HasProcessingCache; } + unsigned getProcessingCache() const { assert(hasProcessingCache()); return ProcessingCache; } + void setProcessingCache(unsigned value) const { ProcessingCache = value; HasProcessingCache = true; @@ -414,9 +424,6 @@ public: static Kind getKind(const IdentifierInfo *Name, const IdentifierInfo *Scope, Syntax SyntaxUsed); - AttributeList *getNext() const { return NextInPosition; } - void setNext(AttributeList *N) { NextInPosition = N; } - /// getNumArgs - Return the number of actual arguments to this attribute. unsigned getNumArgs() const { return NumArgs; } @@ -429,6 +436,7 @@ public: bool isArgExpr(unsigned Arg) const { return Arg < NumArgs && getArg(Arg).is<Expr*>(); } + Expr *getArgAsExpr(unsigned Arg) const { return getArg(Arg).get<Expr*>(); } @@ -436,6 +444,7 @@ public: bool isArgIdent(unsigned Arg) const { return Arg < NumArgs && getArg(Arg).is<IdentifierLoc*>(); } + IdentifierLoc *getArgAsIdent(unsigned Arg) const { return getArg(Arg).get<IdentifierLoc*>(); } @@ -503,7 +512,7 @@ public: return getPropertyDataBuffer(); } - /// \brief Get an index into the attribute spelling list + /// Get an index into the attribute spelling list /// defined in Attr.td. This index is used by an attribute /// to pretty print itself. unsigned getAttributeSpellingListIndex() const; @@ -526,7 +535,7 @@ public: bool isKnownToGCC() const; bool isSupportedByPragmaAttribute() const; - /// \brief If the parsed attribute has a semantic equivalent, and it would + /// If the parsed attribute has a semantic equivalent, and it would /// have a semantic Spelling enumeration (due to having semantically-distinct /// spelling variations), return the value of that semantic spelling. If the /// parsed attribute does not have a semantic equivalent, or would not have @@ -534,6 +543,7 @@ public: unsigned getSemanticSpelling() const; }; +class AttributePool; /// A factory, from which one makes pools, from which one creates /// individual attributes which are deallocated with the pool. /// @@ -545,18 +555,17 @@ public: /// The required allocation size of an availability attribute, /// which we want to ensure is a multiple of sizeof(void*). AvailabilityAllocSize = - sizeof(AttributeList) - + ((sizeof(AvailabilityData) + sizeof(void*) + sizeof(ArgsUnion) - 1) - / sizeof(void*) * sizeof(void*)), - TypeTagForDatatypeAllocSize = - sizeof(AttributeList) - + (sizeof(AttributeList::TypeTagForDatatypeData) + sizeof(void *) + - sizeof(ArgsUnion) - 1) - / sizeof(void*) * sizeof(void*), + sizeof(ParsedAttr) + + ((sizeof(AvailabilityData) + sizeof(void *) + sizeof(ArgsUnion) - 1) / + sizeof(void *) * sizeof(void *)), + TypeTagForDatatypeAllocSize = sizeof(ParsedAttr) + + (sizeof(ParsedAttr::TypeTagForDatatypeData) + + sizeof(void *) + sizeof(ArgsUnion) - 1) / + sizeof(void *) * sizeof(void *), PropertyAllocSize = - sizeof(AttributeList) - + (sizeof(AttributeList::PropertyData) + sizeof(void *) - 1) - / sizeof(void*) * sizeof(void*) + sizeof(ParsedAttr) + + (sizeof(ParsedAttr::PropertyData) + sizeof(void *) - 1) / + sizeof(void *) * sizeof(void *) }; private: @@ -567,14 +576,14 @@ private: /// attribute that needs more than that; on x86-64 you'd need 10 /// expression arguments, and on i386 you'd need 19. InlineFreeListsCapacity = - 1 + (AvailabilityAllocSize - sizeof(AttributeList)) / sizeof(void*) + 1 + (AvailabilityAllocSize - sizeof(ParsedAttr)) / sizeof(void *) }; llvm::BumpPtrAllocator Alloc; /// Free lists. The index is determined by the following formula: - /// (size - sizeof(AttributeList)) / sizeof(void*) - SmallVector<AttributeList*, InlineFreeListsCapacity> FreeLists; + /// (size - sizeof(ParsedAttr)) / sizeof(void*) + SmallVector<SmallVector<ParsedAttr *, 8>, InlineFreeListsCapacity> FreeLists; // The following are the private interface used by AttributePool. friend class AttributePool; @@ -582,12 +591,14 @@ private: /// Allocate an attribute of the given size. void *allocate(size_t size); + void deallocate(ParsedAttr *AL); + /// Reclaim all the attributes in the given pool chain, which is /// non-empty. Note that the current implementation is safe /// against reclaiming things which were not actually allocated /// with the allocator, although of course it's important to make /// sure that their allocator lives at least as long as this one. - void reclaimPool(AttributeList *head); + void reclaimPool(AttributePool &head); public: AttributeFactory(); @@ -595,294 +606,297 @@ public: }; class AttributePool { + friend class AttributeFactory; AttributeFactory &Factory; - AttributeList *Head; + llvm::TinyPtrVector<ParsedAttr *> Attrs; void *allocate(size_t size) { return Factory.allocate(size); } - AttributeList *add(AttributeList *attr) { - // We don't care about the order of the pool. - attr->NextInPool = Head; - Head = attr; + ParsedAttr *add(ParsedAttr *attr) { + Attrs.push_back(attr); return attr; } - void takePool(AttributeList *pool); + void remove(ParsedAttr *attr) { + assert(llvm::is_contained(Attrs, attr) && + "Can't take attribute from a pool that doesn't own it!"); + Attrs.erase(llvm::find(Attrs, attr)); + } + + void takePool(AttributePool &pool); public: /// Create a new pool for a factory. - AttributePool(AttributeFactory &factory) : Factory(factory), Head(nullptr) {} + AttributePool(AttributeFactory &factory) : Factory(factory) {} AttributePool(const AttributePool &) = delete; + ~AttributePool() { Factory.reclaimPool(*this); } + /// Move the given pool's allocations to this pool. - AttributePool(AttributePool &&pool) : Factory(pool.Factory), Head(pool.Head) { - pool.Head = nullptr; - } + AttributePool(AttributePool &&pool) = default; AttributeFactory &getFactory() const { return Factory; } void clear() { - if (Head) { - Factory.reclaimPool(Head); - Head = nullptr; - } + Factory.reclaimPool(*this); + Attrs.clear(); } /// Take the given pool's allocations and add them to this pool. void takeAllFrom(AttributePool &pool) { - if (pool.Head) { - takePool(pool.Head); - pool.Head = nullptr; - } - } - - ~AttributePool() { - if (Head) Factory.reclaimPool(Head); - } - - AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - AttributeList::Syntax syntax, - SourceLocation ellipsisLoc = SourceLocation()) { - void *memory = allocate(sizeof(AttributeList) - + numArgs * sizeof(ArgsUnion)); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - args, numArgs, syntax, - ellipsisLoc)); - } - - AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param, - const AvailabilityChange &introduced, - const AvailabilityChange &deprecated, - const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *MessageExpr, - AttributeList::Syntax syntax, - SourceLocation strict, const Expr *ReplacementExpr) { + takePool(pool); + pool.Attrs.clear(); + } + + ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ArgsUnion *args, unsigned numArgs, + ParsedAttr::Syntax syntax, + SourceLocation ellipsisLoc = SourceLocation()) { + void *memory = allocate(sizeof(ParsedAttr) + numArgs * sizeof(ArgsUnion)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + args, numArgs, syntax, ellipsisLoc)); + } + + ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param, const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, const Expr *MessageExpr, + ParsedAttr::Syntax syntax, SourceLocation strict, + const Expr *ReplacementExpr) { void *memory = allocate(AttributeFactory::AvailabilityAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - Param, introduced, deprecated, - obsoleted, unavailable, MessageExpr, - syntax, strict, ReplacementExpr)); - } - - AttributeList *create(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param1, - IdentifierLoc *Param2, - IdentifierLoc *Param3, - AttributeList::Syntax syntax) { - size_t size = sizeof(AttributeList) + 3 * sizeof(ArgsUnion); + return add(new (memory) ParsedAttr( + attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, + obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr)); + } + + ParsedAttr *create(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param1, IdentifierLoc *Param2, + IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { + size_t size = sizeof(ParsedAttr) + 3 * sizeof(ArgsUnion); void *memory = allocate(size); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - Param1, Param2, Param3, - syntax)); - } - - AttributeList *createTypeTagForDatatype( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *argumentKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, - AttributeList::Syntax syntax) { + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax)); + } + + ParsedAttr * + createTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *argumentKind, + ParsedType matchingCType, bool layoutCompatible, + bool mustBeNull, ParsedAttr::Syntax syntax) { void *memory = allocate(AttributeFactory::TypeTagForDatatypeAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - argumentKind, matchingCType, - layoutCompatible, mustBeNull, - syntax)); - } - - AttributeList *createTypeAttribute( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, AttributeList::Syntax syntaxUsed) { - void *memory = allocate(sizeof(AttributeList) + sizeof(void *)); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - typeArg, syntaxUsed)); - } - - AttributeList *createPropertyAttribute( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - AttributeList::Syntax syntaxUsed) { + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax)); + } + + ParsedAttr *createTypeAttribute(IdentifierInfo *attrName, + SourceRange attrRange, + IdentifierInfo *scopeName, + SourceLocation scopeLoc, ParsedType typeArg, + ParsedAttr::Syntax syntaxUsed) { + void *memory = allocate(sizeof(ParsedAttr) + sizeof(void *)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + typeArg, syntaxUsed)); + } + + ParsedAttr * + createPropertyAttribute(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + ParsedAttr::Syntax syntaxUsed) { void *memory = allocate(AttributeFactory::PropertyAllocSize); - return add(new (memory) AttributeList(attrName, attrRange, - scopeName, scopeLoc, - getterId, setterId, - syntaxUsed)); + return add(new (memory) ParsedAttr(attrName, attrRange, scopeName, scopeLoc, + getterId, setterId, syntaxUsed)); } }; -/// ParsedAttributes - A collection of parsed attributes. Currently -/// we don't differentiate between the various attribute syntaxes, -/// which is basically silly. -/// -/// Right now this is a very lightweight container, but the expectation -/// is that this will become significantly more serious. -class ParsedAttributes { +class ParsedAttributesView { + using VecTy = llvm::TinyPtrVector<ParsedAttr *>; + using SizeType = decltype(std::declval<VecTy>().size()); + public: - ParsedAttributes(AttributeFactory &factory) - : pool(factory), list(nullptr) { + bool empty() const { return AttrList.empty(); } + SizeType size() const { return AttrList.size(); } + ParsedAttr &operator[](SizeType pos) { return *AttrList[pos]; } + const ParsedAttr &operator[](SizeType pos) const { return *AttrList[pos]; } + + void addAtStart(ParsedAttr *newAttr) { + assert(newAttr); + AttrList.insert(AttrList.begin(), newAttr); + } + void addAtEnd(ParsedAttr *newAttr) { + assert(newAttr); + AttrList.push_back(newAttr); } - ParsedAttributes(const ParsedAttributes &) = delete; + void remove(ParsedAttr *ToBeRemoved) { + assert(is_contained(AttrList, ToBeRemoved) && + "Cannot remove attribute that isn't in the list"); + AttrList.erase(llvm::find(AttrList, ToBeRemoved)); + } - AttributePool &getPool() const { return pool; } + void clearListOnly() { AttrList.clear(); } - bool empty() const { return list == nullptr; } + struct iterator : llvm::iterator_adaptor_base<iterator, VecTy::iterator, + std::random_access_iterator_tag, + ParsedAttr> { + iterator() : iterator_adaptor_base(nullptr) {} + iterator(VecTy::iterator I) : iterator_adaptor_base(I) {} + reference operator*() { return **I; } + friend class ParsedAttributesView; + }; + struct const_iterator + : llvm::iterator_adaptor_base<const_iterator, VecTy::const_iterator, + std::random_access_iterator_tag, + ParsedAttr> { + const_iterator() : iterator_adaptor_base(nullptr) {} + const_iterator(VecTy::const_iterator I) : iterator_adaptor_base(I) {} + + reference operator*() const { return **I; } + friend class ParsedAttributesView; + }; - void add(AttributeList *newAttr) { - assert(newAttr); - assert(newAttr->getNext() == nullptr); - newAttr->setNext(list); - list = newAttr; + void addAll(iterator B, iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); } - void addAll(AttributeList *newList) { - if (!newList) return; - - AttributeList *lastInNewList = newList; - while (AttributeList *next = lastInNewList->getNext()) - lastInNewList = next; + void addAll(const_iterator B, const_iterator E) { + AttrList.insert(AttrList.begin(), B.I, E.I); + } - lastInNewList->setNext(list); - list = newList; + void addAllAtEnd(iterator B, iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); } - void addAllAtEnd(AttributeList *newList) { - if (!list) { - list = newList; - return; - } + void addAllAtEnd(const_iterator B, const_iterator E) { + AttrList.insert(AttrList.end(), B.I, E.I); + } - AttributeList *lastInList = list; - while (AttributeList *next = lastInList->getNext()) - lastInList = next; + iterator begin() { return iterator(AttrList.begin()); } + const_iterator begin() const { return const_iterator(AttrList.begin()); } + iterator end() { return iterator(AttrList.end()); } + const_iterator end() const { return const_iterator(AttrList.end()); } - lastInList->setNext(newList); + bool hasAttribute(ParsedAttr::Kind K) const { + return llvm::any_of( + AttrList, [K](const ParsedAttr *AL) { return AL->getKind() == K; }); } - void set(AttributeList *newList) { - list = newList; - } +private: + VecTy AttrList; +}; + +/// ParsedAttributes - A collection of parsed attributes. Currently +/// we don't differentiate between the various attribute syntaxes, +/// which is basically silly. +/// +/// Right now this is a very lightweight container, but the expectation +/// is that this will become significantly more serious. +class ParsedAttributes : public ParsedAttributesView { +public: + ParsedAttributes(AttributeFactory &factory) : pool(factory) {} + ParsedAttributes(const ParsedAttributes &) = delete; + + AttributePool &getPool() const { return pool; } void takeAllFrom(ParsedAttributes &attrs) { - addAll(attrs.list); - attrs.list = nullptr; + addAll(attrs.begin(), attrs.end()); + attrs.clearListOnly(); pool.takeAllFrom(attrs.pool); } - void clear() { list = nullptr; pool.clear(); } - AttributeList *getList() const { return list; } - - void clearListOnly() { list = nullptr; } - - /// Returns a reference to the attribute list. Try not to introduce - /// dependencies on this method, it may not be long-lived. - AttributeList *&getListRef() { return list; } + void clear() { + clearListOnly(); + pool.clear(); + } /// Add attribute with expression arguments. - AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ArgsUnion *args, unsigned numArgs, - AttributeList::Syntax syntax, - SourceLocation ellipsisLoc = SourceLocation()) { - AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, args, numArgs, - syntax, ellipsisLoc); - add(attr); + ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ArgsUnion *args, unsigned numArgs, + ParsedAttr::Syntax syntax, + SourceLocation ellipsisLoc = SourceLocation()) { + ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, + args, numArgs, syntax, ellipsisLoc); + addAtStart(attr); return attr; } /// Add availability attribute. - AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param, - const AvailabilityChange &introduced, - const AvailabilityChange &deprecated, - const AvailabilityChange &obsoleted, - SourceLocation unavailable, - const Expr *MessageExpr, - AttributeList::Syntax syntax, - SourceLocation strict, const Expr *ReplacementExpr) { - AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, Param, introduced, - deprecated, obsoleted, unavailable, MessageExpr, syntax, - strict, ReplacementExpr); - add(attr); + ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param, const AvailabilityChange &introduced, + const AvailabilityChange &deprecated, + const AvailabilityChange &obsoleted, + SourceLocation unavailable, const Expr *MessageExpr, + ParsedAttr::Syntax syntax, SourceLocation strict, + const Expr *ReplacementExpr) { + ParsedAttr *attr = pool.create( + attrName, attrRange, scopeName, scopeLoc, Param, introduced, deprecated, + obsoleted, unavailable, MessageExpr, syntax, strict, ReplacementExpr); + addAtStart(attr); return attr; } /// Add objc_bridge_related attribute. - AttributeList *addNew(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *Param1, - IdentifierLoc *Param2, - IdentifierLoc *Param3, - AttributeList::Syntax syntax) { - AttributeList *attr = - pool.create(attrName, attrRange, scopeName, scopeLoc, - Param1, Param2, Param3, syntax); - add(attr); + ParsedAttr *addNew(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *Param1, IdentifierLoc *Param2, + IdentifierLoc *Param3, ParsedAttr::Syntax syntax) { + ParsedAttr *attr = pool.create(attrName, attrRange, scopeName, scopeLoc, + Param1, Param2, Param3, syntax); + addAtStart(attr); return attr; } /// Add type_tag_for_datatype attribute. - AttributeList *addNewTypeTagForDatatype( - IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierLoc *argumentKind, ParsedType matchingCType, - bool layoutCompatible, bool mustBeNull, - AttributeList::Syntax syntax) { - AttributeList *attr = - pool.createTypeTagForDatatype(attrName, attrRange, - scopeName, scopeLoc, - argumentKind, matchingCType, - layoutCompatible, mustBeNull, syntax); - add(attr); + ParsedAttr * + addNewTypeTagForDatatype(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierLoc *argumentKind, + ParsedType matchingCType, bool layoutCompatible, + bool mustBeNull, ParsedAttr::Syntax syntax) { + ParsedAttr *attr = pool.createTypeTagForDatatype( + attrName, attrRange, scopeName, scopeLoc, argumentKind, matchingCType, + layoutCompatible, mustBeNull, syntax); + addAtStart(attr); return attr; } /// Add an attribute with a single type argument. - AttributeList * - addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - ParsedType typeArg, AttributeList::Syntax syntaxUsed) { - AttributeList *attr = - pool.createTypeAttribute(attrName, attrRange, scopeName, scopeLoc, - typeArg, syntaxUsed); - add(attr); + ParsedAttr *addNewTypeAttr(IdentifierInfo *attrName, SourceRange attrRange, + IdentifierInfo *scopeName, SourceLocation scopeLoc, + ParsedType typeArg, + ParsedAttr::Syntax syntaxUsed) { + ParsedAttr *attr = pool.createTypeAttribute(attrName, attrRange, scopeName, + scopeLoc, typeArg, syntaxUsed); + addAtStart(attr); return attr; } /// Add microsoft __delspec(property) attribute. - AttributeList * + ParsedAttr * addNewPropertyAttr(IdentifierInfo *attrName, SourceRange attrRange, - IdentifierInfo *scopeName, SourceLocation scopeLoc, - IdentifierInfo *getterId, IdentifierInfo *setterId, - AttributeList::Syntax syntaxUsed) { - AttributeList *attr = + IdentifierInfo *scopeName, SourceLocation scopeLoc, + IdentifierInfo *getterId, IdentifierInfo *setterId, + ParsedAttr::Syntax syntaxUsed) { + ParsedAttr *attr = pool.createPropertyAttribute(attrName, attrRange, scopeName, scopeLoc, getterId, setterId, syntaxUsed); - add(attr); + addAtStart(attr); return attr; } private: mutable AttributePool pool; - AttributeList *list; }; /// These constants match the enumerated choices of @@ -910,9 +924,8 @@ enum AttributeDeclKind { ExpectedFunctionVariableOrClass, ExpectedKernelFunction, ExpectedFunctionWithProtoType, - ExpectedForMaybeUnused, }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_ATTRIBUTELIST_H diff --git a/include/clang/Sema/ParsedTemplate.h b/include/clang/Sema/ParsedTemplate.h index 01a4ab3f37a51..f79157ba813e6 100644 --- a/include/clang/Sema/ParsedTemplate.h +++ b/include/clang/Sema/ParsedTemplate.h @@ -26,32 +26,32 @@ #include <new> namespace clang { - /// \brief Represents the parsed form of a C++ template argument. + /// Represents the parsed form of a C++ template argument. class ParsedTemplateArgument { public: - /// \brief Describes the kind of template argument that was parsed. + /// Describes the kind of template argument that was parsed. enum KindType { - /// \brief A template type parameter, stored as a type. + /// A template type parameter, stored as a type. Type, - /// \brief A non-type template parameter, stored as an expression. + /// A non-type template parameter, stored as an expression. NonType, - /// \brief A template template argument, stored as a template name. + /// A template template argument, stored as a template name. Template }; - /// \brief Build an empty template argument. + /// Build an empty template argument. /// /// This template argument is invalid. ParsedTemplateArgument() : Kind(Type), Arg(nullptr) { } - /// \brief Create a template type argument or non-type template argument. + /// Create a template type argument or non-type template argument. /// /// \param Arg the template type argument or non-type template argument. /// \param Loc the location of the type. ParsedTemplateArgument(KindType Kind, void *Arg, SourceLocation Loc) : Kind(Kind), Arg(Arg), Loc(Loc) { } - /// \brief Create a template template argument. + /// Create a template template argument. /// /// \param SS the C++ scope specifier that precedes the template name, if /// any. @@ -67,34 +67,34 @@ namespace clang { Arg(Template.getAsOpaquePtr()), SS(SS), Loc(TemplateLoc), EllipsisLoc() { } - /// \brief Determine whether the given template argument is invalid. + /// Determine whether the given template argument is invalid. bool isInvalid() const { return Arg == nullptr; } - /// \brief Determine what kind of template argument we have. + /// Determine what kind of template argument we have. KindType getKind() const { return Kind; } - /// \brief Retrieve the template type argument's type. + /// Retrieve the template type argument's type. ParsedType getAsType() const { assert(Kind == Type && "Not a template type argument"); return ParsedType::getFromOpaquePtr(Arg); } - /// \brief Retrieve the non-type template argument's expression. + /// Retrieve the non-type template argument's expression. Expr *getAsExpr() const { assert(Kind == NonType && "Not a non-type template argument"); return static_cast<Expr*>(Arg); } - /// \brief Retrieve the template template argument's template name. + /// Retrieve the template template argument's template name. ParsedTemplateTy getAsTemplate() const { assert(Kind == Template && "Not a template template argument"); return ParsedTemplateTy::getFromOpaquePtr(Arg); } - /// \brief Retrieve the location of the template argument. + /// Retrieve the location of the template argument. SourceLocation getLocation() const { return Loc; } - /// \brief Retrieve the nested-name-specifier that precedes the template + /// Retrieve the nested-name-specifier that precedes the template /// name in a template template argument. const CXXScopeSpec &getScopeSpec() const { assert(Kind == Template && @@ -102,7 +102,7 @@ namespace clang { return SS; } - /// \brief Retrieve the location of the ellipsis that makes a template + /// Retrieve the location of the ellipsis that makes a template /// template argument into a pack expansion. SourceLocation getEllipsisLoc() const { assert(Kind == Template && @@ -110,7 +110,7 @@ namespace clang { return EllipsisLoc; } - /// \brief Retrieve a pack expansion of the given template template + /// Retrieve a pack expansion of the given template template /// argument. /// /// \param EllipsisLoc The location of the ellipsis. @@ -120,24 +120,24 @@ namespace clang { private: KindType Kind; - /// \brief The actual template argument representation, which may be + /// The actual template argument representation, which may be /// an \c Sema::TypeTy* (for a type), an Expr* (for an /// expression), or an Sema::TemplateTy (for a template). void *Arg; - /// \brief The nested-name-specifier that can accompany a template template + /// The nested-name-specifier that can accompany a template template /// argument. CXXScopeSpec SS; - /// \brief the location of the template argument. + /// the location of the template argument. SourceLocation Loc; - /// \brief The ellipsis location that can accompany a template template + /// The ellipsis location that can accompany a template template /// argument (turning it into a template template argument expansion). SourceLocation EllipsisLoc; }; - /// \brief Information about a template-id annotation + /// Information about a template-id annotation /// token. /// /// A template-id annotation token contains the template declaration, @@ -149,7 +149,7 @@ namespace clang { : private llvm::TrailingObjects<TemplateIdAnnotation, ParsedTemplateArgument> { friend TrailingObjects; - /// \brief The nested-name-specifier that precedes the template name. + /// The nested-name-specifier that precedes the template name. CXXScopeSpec SS; /// TemplateKWLoc - The location of the template keyword. @@ -184,12 +184,12 @@ namespace clang { /// NumArgs - The number of template arguments. unsigned NumArgs; - /// \brief Retrieves a pointer to the template arguments + /// Retrieves a pointer to the template arguments ParsedTemplateArgument *getTemplateArgs() { return getTrailingObjects<ParsedTemplateArgument>(); } - /// \brief Creates a new TemplateIdAnnotation with NumArgs arguments and + /// Creates a new TemplateIdAnnotation with NumArgs arguments and /// appends it to List. static TemplateIdAnnotation * Create(CXXScopeSpec SS, SourceLocation TemplateKWLoc, @@ -199,8 +199,7 @@ namespace clang { SourceLocation LAngleLoc, SourceLocation RAngleLoc, ArrayRef<ParsedTemplateArgument> TemplateArgs, SmallVectorImpl<TemplateIdAnnotation *> &CleanupList) { - - TemplateIdAnnotation *TemplateId = new (std::malloc( + TemplateIdAnnotation *TemplateId = new (llvm::safe_malloc( totalSizeToAlloc<ParsedTemplateArgument>(TemplateArgs.size()))) TemplateIdAnnotation(SS, TemplateKWLoc, TemplateNameLoc, Name, OperatorKind, OpaqueTemplateName, TemplateKind, diff --git a/include/clang/Sema/Scope.h b/include/clang/Sema/Scope.h index cd58a9910f98e..a3379ff34f123 100644 --- a/include/clang/Sema/Scope.h +++ b/include/clang/Sema/Scope.h @@ -1,4 +1,4 @@ -//===--- Scope.h - Scope interface ------------------------------*- C++ -*-===// +//===- Scope.h - Scope interface --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,101 +14,102 @@ #ifndef LLVM_CLANG_SEMA_SCOPE_H #define LLVM_CLANG_SEMA_SCOPE_H -#include "clang/AST/Decl.h" #include "clang/Basic/Diagnostic.h" #include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/iterator_range.h" +#include <cassert> namespace llvm { class raw_ostream; -} +} // namespace llvm namespace clang { class Decl; +class DeclContext; class UsingDirectiveDecl; class VarDecl; /// Scope - A scope is a transient data structure that is used while parsing the /// program. It assists with resolving identifiers to the appropriate /// declaration. -/// class Scope { public: /// ScopeFlags - These are bitfields that are or'd together when creating a /// scope, which defines the sorts of things the scope contains. enum ScopeFlags { - /// \brief This indicates that the scope corresponds to a function, which + /// This indicates that the scope corresponds to a function, which /// means that labels are set here. FnScope = 0x01, - /// \brief This is a while, do, switch, for, etc that can have break + /// This is a while, do, switch, for, etc that can have break /// statements embedded into it. BreakScope = 0x02, - /// \brief This is a while, do, for, which can have continue statements + /// This is a while, do, for, which can have continue statements /// embedded into it. ContinueScope = 0x04, - /// \brief This is a scope that can contain a declaration. Some scopes + /// This is a scope that can contain a declaration. Some scopes /// just contain loop constructs but don't contain decls. DeclScope = 0x08, - /// \brief The controlling scope in a if/switch/while/for statement. + /// The controlling scope in a if/switch/while/for statement. ControlScope = 0x10, - /// \brief The scope of a struct/union/class definition. + /// The scope of a struct/union/class definition. ClassScope = 0x20, - /// \brief This is a scope that corresponds to a block/closure object. + /// This is a scope that corresponds to a block/closure object. /// Blocks serve as top-level scopes for some objects like labels, they /// also prevent things like break and continue. BlockScopes always have /// the FnScope and DeclScope flags set as well. BlockScope = 0x40, - /// \brief This is a scope that corresponds to the + /// This is a scope that corresponds to the /// template parameters of a C++ template. Template parameter /// scope starts at the 'template' keyword and ends when the /// template declaration ends. TemplateParamScope = 0x80, - /// \brief This is a scope that corresponds to the + /// This is a scope that corresponds to the /// parameters within a function prototype. FunctionPrototypeScope = 0x100, - /// \brief This is a scope that corresponds to the parameters within + /// This is a scope that corresponds to the parameters within /// a function prototype for a function declaration (as opposed to any /// other kind of function declarator). Always has FunctionPrototypeScope /// set as well. FunctionDeclarationScope = 0x200, - /// \brief This is a scope that corresponds to the Objective-C + /// This is a scope that corresponds to the Objective-C /// \@catch statement. AtCatchScope = 0x400, - /// \brief This scope corresponds to an Objective-C method body. + /// This scope corresponds to an Objective-C method body. /// It always has FnScope and DeclScope set as well. ObjCMethodScope = 0x800, - /// \brief This is a scope that corresponds to a switch statement. + /// This is a scope that corresponds to a switch statement. SwitchScope = 0x1000, - /// \brief This is the scope of a C++ try statement. + /// This is the scope of a C++ try statement. TryScope = 0x2000, - /// \brief This is the scope for a function-level C++ try or catch scope. + /// This is the scope for a function-level C++ try or catch scope. FnTryCatchScope = 0x4000, - /// \brief This is the scope of OpenMP executable directive. + /// This is the scope of OpenMP executable directive. OpenMPDirectiveScope = 0x8000, - /// \brief This is the scope of some OpenMP loop directive. + /// This is the scope of some OpenMP loop directive. OpenMPLoopDirectiveScope = 0x10000, - /// \brief This is the scope of some OpenMP simd directive. + /// This is the scope of some OpenMP simd directive. /// For example, it is used for 'omp simd', 'omp for simd'. /// This flag is propagated to children scopes. OpenMPSimdDirectiveScope = 0x20000, @@ -131,6 +132,7 @@ public: /// We are between inheritance colon and the real class/struct definition scope. ClassInheritanceScope = 0x800000, }; + private: /// The parent scope for this scope. This is null for the translation-unit /// scope. @@ -144,7 +146,7 @@ private: /// depth 0. unsigned short Depth; - /// \brief Declarations with static linkage are mangled with the number of + /// Declarations with static linkage are mangled with the number of /// scopes seen as a component. unsigned short MSLastManglingNumber; @@ -185,7 +187,7 @@ private: /// popped, these declarations are removed from the IdentifierTable's notion /// of current declaration. It is up to the current Action implementation to /// implement these semantics. - typedef llvm::SmallPtrSet<Decl *, 32> DeclSetTy; + using DeclSetTy = llvm::SmallPtrSet<Decl *, 32>; DeclSetTy DeclsInScope; /// The DeclContext with which this scope is associated. For @@ -193,10 +195,10 @@ private: /// entity of a function scope is a function, etc. DeclContext *Entity; - typedef SmallVector<UsingDirectiveDecl *, 2> UsingDirectivesTy; + using UsingDirectivesTy = SmallVector<UsingDirectiveDecl *, 2>; UsingDirectivesTy UsingDirectives; - /// \brief Used to determine if errors occurred in this scope. + /// Used to determine if errors occurred in this scope. DiagnosticErrorTrap ErrorTrap; /// A lattice consisting of undefined, a single NRVO candidate variable in @@ -207,25 +209,23 @@ private: public: Scope(Scope *Parent, unsigned ScopeFlags, DiagnosticsEngine &Diag) - : ErrorTrap(Diag) { + : ErrorTrap(Diag) { Init(Parent, ScopeFlags); } /// getFlags - Return the flags for this scope. - /// unsigned getFlags() const { return Flags; } + void setFlags(unsigned F) { setFlags(getParent(), F); } /// isBlockScope - Return true if this scope correspond to a closure. bool isBlockScope() const { return Flags & BlockScope; } /// getParent - Return the scope that this is nested in. - /// const Scope *getParent() const { return AnyParent; } Scope *getParent() { return AnyParent; } /// getFnParent - Return the closest scope that is a function body. - /// const Scope *getFnParent() const { return FnParent; } Scope *getFnParent() { return FnParent; } @@ -259,6 +259,9 @@ public: Scope *getTemplateParamParent() { return TemplateParamParent; } const Scope *getTemplateParamParent() const { return TemplateParamParent; } + /// Returns the depth of this scope. The translation-unit has scope depth 0. + unsigned getDepth() const { return Depth; } + /// Returns the number of function prototype scopes in this scope /// chain. unsigned getFunctionPrototypeDepth() const { @@ -272,10 +275,12 @@ public: return PrototypeIndex++; } - typedef llvm::iterator_range<DeclSetTy::iterator> decl_range; + using decl_range = llvm::iterator_range<DeclSetTy::iterator>; + decl_range decls() const { return decl_range(DeclsInScope.begin(), DeclsInScope.end()); } + bool decl_empty() const { return DeclsInScope.empty(); } void AddDecl(Decl *D) { @@ -365,7 +370,6 @@ public: return false; } - /// isTemplateParamScope - Return true if this scope is a C++ /// template parameter scope. bool isTemplateParamScope() const { @@ -397,12 +401,12 @@ public: return false; } - /// \brief Determines whether this scope is the OpenMP directive scope + /// Determines whether this scope is the OpenMP directive scope bool isOpenMPDirectiveScope() const { return (getFlags() & Scope::OpenMPDirectiveScope); } - /// \brief Determine whether this scope is some OpenMP loop directive scope + /// Determine whether this scope is some OpenMP loop directive scope /// (for example, 'omp for', 'omp simd'). bool isOpenMPLoopDirectiveScope() const { if (getFlags() & Scope::OpenMPLoopDirectiveScope) { @@ -413,34 +417,34 @@ public: return false; } - /// \brief Determine whether this scope is (or is nested into) some OpenMP + /// Determine whether this scope is (or is nested into) some OpenMP /// loop simd directive scope (for example, 'omp simd', 'omp for simd'). bool isOpenMPSimdDirectiveScope() const { return getFlags() & Scope::OpenMPSimdDirectiveScope; } - /// \brief Determine whether this scope is a loop having OpenMP loop + /// Determine whether this scope is a loop having OpenMP loop /// directive attached. bool isOpenMPLoopScope() const { const Scope *P = getParent(); return P && P->isOpenMPLoopDirectiveScope(); } - /// \brief Determine whether this scope is a C++ 'try' block. + /// Determine whether this scope is a C++ 'try' block. bool isTryScope() const { return getFlags() & Scope::TryScope; } - /// \brief Determine whether this scope is a SEH '__try' block. + /// Determine whether this scope is a SEH '__try' block. bool isSEHTryScope() const { return getFlags() & Scope::SEHTryScope; } - /// \brief Determine whether this scope is a SEH '__except' block. + /// Determine whether this scope is a SEH '__except' block. bool isSEHExceptScope() const { return getFlags() & Scope::SEHExceptScope; } - /// \brief Determine whether this scope is a compound statement scope. + /// Determine whether this scope is a compound statement scope. bool isCompoundStmtScope() const { return getFlags() & Scope::CompoundStmtScope; } - /// \brief Returns if rhs has a higher scope depth than this. + /// Returns if rhs has a higher scope depth than this. /// /// The caller is responsible for calling this only if one of the two scopes /// is an ancestor of the other. @@ -454,8 +458,8 @@ public: UsingDirectives.push_back(UDir); } - typedef llvm::iterator_range<UsingDirectivesTy::iterator> - using_directives_range; + using using_directives_range = + llvm::iterator_range<UsingDirectivesTy::iterator>; using_directives_range using_directives() { return using_directives_range(UsingDirectives.begin(), @@ -474,25 +478,23 @@ public: } void setNoNRVO() { - NRVO.setInt(1); + NRVO.setInt(true); NRVO.setPointer(nullptr); } void mergeNRVOIntoParent(); /// Init - This is used by the parser to implement scope caching. - /// void Init(Scope *parent, unsigned flags); - /// \brief Sets up the specified scope flags and adjusts the scope state + /// Sets up the specified scope flags and adjusts the scope state /// variables accordingly. - /// void AddFlags(unsigned Flags); void dumpImpl(raw_ostream &OS) const; void dump() const; }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_SCOPE_H diff --git a/include/clang/Sema/ScopeInfo.h b/include/clang/Sema/ScopeInfo.h index c707a3e8ef074..5eac2845fd33e 100644 --- a/include/clang/Sema/ScopeInfo.h +++ b/include/clang/Sema/ScopeInfo.h @@ -1,4 +1,4 @@ -//===--- ScopeInfo.h - Information about a semantic context -----*- C++ -*-===// +//===- ScopeInfo.h - Information about a semantic context -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,48 +18,62 @@ #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/Basic/CapturedStmt.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Sema/CleanupInfo.h" -#include "clang/Sema/Ownership.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/DenseMapInfo.h" +#include "llvm/ADT/MapVector.h" +#include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallSet.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/StringSwitch.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" #include <algorithm> +#include <cassert> +#include <utility> namespace clang { -class Decl; class BlockDecl; class CapturedDecl; class CXXMethodDecl; -class FieldDecl; -class ObjCPropertyDecl; -class IdentifierInfo; +class CXXRecordDecl; class ImplicitParamDecl; -class LabelDecl; +class NamedDecl; +class ObjCIvarRefExpr; +class ObjCMessageExpr; +class ObjCPropertyDecl; +class ObjCPropertyRefExpr; +class ParmVarDecl; +class RecordDecl; class ReturnStmt; class Scope; +class Stmt; class SwitchStmt; -class TemplateTypeParmDecl; class TemplateParameterList; +class TemplateTypeParmDecl; class VarDecl; -class ObjCIvarRefExpr; -class ObjCPropertyRefExpr; -class ObjCMessageExpr; namespace sema { -/// \brief Contains information about the compound statement currently being +/// Contains information about the compound statement currently being /// parsed. class CompoundScopeInfo { public: - CompoundScopeInfo() - : HasEmptyLoopBodies(false) { } - - /// \brief Whether this compound stamement contains `for' or `while' loops + /// Whether this compound stamement contains `for' or `while' loops /// with empty bodies. - bool HasEmptyLoopBodies; + bool HasEmptyLoopBodies = false; + + /// Whether this compound statement corresponds to a GNU statement + /// expression. + bool IsStmtExpr; + + CompoundScopeInfo(bool IsStmtExpr) : IsStmtExpr(IsStmtExpr) {} void setHasEmptyLoopBodies() { HasEmptyLoopBodies = true; @@ -74,10 +88,10 @@ public: PossiblyUnreachableDiag(const PartialDiagnostic &PD, SourceLocation Loc, const Stmt *stmt) - : PD(PD), Loc(Loc), stmt(stmt) {} + : PD(PD), Loc(Loc), stmt(stmt) {} }; -/// \brief Retains information about a function, method, or block that is +/// Retains information about a function, method, or block that is /// currently being parsed. class FunctionScopeInfo { protected: @@ -89,30 +103,29 @@ protected: }; public: - /// \brief What kind of scope we are describing. - /// + /// What kind of scope we are describing. ScopeKind Kind : 3; - /// \brief Whether this function contains a VLA, \@try, try, C++ + /// Whether this function contains a VLA, \@try, try, C++ /// initializer, or anything else that can't be jumped past. bool HasBranchProtectedScope : 1; - /// \brief Whether this function contains any switches or direct gotos. + /// Whether this function contains any switches or direct gotos. bool HasBranchIntoScope : 1; - /// \brief Whether this function contains any indirect gotos. + /// Whether this function contains any indirect gotos. bool HasIndirectGoto : 1; - /// \brief Whether a statement was dropped because it was invalid. + /// Whether a statement was dropped because it was invalid. bool HasDroppedStmt : 1; - /// \brief True if current scope is for OpenMP declare reduction combiner. + /// True if current scope is for OpenMP declare reduction combiner. bool HasOMPDeclareReductionCombiner : 1; - /// \brief Whether there is a fallthrough statement in this function. + /// Whether there is a fallthrough statement in this function. bool HasFallthroughStmt : 1; - /// \brief Whether we make reference to a declaration that could be + /// Whether we make reference to a declaration that could be /// unavailable. bool HasPotentialAvailabilityViolations : 1; @@ -123,6 +136,7 @@ public: /// True when this is a method marked as a designated initializer. bool ObjCIsDesignatedInit : 1; + /// This starts true for a method marked as designated initializer and will /// be set to false if there is an invocation to a designated initializer of /// the super class. @@ -132,15 +146,16 @@ public: /// initializer within a class that has at least one initializer marked as a /// designated initializer. bool ObjCIsSecondaryInit : 1; + /// This starts true for a secondary initializer method and will be set to /// false if there is an invocation of an initializer on 'self'. bool ObjCWarnForNoInitDelegation : 1; - /// \brief True only when this function has not already built, or attempted + /// True only when this function has not already built, or attempted /// to build, the initial and final coroutine suspend points bool NeedsCoroutineSuspends : 1; - /// \brief An enumeration represeting the kind of the first coroutine statement + /// An enumeration represeting the kind of the first coroutine statement /// in the function. One of co_return, co_await, or co_yield. unsigned char FirstCoroutineStmtKind : 2; @@ -157,36 +172,44 @@ public: /// First SEH '__try' statement in the current function. SourceLocation FirstSEHTryLoc; - /// \brief Used to determine if errors occurred in this function or block. + /// Used to determine if errors occurred in this function or block. DiagnosticErrorTrap ErrorTrap; + /// A SwitchStmt, along with a flag indicating if its list of case statements + /// is incomplete (because we dropped an invalid one while parsing). + using SwitchInfo = llvm::PointerIntPair<SwitchStmt*, 1, bool>; + /// SwitchStack - This is the current set of active switch statements in the /// block. - SmallVector<SwitchStmt*, 8> SwitchStack; + SmallVector<SwitchInfo, 8> SwitchStack; - /// \brief The list of return statements that occur within the function or + /// The list of return statements that occur within the function or /// block, if there is any chance of applying the named return value /// optimization, or if we need to infer a return type. SmallVector<ReturnStmt*, 4> Returns; - /// \brief The promise object for this coroutine, if any. + /// The promise object for this coroutine, if any. VarDecl *CoroutinePromise = nullptr; - /// \brief The initial and final coroutine suspend points. + /// A mapping between the coroutine function parameters that were moved + /// to the coroutine frame, and their move statements. + llvm::SmallMapVector<ParmVarDecl *, Stmt *, 4> CoroutineParameterMoves; + + /// The initial and final coroutine suspend points. std::pair<Stmt *, Stmt *> CoroutineSuspends; - /// \brief The stack of currently active compound stamement scopes in the + /// The stack of currently active compound stamement scopes in the /// function. SmallVector<CompoundScopeInfo, 4> CompoundScopes; - /// \brief A list of PartialDiagnostics created but delayed within the + /// A list of PartialDiagnostics created but delayed within the /// 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 + /// A list of parameters which have the nonnull attribute and are /// modified in the function. - llvm::SmallPtrSet<const ParmVarDecl*, 8> ModifiedNonNullParams; + llvm::SmallPtrSet<const ParmVarDecl *, 8> ModifiedNonNullParams; public: /// Represents a simple identification of a weak object. @@ -218,14 +241,14 @@ public: /// identify the object in memory. /// /// \sa isExactProfile() - typedef llvm::PointerIntPair<const NamedDecl *, 1, bool> BaseInfoTy; + using BaseInfoTy = llvm::PointerIntPair<const NamedDecl *, 1, bool>; BaseInfoTy Base; /// The "property" decl, as described in the class documentation. /// /// Note that this may not actually be an ObjCPropertyDecl, e.g. in the /// case of "implicit" properties (regular methods accessed via dot syntax). - const NamedDecl *Property; + const NamedDecl *Property = nullptr; /// Used to find the proper base profile for a given base expression. static BaseInfoTy getBaseInfo(const Expr *BaseE); @@ -270,12 +293,14 @@ public: static inline WeakObjectProfileTy getEmptyKey() { return WeakObjectProfileTy(); } + static inline WeakObjectProfileTy getTombstoneKey() { return WeakObjectProfileTy::getSentinel(); } static unsigned getHashValue(const WeakObjectProfileTy &Val) { - typedef std::pair<BaseInfoTy, const NamedDecl *> Pair; + using Pair = std::pair<BaseInfoTy, const NamedDecl *>; + return llvm::DenseMapInfo<Pair>::getHashValue(Pair(Val.Base, Val.Property)); } @@ -295,6 +320,7 @@ public: /// Part of the implementation of -Wrepeated-use-of-weak. class WeakUseTy { llvm::PointerIntPair<const Expr *, 1, bool> Rep; + public: WeakUseTy(const Expr *Use, bool IsRead) : Rep(Use, IsRead) {} @@ -310,14 +336,14 @@ public: /// Used to collect uses of a particular weak object in a function body. /// /// Part of the implementation of -Wrepeated-use-of-weak. - typedef SmallVector<WeakUseTy, 4> WeakUseVector; + using WeakUseVector = SmallVector<WeakUseTy, 4>; /// Used to collect all uses of weak objects in a function body. /// /// Part of the implementation of -Wrepeated-use-of-weak. - typedef llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8, - WeakObjectProfileTy::DenseMapInfo> - WeakObjectUseMap; + using WeakObjectUseMap = + llvm::SmallDenseMap<WeakObjectProfileTy, WeakUseVector, 8, + WeakObjectProfileTy::DenseMapInfo>; private: /// Used to collect all uses of weak objects in this function body. @@ -329,6 +355,18 @@ protected: FunctionScopeInfo(const FunctionScopeInfo&) = default; public: + FunctionScopeInfo(DiagnosticsEngine &Diag) + : Kind(SK_Function), HasBranchProtectedScope(false), + HasBranchIntoScope(false), HasIndirectGoto(false), + HasDroppedStmt(false), HasOMPDeclareReductionCombiner(false), + HasFallthroughStmt(false), HasPotentialAvailabilityViolations(false), + ObjCShouldCallSuper(false), ObjCIsDesignatedInit(false), + ObjCWarnForNoDesignatedInitChain(false), ObjCIsSecondaryInit(false), + ObjCWarnForNoInitDelegation(false), NeedsCoroutineSuspends(true), + ErrorTrap(Diag) {} + + virtual ~FunctionScopeInfo(); + /// Record that a weak object was accessed. /// /// Part of the implementation of -Wrepeated-use-of-weak. @@ -430,179 +468,165 @@ public: CoroutineSuspends.second = Final; } - FunctionScopeInfo(DiagnosticsEngine &Diag) - : Kind(SK_Function), - HasBranchProtectedScope(false), - HasBranchIntoScope(false), - HasIndirectGoto(false), - HasDroppedStmt(false), - HasOMPDeclareReductionCombiner(false), - HasFallthroughStmt(false), - HasPotentialAvailabilityViolations(false), - ObjCShouldCallSuper(false), - ObjCIsDesignatedInit(false), - ObjCWarnForNoDesignatedInitChain(false), - ObjCIsSecondaryInit(false), - ObjCWarnForNoInitDelegation(false), - NeedsCoroutineSuspends(true), - ErrorTrap(Diag) { } - - virtual ~FunctionScopeInfo(); - - /// \brief Clear out the information in this function scope, making it + /// Clear out the information in this function scope, making it /// suitable for reuse. void Clear(); }; -class CapturingScopeInfo : public FunctionScopeInfo { -protected: - CapturingScopeInfo(const CapturingScopeInfo&) = default; +class Capture { + // There are three categories of capture: capturing 'this', capturing + // local variables, and C++1y initialized captures (which can have an + // arbitrary initializer, and don't really capture in the traditional + // sense at all). + // + // There are three ways to capture a local variable: + // - capture by copy in the C++11 sense, + // - capture by reference in the C++11 sense, and + // - __block capture. + // Lambdas explicitly specify capture by copy or capture by reference. + // For blocks, __block capture applies to variables with that annotation, + // variables of reference type are captured by reference, and other + // variables are captured by copy. + enum CaptureKind { + Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA + }; + enum { + IsNestedCapture = 0x1, + IsThisCaptured = 0x2 + }; + + /// The variable being captured (if we are not capturing 'this') and whether + /// this is a nested capture, and whether we are capturing 'this' + llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis; + + /// Expression to initialize a field of the given type, and the kind of + /// 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<void *, 2, CaptureKind> InitExprAndCaptureKind; + + /// The source location at which the first capture occurred. + SourceLocation Loc; + + /// The location of the ellipsis that expands a parameter pack. + SourceLocation EllipsisLoc; + + /// The type as it was captured, which is in effect the type of the + /// non-static data member that would hold the capture. + QualType CaptureType; + + /// Whether an explicit capture has been odr-used in the body of the + /// lambda. + bool ODRUsed = false; + + /// Whether an explicit capture has been non-odr-used in the body of + /// the lambda. + bool NonODRUsed = false; public: - enum ImplicitCaptureStyle { - ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, - ImpCap_CapturedRegion - }; + Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, + SourceLocation Loc, SourceLocation EllipsisLoc, + QualType CaptureType, Expr *Cpy) + : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0), + InitExprAndCaptureKind( + Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef + : Cap_ByCopy), + Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType) {} - ImplicitCaptureStyle ImpCaptureStyle; + enum IsThisCapture { ThisCapture }; + Capture(IsThisCapture, bool IsNested, SourceLocation Loc, + QualType CaptureType, Expr *Cpy, const bool ByCopy) + : VarAndNestedAndThis( + nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), + InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), + Loc(Loc), CaptureType(CaptureType) {} - class Capture { - // There are three categories of capture: capturing 'this', capturing - // local variables, and C++1y initialized captures (which can have an - // arbitrary initializer, and don't really capture in the traditional - // sense at all). - // - // There are three ways to capture a local variable: - // - capture by copy in the C++11 sense, - // - capture by reference in the C++11 sense, and - // - __block capture. - // Lambdas explicitly specify capture by copy or capture by reference. - // For blocks, __block capture applies to variables with that annotation, - // variables of reference type are captured by reference, and other - // variables are captured by copy. - enum CaptureKind { - Cap_ByCopy, Cap_ByRef, Cap_Block, Cap_VLA - }; - enum { - IsNestedCapture = 0x1, - IsThisCaptured = 0x2 - }; - /// The variable being captured (if we are not capturing 'this') and whether - /// this is a nested capture, and whether we are capturing 'this' - llvm::PointerIntPair<VarDecl*, 2> VarAndNestedAndThis; - /// Expression to initialize a field of the given type, and the kind of - /// 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<void *, 2, CaptureKind> InitExprAndCaptureKind; - - /// \brief The source location at which the first capture occurred. - SourceLocation Loc; + bool isThisCapture() const { + return VarAndNestedAndThis.getInt() & IsThisCaptured; + } - /// \brief The location of the ellipsis that expands a parameter pack. - SourceLocation EllipsisLoc; + bool isVariableCapture() const { + return !isThisCapture() && !isVLATypeCapture(); + } - /// \brief The type as it was captured, which is in effect the type of the - /// non-static data member that would hold the capture. - QualType CaptureType; + bool isCopyCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_ByCopy; + } - /// \brief Whether an explicit capture has been odr-used in the body of the - /// lambda. - bool ODRUsed; + bool isReferenceCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_ByRef; + } - /// \brief Whether an explicit capture has been non-odr-used in the body of - /// the lambda. - bool NonODRUsed; + bool isBlockCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_Block; + } - public: - Capture(VarDecl *Var, bool Block, bool ByRef, bool IsNested, - SourceLocation Loc, SourceLocation EllipsisLoc, - QualType CaptureType, Expr *Cpy) - : VarAndNestedAndThis(Var, IsNested ? IsNestedCapture : 0), - InitExprAndCaptureKind( - Cpy, !Var ? Cap_VLA : Block ? Cap_Block : ByRef ? Cap_ByRef - : Cap_ByCopy), - Loc(Loc), EllipsisLoc(EllipsisLoc), CaptureType(CaptureType), - ODRUsed(false), NonODRUsed(false) {} - - enum IsThisCapture { ThisCapture }; - Capture(IsThisCapture, bool IsNested, SourceLocation Loc, - QualType CaptureType, Expr *Cpy, const bool ByCopy) - : VarAndNestedAndThis( - nullptr, (IsThisCaptured | (IsNested ? IsNestedCapture : 0))), - InitExprAndCaptureKind(Cpy, ByCopy ? Cap_ByCopy : Cap_ByRef), - Loc(Loc), EllipsisLoc(), CaptureType(CaptureType), ODRUsed(false), - NonODRUsed(false) {} - - bool isThisCapture() const { - return VarAndNestedAndThis.getInt() & IsThisCaptured; - } - bool isVariableCapture() const { - return !isThisCapture() && !isVLATypeCapture(); - } - bool isCopyCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_ByCopy; - } - bool isReferenceCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_ByRef; - } - bool isBlockCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_Block; - } - bool isVLATypeCapture() const { - return InitExprAndCaptureKind.getInt() == Cap_VLA; - } - bool isNested() const { - return VarAndNestedAndThis.getInt() & IsNestedCapture; - } - bool isODRUsed() const { return ODRUsed; } - bool isNonODRUsed() const { return NonODRUsed; } - void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } + bool isVLATypeCapture() const { + return InitExprAndCaptureKind.getInt() == Cap_VLA; + } - VarDecl *getVariable() const { - assert(isVariableCapture()); - return VarAndNestedAndThis.getPointer(); - } - - /// \brief Retrieve the location at which this variable was captured. - SourceLocation getLocation() const { return Loc; } - - /// \brief Retrieve the source location of the ellipsis, whose presence - /// indicates that the capture is a pack expansion. - SourceLocation getEllipsisLoc() const { return EllipsisLoc; } - - /// \brief Retrieve the capture type for this capture, which is effectively - /// the type of the non-static data member in the lambda/block structure - /// that would store this capture. - QualType getCaptureType() const { - assert(!isThisCapture()); - return CaptureType; - } + bool isNested() const { + return VarAndNestedAndThis.getInt() & IsNestedCapture; + } - Expr *getInitExpr() const { - assert(!isVLATypeCapture() && "no init expression for type capture"); - return static_cast<Expr *>(InitExprAndCaptureKind.getPointer()); - } + bool isODRUsed() const { return ODRUsed; } + bool isNonODRUsed() const { return NonODRUsed; } + void markUsed(bool IsODRUse) { (IsODRUse ? ODRUsed : NonODRUsed) = true; } + + VarDecl *getVariable() const { + assert(isVariableCapture()); + return VarAndNestedAndThis.getPointer(); + } + + /// Retrieve the location at which this variable was captured. + SourceLocation getLocation() const { return Loc; } + + /// Retrieve the source location of the ellipsis, whose presence + /// indicates that the capture is a pack expansion. + SourceLocation getEllipsisLoc() const { return EllipsisLoc; } + + /// Retrieve the capture type for this capture, which is effectively + /// the type of the non-static data member in the lambda/block structure + /// that would store this capture. + QualType getCaptureType() const { + assert(!isThisCapture()); + return CaptureType; + } + + Expr *getInitExpr() const { + assert(!isVLATypeCapture() && "no init expression for type capture"); + return static_cast<Expr *>(InitExprAndCaptureKind.getPointer()); + } +}; + +class CapturingScopeInfo : public FunctionScopeInfo { +protected: + CapturingScopeInfo(const CapturingScopeInfo&) = default; + +public: + enum ImplicitCaptureStyle { + ImpCap_None, ImpCap_LambdaByval, ImpCap_LambdaByref, ImpCap_Block, + ImpCap_CapturedRegion }; + ImplicitCaptureStyle ImpCaptureStyle; + CapturingScopeInfo(DiagnosticsEngine &Diag, ImplicitCaptureStyle Style) - : FunctionScopeInfo(Diag), ImpCaptureStyle(Style), CXXThisCaptureIndex(0), - HasImplicitReturnType(false) - {} + : FunctionScopeInfo(Diag), ImpCaptureStyle(Style) {} /// CaptureMap - A map of captured variables to (index+1) into Captures. llvm::DenseMap<VarDecl*, unsigned> CaptureMap; /// CXXThisCaptureIndex - The (index+1) of the capture of 'this'; /// zero if 'this' is not captured. - unsigned CXXThisCaptureIndex; + unsigned CXXThisCaptureIndex = 0; /// Captures - The captures. SmallVector<Capture, 4> Captures; - /// \brief - Whether the target type of return statements in this context + /// - Whether the target type of return statements in this context /// is deduced (e.g. a lambda or block with omitted return type). - bool HasImplicitReturnType; + bool HasImplicitReturnType = false; /// ReturnType - The target type of return statements in this context, /// or null if unknown. @@ -629,24 +653,24 @@ public: void addThisCapture(bool isNested, SourceLocation Loc, Expr *Cpy, bool ByCopy); - /// \brief Determine whether the C++ 'this' is captured. + /// Determine whether the C++ 'this' is captured. bool isCXXThisCaptured() const { return CXXThisCaptureIndex != 0; } - /// \brief Retrieve the capture of C++ 'this', if it has been captured. + /// Retrieve the capture of C++ 'this', if it has been captured. Capture &getCXXThisCapture() { assert(isCXXThisCaptured() && "this has not been captured"); return Captures[CXXThisCaptureIndex - 1]; } - /// \brief Determine whether the given variable has been captured. + /// Determine whether the given variable has been captured. bool isCaptured(VarDecl *Var) const { return CaptureMap.count(Var); } - /// \brief Determine whether the given variable-array type has been captured. + /// 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 + /// Retrieve the capture of the given variable, if it has been /// captured already. Capture &getCapture(VarDecl *Var) { assert(isCaptured(Var) && "Variable has not been captured"); @@ -666,7 +690,7 @@ public: } }; -/// \brief Retains information about a block that is currently being parsed. +/// Retains information about a block that is currently being parsed. class BlockScopeInfo final : public CapturingScopeInfo { public: BlockDecl *TheDecl; @@ -680,9 +704,8 @@ public: QualType FunctionType; BlockScopeInfo(DiagnosticsEngine &Diag, Scope *BlockScope, BlockDecl *Block) - : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), - TheScope(BlockScope) - { + : CapturingScopeInfo(Diag, ImpCap_Block), TheDecl(Block), + TheScope(BlockScope) { Kind = SK_Block; } @@ -693,38 +716,44 @@ public: } }; -/// \brief Retains information about a captured region. +/// Retains information about a captured region. class CapturedRegionScopeInfo final : public CapturingScopeInfo { public: - /// \brief The CapturedDecl for this statement. + /// The CapturedDecl for this statement. CapturedDecl *TheCapturedDecl; - /// \brief The captured record type. + + /// The captured record type. RecordDecl *TheRecordDecl; - /// \brief This is the enclosing scope of the captured region. + + /// This is the enclosing scope of the captured region. Scope *TheScope; - /// \brief The implicit parameter for the captured variables. + + /// The implicit parameter for the captured variables. ImplicitParamDecl *ContextParam; - /// \brief The kind of captured region. + + /// The kind of captured region. unsigned short CapRegionKind; + unsigned short OpenMPLevel; CapturedRegionScopeInfo(DiagnosticsEngine &Diag, Scope *S, CapturedDecl *CD, RecordDecl *RD, ImplicitParamDecl *Context, CapturedRegionKind K, unsigned OpenMPLevel) - : CapturingScopeInfo(Diag, ImpCap_CapturedRegion), - TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), - ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) - { + : CapturingScopeInfo(Diag, ImpCap_CapturedRegion), + TheCapturedDecl(CD), TheRecordDecl(RD), TheScope(S), + ContextParam(Context), CapRegionKind(K), OpenMPLevel(OpenMPLevel) { Kind = SK_CapturedRegion; } ~CapturedRegionScopeInfo() override; - /// \brief A descriptive name for the kind of captured region this is. + /// A descriptive name for the kind of captured region this is. StringRef getRegionName() const { switch (CapRegionKind) { case CR_Default: return "default captured statement"; + case CR_ObjCAtFinally: + return "Objective-C @finally statement"; case CR_OpenMP: return "OpenMP region"; } @@ -738,40 +767,40 @@ public: class LambdaScopeInfo final : public CapturingScopeInfo { public: - /// \brief The class that describes the lambda. - CXXRecordDecl *Lambda; + /// The class that describes the lambda. + CXXRecordDecl *Lambda = nullptr; - /// \brief The lambda's compiler-generated \c operator(). - CXXMethodDecl *CallOperator; + /// The lambda's compiler-generated \c operator(). + CXXMethodDecl *CallOperator = nullptr; - /// \brief Source range covering the lambda introducer [...]. + /// Source range covering the lambda introducer [...]. SourceRange IntroducerRange; - /// \brief Source location of the '&' or '=' specifying the default capture + /// Source location of the '&' or '=' specifying the default capture /// type, if any. SourceLocation CaptureDefaultLoc; - /// \brief The number of captures in the \c Captures list that are + /// The number of captures in the \c Captures list that are /// explicit captures. - unsigned NumExplicitCaptures; + unsigned NumExplicitCaptures = 0; - /// \brief Whether this is a mutable lambda. - bool Mutable; + /// Whether this is a mutable lambda. + bool Mutable = false; - /// \brief Whether the (empty) parameter list is explicit. - bool ExplicitParams; + /// Whether the (empty) parameter list is explicit. + bool ExplicitParams = false; - /// \brief Whether any of the capture expressions requires cleanups. + /// Whether any of the capture expressions requires cleanups. CleanupInfo Cleanup; - /// \brief Whether the lambda contains an unexpanded parameter pack. - bool ContainsUnexpandedParameterPack; + /// Whether the lambda contains an unexpanded parameter pack. + bool ContainsUnexpandedParameterPack = false; - /// \brief If this is a generic lambda, use this as the depth of + /// If this is a generic lambda, use this as the depth of /// each 'auto' parameter, during initial AST construction. - unsigned AutoTemplateParameterDepth; + unsigned AutoTemplateParameterDepth = 0; - /// \brief Store the list of the auto parameters for a generic lambda. + /// Store the list of the auto parameters for a generic lambda. /// If this is a generic lambda, store the list of the auto /// parameters converted into TemplateTypeParmDecls into a vector /// that can be used to construct the generic lambda's template @@ -781,30 +810,32 @@ public: /// If this is a generic lambda, and the template parameter /// list has been created (from the AutoTemplateParams) then /// store a reference to it (cache it to avoid reconstructing it). - TemplateParameterList *GLTemplateParameterList; + TemplateParameterList *GLTemplateParameterList = nullptr; - /// \brief Contains all variable-referring-expressions (i.e. DeclRefExprs + /// Contains all variable-referring-expressions (i.e. DeclRefExprs /// or MemberExprs) that refer to local variables in a generic lambda /// or a lambda in a potentially-evaluated-if-used context. /// /// Potentially capturable variables of a nested lambda that might need /// to be captured by the lambda are housed here. /// This is specifically useful for generic lambdas or - /// lambdas within a a potentially evaluated-if-used context. + /// lambdas within a potentially evaluated-if-used context. /// If an enclosing variable is named in an expression of a lambda nested /// within a generic lambda, we don't always know know whether the variable /// will truly be odr-used (i.e. need to be captured) by that nested lambda, /// until its instantiation. But we still need to capture it in the /// enclosing lambda if all intervening lambdas can capture the variable. - llvm::SmallVector<Expr*, 4> PotentiallyCapturingExprs; - /// \brief Contains all variable-referring-expressions that refer + /// Contains all variable-referring-expressions that refer /// to local variables that are usable as constant expressions and /// do not involve an odr-use (they may still need to be captured /// if the enclosing full-expression is instantiation dependent). llvm::SmallSet<Expr *, 8> NonODRUsedCapturingExprs; + /// A map of explicit capture indices to their introducer source ranges. + llvm::DenseMap<unsigned, SourceRange> ExplicitCaptureRanges; + /// Contains all of the variables defined in this lambda that shadow variables /// that were defined in parent contexts. Used to avoid warnings when the /// shadowed variables are uncaptured by this lambda. @@ -817,15 +848,11 @@ public: SourceLocation PotentialThisCaptureLocation; LambdaScopeInfo(DiagnosticsEngine &Diag) - : CapturingScopeInfo(Diag, ImpCap_None), Lambda(nullptr), - CallOperator(nullptr), NumExplicitCaptures(0), Mutable(false), - ExplicitParams(false), Cleanup{}, - ContainsUnexpandedParameterPack(false), AutoTemplateParameterDepth(0), - GLTemplateParameterList(nullptr) { + : CapturingScopeInfo(Diag, ImpCap_None) { Kind = SK_Lambda; } - /// \brief Note when all explicit captures have been added. + /// Note when all explicit captures have been added. void finishedExplicitCaptures() { NumExplicitCaptures = Captures.size(); } @@ -840,8 +867,7 @@ public: return !AutoTemplateParams.empty() || GLTemplateParameterList; } - /// - /// \brief Add a variable that might potentially be captured by the + /// Add a variable that might potentially be captured by the /// lambda and therefore the enclosing lambdas. /// /// This is also used by enclosing lambda's to speculatively capture @@ -866,11 +892,12 @@ public: void addPotentialThisCapture(SourceLocation Loc) { PotentialThisCaptureLocation = Loc; } + bool hasPotentialThisCapture() const { return PotentialThisCaptureLocation.isValid(); } - /// \brief Mark a variable's reference in a lambda as non-odr using. + /// Mark a variable's reference in a lambda as non-odr using. /// /// For generic lambdas, if a variable is named in a potentially evaluated /// expression, where the enclosing full expression is dependent then we @@ -909,7 +936,6 @@ public: /// seemingly harmless change elsewhere in Sema could cause us to start or stop /// building such a node. So we need a rule that anyone can implement and get /// exactly the same result". - /// void markVariableExprAsNonODRUsed(Expr *CapturingVarExpr) { assert(isa<DeclRefExpr>(CapturingVarExpr) || isa<MemberExpr>(CapturingVarExpr)); @@ -945,7 +971,7 @@ public: }; FunctionScopeInfo::WeakObjectProfileTy::WeakObjectProfileTy() - : Base(nullptr, false), Property(nullptr) {} + : Base(nullptr, false) {} FunctionScopeInfo::WeakObjectProfileTy FunctionScopeInfo::WeakObjectProfileTy::getSentinel() { @@ -970,7 +996,8 @@ CapturingScopeInfo::addThisCapture(bool isNested, SourceLocation Loc, CXXThisCaptureIndex = Captures.size(); } -} // end namespace sema -} // end namespace clang +} // namespace sema + +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_SCOPEINFO_H diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 9cbe8e5cd63ef..b1077c620f8aa 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -17,9 +17,11 @@ #include "clang/AST/Attr.h" #include "clang/AST/Availability.h" -#include "clang/AST/DeclarationName.h" +#include "clang/AST/ComparisonCategories.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" +#include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" #include "clang/AST/ExternalASTSource.h" #include "clang/AST/LocInfoType.h" @@ -30,7 +32,6 @@ #include "clang/AST/TypeLoc.h" #include "clang/AST/TypeOrdering.h" #include "clang/Basic/ExpressionTraits.h" -#include "clang/Basic/LangOptions.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenMPKinds.h" #include "clang/Basic/PragmaKinds.h" @@ -45,12 +46,12 @@ #include "clang/Sema/ObjCMethodList.h" #include "clang/Sema/Ownership.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/ScopeInfo.h" #include "clang/Sema/TypoCorrection.h" #include "clang/Sema/Weak.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallBitVector.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/TinyPtrVector.h" @@ -75,7 +76,7 @@ namespace clang { class ASTReader; class ASTWriter; class ArrayType; - class AttributeList; + class ParsedAttr; class BindingDecl; class BlockDecl; class CapturedDecl; @@ -172,6 +173,7 @@ namespace clang { class TemplateArgumentList; class TemplateArgumentLoc; class TemplateDecl; + class TemplateInstantiationCallback; class TemplateParameterList; class TemplatePartialOrderingContext; class TemplateTemplateParmDecl; @@ -200,6 +202,7 @@ namespace clang { namespace sema { class AccessedEntity; class BlockScopeInfo; + class Capture; class CapturedRegionScopeInfo; class CapturingScopeInfo; class CompoundScopeInfo; @@ -275,10 +278,10 @@ class Sema { Sema(const Sema &) = delete; void operator=(const Sema &) = delete; - ///\brief Source of additional semantic information. + ///Source of additional semantic information. ExternalSemaSource *ExternalSource; - ///\brief Whether Sema has generated a multiplexer and has to delete it. + ///Whether Sema has generated a multiplexer and has to delete it. bool isMultiplexExternalSource; static bool mightHaveNonExternalLinkage(const DeclaratorDecl *FD); @@ -318,16 +321,16 @@ public: DiagnosticsEngine &Diags; SourceManager &SourceMgr; - /// \brief Flag indicating whether or not to collect detailed statistics. + /// Flag indicating whether or not to collect detailed statistics. bool CollectStats; - /// \brief Code-completion consumer. + /// Code-completion consumer. CodeCompleteConsumer *CodeCompleter; /// CurContext - This is the current declaration context of parsing. DeclContext *CurContext; - /// \brief Generally null except when we temporarily switch decl contexts, + /// Generally null except when we temporarily switch decl contexts, /// like in \see ActOnObjCTemporaryExitContainerContext. DeclContext *OriginalLexicalContext; @@ -337,17 +340,17 @@ public: bool MSStructPragmaOn; // True when \#pragma ms_struct on - /// \brief Controls member pointer representation format under the MS ABI. + /// Controls member pointer representation format under the MS ABI. LangOptions::PragmaMSPointersToMembersKind MSPointerToMemberRepresentationMethod; /// Stack of active SEH __finally scopes. Can be empty. SmallVector<Scope*, 2> CurrentSEHFinally; - /// \brief Source location for newly created implicit MSInheritanceAttrs + /// Source location for newly created implicit MSInheritanceAttrs SourceLocation ImplicitMSInheritanceAttrLoc; - /// \brief pragma clang section kind + /// pragma clang section kind enum PragmaClangSectionKind { PCSK_Invalid = 0, PCSK_BSS = 1, @@ -438,7 +441,7 @@ public: // FIXME: We should serialize / deserialize these if they occur in a PCH (but // we shouldn't do so if they're in a module). - /// \brief Whether to insert vtordisps prior to virtual bases in the Microsoft + /// Whether to insert vtordisps prior to virtual bases in the Microsoft /// C++ ABI. Possible values are 0, 1, and 2, which mean: /// /// 0: Suppress all vtordisps @@ -487,26 +490,26 @@ public: /// VisContext - Manages the stack for \#pragma GCC visibility. void *VisContext; // Really a "PragmaVisStack*" - /// \brief This represents the stack of attributes that were pushed by + /// This represents the stack of attributes that were pushed by /// \#pragma clang attribute. struct PragmaAttributeEntry { SourceLocation Loc; - AttributeList *Attribute; + ParsedAttr *Attribute; SmallVector<attr::SubjectMatchRule, 4> MatchRules; bool IsUsed; }; SmallVector<PragmaAttributeEntry, 2> PragmaAttributeStack; - /// \brief The declaration that is currently receiving an attribute from the + /// The declaration that is currently receiving an attribute from the /// #pragma attribute stack. const Decl *PragmaAttributeCurrentTargetDecl; - /// \brief This represents the last location of a "#pragma clang optimize off" + /// This represents the last location of a "#pragma clang optimize off" /// directive if such a directive has not been closed by an "on" yet. If /// optimizations are currently "on", this is set to an invalid location. SourceLocation OptimizeOffPragmaLocation; - /// \brief Flag indicating if Sema is building a recovery call expression. + /// Flag indicating if Sema is building a recovery call expression. /// /// This flag is used to avoid building recovery call expressions /// if Sema is already doing so, which would cause infinite recursions. @@ -520,7 +523,7 @@ public: /// element type here is ExprWithCleanups::Object. SmallVector<BlockDecl*, 8> ExprCleanupObjects; - /// \brief Store a list of either DeclRefExprs or MemberExprs + /// Store a list of either DeclRefExprs or MemberExprs /// that contain a reference to a variable (constant) that may or may not /// be odr-used in this Expr, and we won't know until all lvalue-to-rvalue /// and discarded value conversions have been applied to all subexpressions @@ -528,12 +531,10 @@ public: /// full expression. llvm::SmallPtrSet<Expr*, 2> MaybeODRUseExprs; - /// \brief Stack containing information about each of the nested + std::unique_ptr<sema::FunctionScopeInfo> PreallocatedFunctionScope; + + /// Stack containing information about each of the nested /// function, block, and method scopes that are currently active. - /// - /// This array is never empty. Clients should ignore the first - /// element, which is used to cache a single FunctionScopeInfo - /// that's used to parse every top-level function. SmallVector<sema::FunctionScopeInfo *, 4> FunctionScopes; typedef LazyVector<TypedefNameDecl *, ExternalSemaSource, @@ -548,16 +549,16 @@ public: /// FieldCollector - Collects CXXFieldDecls during parsing of C++ classes. std::unique_ptr<CXXFieldCollector> FieldCollector; - typedef llvm::SmallSetVector<const NamedDecl*, 16> NamedDeclSetType; + typedef llvm::SmallSetVector<NamedDecl *, 16> NamedDeclSetType; - /// \brief Set containing all declared private fields that are not used. + /// Set containing all declared private fields that are not used. NamedDeclSetType UnusedPrivateFields; - /// \brief Set containing all typedefs that are likely unused. + /// Set containing all typedefs that are likely unused. llvm::SmallSetVector<const TypedefNameDecl *, 4> UnusedLocalTypedefNameCandidates; - /// \brief Delete-expressions to be analyzed at the end of translation unit + /// Delete-expressions to be analyzed at the end of translation unit /// /// This list contains class members, and locations of delete-expressions /// that could not be proven as to whether they mismatch with new-expression @@ -577,21 +578,21 @@ public: /// we are currently parsing the initializer. llvm::SmallPtrSet<const Decl*, 4> ParsingInitForAutoVars; - /// \brief Look for a locally scoped extern "C" declaration by the given name. + /// Look for a locally scoped extern "C" declaration by the given name. NamedDecl *findLocallyScopedExternCDecl(DeclarationName Name); typedef LazyVector<VarDecl *, ExternalSemaSource, &ExternalSemaSource::ReadTentativeDefinitions, 2, 2> TentativeDefinitionsType; - /// \brief All the tentative definitions encountered in the TU. + /// All the tentative definitions encountered in the TU. TentativeDefinitionsType TentativeDefinitions; typedef LazyVector<const DeclaratorDecl *, ExternalSemaSource, &ExternalSemaSource::ReadUnusedFileScopedDecls, 2, 2> UnusedFileScopedDeclsType; - /// \brief The set of file scoped decls seen so far that have not been used + /// The set of file scoped decls seen so far that have not been used /// and must warn if not used. Only contains the first declaration. UnusedFileScopedDeclsType UnusedFileScopedDecls; @@ -599,17 +600,17 @@ public: &ExternalSemaSource::ReadDelegatingConstructors, 2, 2> DelegatingCtorDeclsType; - /// \brief All the delegating constructors seen so far in the file, used for + /// All the delegating constructors seen so far in the file, used for /// cycle detection at the end of the TU. DelegatingCtorDeclsType DelegatingCtorDecls; - /// \brief All the overriding functions seen during a class definition + /// 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 + /// All the members seen during a class definition which were both /// explicitly defaulted and had explicitly-specified exception /// specifications, along with the function type containing their /// user-specified exception specification. Those exception specifications @@ -624,7 +625,7 @@ public: LateParsedTemplateMapT; LateParsedTemplateMapT LateParsedTemplateMap; - /// \brief Callback to the parser to parse templated functions when needed. + /// Callback to the parser to parse templated functions when needed. typedef void LateTemplateParserCB(void *P, LateParsedTemplate &LPT); typedef void LateTemplateParserCleanupCB(void *P); LateTemplateParserCB *LateTemplateParser; @@ -651,7 +652,7 @@ public: /// A class which encapsulates the logic for delaying diagnostics /// during parsing and other processing. class DelayedDiagnostics { - /// \brief The current pool of diagnostics into which delayed + /// The current pool of diagnostics into which delayed /// diagnostics should go. sema::DelayedDiagnosticPool *CurPool; @@ -734,7 +735,7 @@ public: } }; - /// \brief RAII object to handle the state changes required to synthesize + /// RAII object to handle the state changes required to synthesize /// a function body. class SynthesizedFunctionScope { Sema &S; @@ -787,7 +788,7 @@ public: llvm::DenseMap<IdentifierInfo*,AsmLabelAttr*> ExtnameUndeclaredIdentifiers; - /// \brief Load weak undeclared identifiers from the external source. + /// Load weak undeclared identifiers from the external source. void LoadExternalWeakUndeclaredIdentifiers(); /// WeakTopLevelDecl - Translation-unit scoped declarations generated by @@ -804,77 +805,81 @@ public: /// For example, user-defined classes, built-in "id" type, etc. Scope *TUScope; - /// \brief The C++ "std" namespace, where the standard library resides. + /// The C++ "std" namespace, where the standard library resides. LazyDeclPtr StdNamespace; - /// \brief The C++ "std::bad_alloc" class, which is defined by the C++ + /// The C++ "std::bad_alloc" class, which is defined by the C++ /// standard library. LazyDeclPtr StdBadAlloc; - /// \brief The C++ "std::align_val_t" enum class, which is defined by the C++ + /// The C++ "std::align_val_t" enum class, which is defined by the C++ /// standard library. LazyDeclPtr StdAlignValT; - /// \brief The C++ "std::experimental" namespace, where the experimental parts + /// The C++ "std::experimental" namespace, where the experimental parts /// of the standard library resides. NamespaceDecl *StdExperimentalNamespaceCache; - /// \brief The C++ "std::initializer_list" template, which is defined in + /// The C++ "std::initializer_list" template, which is defined in /// \<initializer_list>. ClassTemplateDecl *StdInitializerList; - /// \brief The C++ "type_info" declaration, which is defined in \<typeinfo>. + /// The C++ "std::coroutine_traits" template, which is defined in + /// \<coroutine_traits> + ClassTemplateDecl *StdCoroutineTraitsCache; + + /// The C++ "type_info" declaration, which is defined in \<typeinfo>. RecordDecl *CXXTypeInfoDecl; - /// \brief The MSVC "_GUID" struct, which is defined in MSVC header files. + /// The MSVC "_GUID" struct, which is defined in MSVC header files. RecordDecl *MSVCGuidDecl; - /// \brief Caches identifiers/selectors for NSFoundation APIs. + /// Caches identifiers/selectors for NSFoundation APIs. std::unique_ptr<NSAPI> NSAPIObj; - /// \brief The declaration of the Objective-C NSNumber class. + /// The declaration of the Objective-C NSNumber class. ObjCInterfaceDecl *NSNumberDecl; - /// \brief The declaration of the Objective-C NSValue class. + /// The declaration of the Objective-C NSValue class. ObjCInterfaceDecl *NSValueDecl; - /// \brief Pointer to NSNumber type (NSNumber *). + /// Pointer to NSNumber type (NSNumber *). QualType NSNumberPointer; - /// \brief Pointer to NSValue type (NSValue *). + /// Pointer to NSValue type (NSValue *). QualType NSValuePointer; - /// \brief The Objective-C NSNumber methods used to create NSNumber literals. + /// The Objective-C NSNumber methods used to create NSNumber literals. ObjCMethodDecl *NSNumberLiteralMethods[NSAPI::NumNSNumberLiteralMethods]; - /// \brief The declaration of the Objective-C NSString class. + /// The declaration of the Objective-C NSString class. ObjCInterfaceDecl *NSStringDecl; - /// \brief Pointer to NSString type (NSString *). + /// Pointer to NSString type (NSString *). QualType NSStringPointer; - /// \brief The declaration of the stringWithUTF8String: method. + /// The declaration of the stringWithUTF8String: method. ObjCMethodDecl *StringWithUTF8StringMethod; - /// \brief The declaration of the valueWithBytes:objCType: method. + /// The declaration of the valueWithBytes:objCType: method. ObjCMethodDecl *ValueWithBytesObjCTypeMethod; - /// \brief The declaration of the Objective-C NSArray class. + /// The declaration of the Objective-C NSArray class. ObjCInterfaceDecl *NSArrayDecl; - /// \brief The declaration of the arrayWithObjects:count: method. + /// The declaration of the arrayWithObjects:count: method. ObjCMethodDecl *ArrayWithObjectsMethod; - /// \brief The declaration of the Objective-C NSDictionary class. + /// The declaration of the Objective-C NSDictionary class. ObjCInterfaceDecl *NSDictionaryDecl; - /// \brief The declaration of the dictionaryWithObjects:forKeys:count: method. + /// The declaration of the dictionaryWithObjects:forKeys:count: method. ObjCMethodDecl *DictionaryWithObjectsMethod; - /// \brief id<NSCopying> type. + /// id<NSCopying> type. QualType QIDNSCopying; - /// \brief will hold 'respondsToSelector:' + /// will hold 'respondsToSelector:' Selector RespondsToSelectorSel; /// A flag to remember whether the implicit forms of operator new and delete @@ -885,43 +890,43 @@ public: /// references to fields. This is really a bool AllowAbstractFieldReference; - /// \brief Describes how the expressions currently being parsed are + /// Describes how the expressions currently being parsed are /// evaluated at run-time, if at all. enum class ExpressionEvaluationContext { - /// \brief The current expression and its subexpressions occur within an + /// The current expression and its subexpressions occur within an /// unevaluated operand (C++11 [expr]p7), such as the subexpression of /// \c sizeof, where the type of the expression may be significant but /// no code will be generated to evaluate the value of the expression at /// run time. Unevaluated, - /// \brief The current expression occurs within a braced-init-list within + /// The current expression occurs within a braced-init-list within /// an unevaluated operand. This is mostly like a regular unevaluated /// context, except that we still instantiate constexpr functions that are /// referenced here so that we can perform narrowing checks correctly. UnevaluatedList, - /// \brief The current expression occurs within a discarded statement. + /// The current expression occurs within a discarded statement. /// This behaves largely similarly to an unevaluated operand in preventing /// definitions from being required, but not in other ways. DiscardedStatement, - /// \brief The current expression occurs within an unevaluated + /// The current expression occurs within an unevaluated /// operand that unconditionally permits abstract references to /// fields, such as a SIZE operator in MS-style inline assembly. UnevaluatedAbstract, - /// \brief The current context is "potentially evaluated" in C++11 terms, + /// The current context is "potentially evaluated" in C++11 terms, /// but the expression is evaluated at compile-time (like the values of /// cases in a switch statement). ConstantEvaluated, - /// \brief The current expression is potentially evaluated at run time, + /// The current expression is potentially evaluated at run time, /// which means that code may be generated to evaluate the value of the /// expression at run time. PotentiallyEvaluated, - /// \brief The current expression is potentially evaluated, but any + /// The current expression is potentially evaluated, but any /// declarations referenced inside that expression are only used if /// in fact the current expression is used. /// @@ -932,63 +937,69 @@ public: PotentiallyEvaluatedIfUsed }; - /// \brief Data structure used to record current or nested + /// Data structure used to record current or nested /// expression evaluation contexts. struct ExpressionEvaluationContextRecord { - /// \brief The expression evaluation context. + /// The expression evaluation context. ExpressionEvaluationContext Context; - /// \brief Whether the enclosing context needed a cleanup. + /// Whether the enclosing context needed a cleanup. CleanupInfo ParentCleanup; - /// \brief Whether we are in a decltype expression. + /// Whether we are in a decltype expression. bool IsDecltype; - /// \brief The number of active cleanup objects when we entered + /// The number of active cleanup objects when we entered /// this expression evaluation context. unsigned NumCleanupObjects; - /// \brief The number of typos encountered during this expression evaluation + /// 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 + /// The lambdas that are present within this context, if it /// is indeed an unevaluated context. SmallVector<LambdaExpr *, 2> Lambdas; - /// \brief The declaration that provides context for lambda expressions + /// The declaration that provides context for lambda expressions /// and block literals if the normal declaration context does not /// suffice, e.g., in a default function argument. Decl *ManglingContextDecl; - /// \brief The context information used to mangle lambda expressions + /// The context information used to mangle lambda expressions /// and block literals within this context. /// /// This mangling information is allocated lazily, since most contexts /// do not have lambda expressions or block literals. std::unique_ptr<MangleNumberingContext> MangleNumbering; - /// \brief If we are processing a decltype type, a set of call expressions + /// If we are processing a decltype type, a set of call expressions /// for which we have deferred checking the completeness of the return type. SmallVector<CallExpr *, 8> DelayedDecltypeCalls; - /// \brief If we are processing a decltype type, a set of temporary binding + /// If we are processing a decltype type, a set of temporary binding /// expressions for which we have deferred checking the destructor. SmallVector<CXXBindTemporaryExpr *, 8> DelayedDecltypeBinds; + /// \brief Describes whether we are in an expression constext which we have + /// to handle differently. + enum ExpressionKind { + EK_Decltype, EK_TemplateArgument, EK_Other + } ExprContext; + ExpressionEvaluationContextRecord(ExpressionEvaluationContext Context, unsigned NumCleanupObjects, CleanupInfo ParentCleanup, Decl *ManglingContextDecl, - bool IsDecltype) - : Context(Context), ParentCleanup(ParentCleanup), - IsDecltype(IsDecltype), NumCleanupObjects(NumCleanupObjects), - NumTypos(0), - ManglingContextDecl(ManglingContextDecl), MangleNumbering() { } + ExpressionKind ExprContext) + : Context(Context), ParentCleanup(ParentCleanup), + NumCleanupObjects(NumCleanupObjects), NumTypos(0), + ManglingContextDecl(ManglingContextDecl), MangleNumbering(), + ExprContext(ExprContext) {} - /// \brief Retrieve the mangling numbering context, used to consistently + /// Retrieve the mangling numbering context, used to consistently /// number constructs like lambdas for mangling. MangleNumberingContext &getMangleNumberingContext(ASTContext &Ctx); @@ -1005,7 +1016,7 @@ public: /// A stack of expression evaluation contexts. SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts; - /// \brief Compute the mangling number context for a lambda expression or + /// Compute the mangling number context for a lambda expression or /// block literal. /// /// \param DC - The DeclContext containing the lambda expression or @@ -1054,15 +1065,15 @@ public: {} }; - /// \brief A cache of special member function overload resolution results + /// A cache of special member function overload resolution results /// for C++ records. llvm::FoldingSet<SpecialMemberOverloadResultEntry> SpecialMemberCache; - /// \brief A cache of the flags available in enumerations with the flag_bits + /// A cache of the flags available in enumerations with the flag_bits /// attribute. mutable llvm::DenseMap<const EnumDecl*, llvm::APInt> FlagBitsCache; - /// \brief The kind of translation unit we are processing. + /// The kind of translation unit we are processing. /// /// When we're processing a complete translation unit, Sema will perform /// end-of-translation-unit semantic tasks (such as creating @@ -1073,13 +1084,13 @@ public: llvm::BumpPtrAllocator BumpAlloc; - /// \brief The number of SFINAE diagnostics that have been trapped. + /// The number of SFINAE diagnostics that have been trapped. unsigned NumSFINAEErrors; typedef llvm::DenseMap<ParmVarDecl *, llvm::TinyPtrVector<ParmVarDecl *>> UnparsedDefaultArgInstantiationsMap; - /// \brief A mapping from parameters with unparsed default arguments to the + /// A mapping from parameters with unparsed default arguments to the /// set of instantiations of each parameter. /// /// This mapping is a temporary data structure used when parsing @@ -1161,7 +1172,7 @@ public: bool isSelfExpr(Expr *RExpr); bool isSelfExpr(Expr *RExpr, const ObjCMethodDecl *Method); - /// \brief Cause the active diagnostic on the DiagosticsEngine to be + /// Cause the active diagnostic on the DiagosticsEngine to be /// emitted. This is closely coupled to the SemaDiagnosticBuilder class and /// should not be used elsewhere. void EmitCurrentDiagnostic(unsigned DiagID); @@ -1186,7 +1197,7 @@ public: CodeCompleteConsumer *CompletionConsumer = nullptr); ~Sema(); - /// \brief Perform initialization that occurs after the parser has been + /// Perform initialization that occurs after the parser has been /// initialized but before it parses anything. void Initialize(); @@ -1202,7 +1213,7 @@ public: ASTMutationListener *getASTMutationListener() const; ExternalSemaSource* getExternalSource() const { return ExternalSource; } - ///\brief Registers an external source. If an external source already exists, + ///Registers an external source. If an external source already exists, /// creates a multiplex external source and appends to it. /// ///\param[in] E - A non-null external sema source. @@ -1211,7 +1222,7 @@ public: void PrintStats() const; - /// \brief Helper class that creates diagnostics with optional + /// Helper class that creates diagnostics with optional /// template instantiation stacks. /// /// This class provides a wrapper around the basic DiagnosticBuilder @@ -1266,29 +1277,29 @@ public: } }; - /// \brief Emit a diagnostic. + /// Emit a diagnostic. SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) { DiagnosticBuilder DB = Diags.Report(Loc, DiagID); return SemaDiagnosticBuilder(DB, *this, DiagID); } - /// \brief Emit a partial diagnostic. + /// Emit a partial diagnostic. SemaDiagnosticBuilder Diag(SourceLocation Loc, const PartialDiagnostic& PD); - /// \brief Build a partial diagnostic. + /// Build a partial diagnostic. PartialDiagnostic PDiag(unsigned DiagID = 0); // in SemaInternal.h bool findMacroSpelling(SourceLocation &loc, StringRef name); - /// \brief Get a string to suggest for zero-initialization of a type. + /// Get a string to suggest for zero-initialization of a type. std::string getFixItZeroInitializerForType(QualType T, SourceLocation Loc) const; std::string getFixItZeroLiteralForType(QualType T, SourceLocation Loc) const; - /// \brief Calls \c Lexer::getLocForEndOfToken() + /// Calls \c Lexer::getLocForEndOfToken() SourceLocation getLocForEndOfToken(SourceLocation Loc, unsigned Offset = 0); - /// \brief Retrieve the module loader associated with the preprocessor. + /// Retrieve the module loader associated with the preprocessor. ModuleLoader &getModuleLoader() const; void emitAndClearUnusedLocalTypedefWarnings(); @@ -1304,7 +1315,7 @@ public: void PushBlockScope(Scope *BlockScope, BlockDecl *Block); sema::LambdaScopeInfo *PushLambdaScope(); - /// \brief This is used to inform Sema what the current TemplateParameterDepth + /// This is used to inform Sema what the current TemplateParameterDepth /// is during Parsing. Currently it is used to pass on the depth /// when parsing generic lambda 'auto' parameters. void RecordParsingTemplateParameterDepth(unsigned Depth); @@ -1318,35 +1329,23 @@ public: const BlockExpr *blkExpr = nullptr); sema::FunctionScopeInfo *getCurFunction() const { - return FunctionScopes.back(); + return FunctionScopes.empty() ? nullptr : FunctionScopes.back(); } - sema::FunctionScopeInfo *getEnclosingFunction() const { - if (FunctionScopes.empty()) - return nullptr; + sema::FunctionScopeInfo *getEnclosingFunction() const; - for (int e = FunctionScopes.size()-1; e >= 0; --e) { - if (isa<sema::BlockScopeInfo>(FunctionScopes[e])) - continue; - return FunctionScopes[e]; - } - return nullptr; - } + void setFunctionHasBranchIntoScope(); + void setFunctionHasBranchProtectedScope(); + void setFunctionHasIndirectGoto(); - template <typename ExprT> - void recordUseOfEvaluatedWeak(const ExprT *E, bool IsRead=true) { - if (!isUnevaluatedContext()) - getCurFunction()->recordUseOfWeak(E, IsRead); - } - - void PushCompoundScope(); + void PushCompoundScope(bool IsStmtExpr); void PopCompoundScope(); sema::CompoundScopeInfo &getCurCompoundScope() const; bool hasAnyUnrecoverableErrorsInThisFunction() const; - /// \brief Retrieve the current block, if any. + /// Retrieve the current block, if any. sema::BlockScopeInfo *getCurBlock(); /// Retrieve the current lambda scope info, if any. @@ -1356,10 +1355,10 @@ public: sema::LambdaScopeInfo * getCurLambda(bool IgnoreNonLambdaCapturingScope = false); - /// \brief Retrieve the current generic lambda info, if any. + /// Retrieve the current generic lambda info, if any. sema::LambdaScopeInfo *getCurGenericLambda(); - /// \brief Retrieve the current captured region, if any. + /// Retrieve the current captured region, if any. sema::CapturedRegionScopeInfo *getCurCapturedRegion(); /// WeakTopLevelDeclDecls - access to \#pragma weak-generated Decls @@ -1382,6 +1381,7 @@ public: QualType BuildArrayType(QualType T, ArrayType::ArraySizeModifier ASM, Expr *ArraySize, unsigned Quals, SourceRange Brackets, DeclarationName Entity); + QualType BuildVectorType(QualType T, Expr *VecSize, SourceLocation AttrLoc); QualType BuildExtVectorType(QualType T, Expr *ArraySize, SourceLocation AttrLoc); QualType BuildAddressSpaceAttr(QualType &T, Expr *AddrSpace, @@ -1389,7 +1389,7 @@ public: bool CheckFunctionReturnType(QualType T, SourceLocation Loc); - /// \brief Build a function type. + /// Build a function type. /// /// This routine checks the function type according to C++ rules and /// under the assumption that the result type and parameter types have @@ -1438,7 +1438,7 @@ public: TypeSourceInfo *GetTypeSourceInfoForDeclarator(Declarator &D, QualType T, TypeSourceInfo *ReturnTypeInfo); - /// \brief Package the given type and TSI into a ParsedType. + /// Package the given type and TSI into a ParsedType. ParsedType CreateParsedType(QualType T, TypeSourceInfo *TInfo); DeclarationNameInfo GetNameForDeclarator(Declarator &D); DeclarationNameInfo GetNameFromUnqualifiedId(const UnqualifiedId &Name); @@ -1459,6 +1459,7 @@ public: const PartialDiagnostic &DiagID, const PartialDiagnostic & NoteID, const FunctionProtoType *Old, SourceLocation OldLoc, const FunctionProtoType *New, SourceLocation NewLoc); + bool handlerCanCatch(QualType HandlerType, QualType ExceptionType); bool CheckExceptionSpecSubset(const PartialDiagnostic &DiagID, const PartialDiagnostic &NestedDiagID, const PartialDiagnostic &NoteID, @@ -1475,11 +1476,11 @@ public: TypeResult ActOnTypeName(Scope *S, Declarator &D); - /// \brief The parser has parsed the context-sensitive type 'instancetype' + /// The parser has parsed the context-sensitive type 'instancetype' /// in an Objective-C message declaration. Return the appropriate type. ParsedType ActOnObjCInstanceType(SourceLocation Loc); - /// \brief Abstract class used to diagnose incomplete types. + /// Abstract class used to diagnose incomplete types. struct TypeDiagnoser { TypeDiagnoser() {} @@ -1548,10 +1549,10 @@ private: VisibleModuleSet VisibleModules; public: - /// \brief Get the module owning an entity. + /// Get the module owning an entity. Module *getOwningModule(Decl *Entity) { return Entity->getOwningModule(); } - /// \brief Make a merged definition of an existing hidden definition \p ND + /// Make a merged definition of an existing hidden definition \p ND /// visible at the specified location. void makeMergedDefinitionVisible(NamedDecl *ND); @@ -1649,7 +1650,8 @@ public: } QualType getElaboratedType(ElaboratedTypeKeyword Keyword, - const CXXScopeSpec &SS, QualType T); + const CXXScopeSpec &SS, QualType T, + TagDecl *OwnedTagDecl = nullptr); QualType BuildTypeofExprType(Expr *E, SourceLocation Loc); /// If AsUnevaluated is false, E is treated as though it were an evaluated @@ -1705,7 +1707,7 @@ public: SourceLocation NameLoc, bool IsTemplateTypeArg); - /// \brief Describes the result of the name lookup and resolution performed + /// Describes the result of the name lookup and resolution performed /// by \c ClassifyName(). enum NameClassificationKind { NC_Unknown, @@ -1796,7 +1798,7 @@ public: } }; - /// \brief Perform name lookup on the given name, classifying it based on + /// Perform name lookup on the given name, classifying it based on /// the results of name lookup and the following token. /// /// This routine is used by the parser to resolve identifiers and help direct @@ -1840,13 +1842,19 @@ public: /// Determine whether it's plausible that E was intended to be a /// template-name. - bool mightBeIntendedToBeTemplateName(ExprResult E) { + bool mightBeIntendedToBeTemplateName(ExprResult E, bool &Dependent) { if (!getLangOpts().CPlusPlus || E.isInvalid()) return false; + Dependent = false; if (auto *DRE = dyn_cast<DeclRefExpr>(E.get())) return !DRE->hasExplicitTemplateArgs(); if (auto *ME = dyn_cast<MemberExpr>(E.get())) return !ME->hasExplicitTemplateArgs(); + Dependent = true; + if (auto *DSDRE = dyn_cast<DependentScopeDeclRefExpr>(E.get())) + return !DSDRE->hasExplicitTemplateArgs(); + if (auto *DSME = dyn_cast<CXXDependentScopeMemberExpr>(E.get())) + return !DSME->hasExplicitTemplateArgs(); // Any additional cases recognized here should also be handled by // diagnoseExprIntendedAsTemplateName. return false; @@ -1862,8 +1870,8 @@ public: void RegisterLocallyScopedExternCDecl(NamedDecl *ND, Scope *S); bool DiagnoseClassNameShadow(DeclContext *DC, DeclarationNameInfo Info); bool diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, - DeclarationName Name, - SourceLocation Loc); + DeclarationName Name, SourceLocation Loc, + bool IsTemplateId); void diagnoseIgnoredQualifiers(unsigned DiagID, unsigned Quals, SourceLocation FallbackLoc, @@ -1944,6 +1952,7 @@ public: bool shouldLinkDependentDeclWithPrevious(Decl *D, Decl *OldDecl); void CheckMain(FunctionDecl *FD, const DeclSpec &D); void CheckMSVCRTEntryPoint(FunctionDecl *FD); + Attr *getImplicitCodeSegOrSectionAttrForFunction(const FunctionDecl *FD, bool IsDefinition); Decl *ActOnParamDeclarator(Scope *S, Declarator &D); ParmVarDecl *BuildParmVarDeclForTypedef(DeclContext *DC, SourceLocation Loc, @@ -1999,7 +2008,7 @@ public: return D && isa<ObjCMethodDecl>(D); } - /// \brief Determine whether we can delay parsing the body of a function or + /// Determine whether we can delay parsing the body of a function or /// function template until it is used, assuming we don't care about emitting /// code for that function. /// @@ -2009,7 +2018,7 @@ public: /// or has an 'auto' return type in C++14. These cases are essentially bugs. bool canDelayFunctionBody(const Declarator &D); - /// \brief Determine whether we can skip parsing the body of a function + /// Determine whether we can skip parsing the body of a function /// definition, assuming we don't care about analyzing its body or emitting /// code for that function. /// @@ -2028,11 +2037,11 @@ public: /// attribute for which parsing is delayed. void ActOnFinishDelayedAttribute(Scope *S, Decl *D, ParsedAttributes &Attrs); - /// \brief Diagnose any unused parameters in the given sequence of + /// Diagnose any unused parameters in the given sequence of /// ParmVarDecl pointers. void DiagnoseUnusedParameters(ArrayRef<ParmVarDecl *> Parameters); - /// \brief Diagnose whether the size of parameters or return value of a + /// Diagnose whether the size of parameters or return value of a /// function or obj-c method definition is pass-by-value and larger than a /// specified threshold. void @@ -2044,9 +2053,8 @@ public: SourceLocation AsmLoc, SourceLocation RParenLoc); - /// \brief Handle a C++11 empty-declaration and attribute-declaration. - Decl *ActOnEmptyDeclaration(Scope *S, - AttributeList *AttrList, + /// Handle a C++11 empty-declaration and attribute-declaration. + Decl *ActOnEmptyDeclaration(Scope *S, const ParsedAttributesView &AttrList, SourceLocation SemiLoc); enum class ModuleDeclKind { @@ -2061,7 +2069,7 @@ public: SourceLocation ModuleLoc, ModuleDeclKind MDK, ModuleIdPath Path); - /// \brief The parser has processed a module import declaration. + /// The parser has processed a module import declaration. /// /// \param AtLoc The location of the '@' symbol, if any. /// @@ -2071,17 +2079,17 @@ public: DeclResult ActOnModuleImport(SourceLocation AtLoc, SourceLocation ImportLoc, ModuleIdPath Path); - /// \brief The parser has processed a module import translated from a + /// The parser has processed a module import translated from a /// #include or similar preprocessing directive. void ActOnModuleInclude(SourceLocation DirectiveLoc, Module *Mod); void BuildModuleInclude(SourceLocation DirectiveLoc, Module *Mod); - /// \brief The parsed has entered a submodule. + /// The parsed has entered a submodule. void ActOnModuleBegin(SourceLocation DirectiveLoc, Module *Mod); - /// \brief The parser has left a submodule. + /// The parser has left a submodule. void ActOnModuleEnd(SourceLocation DirectiveLoc, Module *Mod); - /// \brief Create an implicit import of the given module at the given + /// Create an implicit import of the given module at the given /// source location, for error recovery, if possible. /// /// This routine is typically used when an entity found by name lookup @@ -2100,7 +2108,7 @@ public: PartialSpecialization }; - /// \brief Diagnose that the specified declaration needs to be visible but + /// Diagnose that the specified declaration needs to be visible but /// isn't, and suggest a module import that would resolve the problem. void diagnoseMissingImport(SourceLocation Loc, NamedDecl *Decl, MissingImportKind MIK, bool Recover = true); @@ -2113,23 +2121,23 @@ public: Decl *ActOnFinishExportDecl(Scope *S, Decl *ExportDecl, SourceLocation RBraceLoc); - /// \brief We've found a use of a templated declaration that would trigger an + /// We've found a use of a templated declaration that would trigger an /// implicit instantiation. Check that any relevant explicit specializations /// and partial specializations are visible, and diagnose if not. void checkSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec); - /// \brief We've found a use of a template specialization that would select a + /// We've found a use of a template specialization that would select a /// partial specialization. Check that the partial specialization is visible, /// and diagnose if not. void checkPartialSpecializationVisibility(SourceLocation Loc, NamedDecl *Spec); - /// \brief Retrieve a suitable printing policy. + /// Retrieve a suitable printing policy for diagnostics. PrintingPolicy getPrintingPolicy() const { return getPrintingPolicy(Context, PP); } - /// \brief Retrieve a suitable printing policy. + /// Retrieve a suitable printing policy for diagnostics. static PrintingPolicy getPrintingPolicy(const ASTContext &Ctx, const Preprocessor &PP); @@ -2184,7 +2192,7 @@ public: Decl *ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, CXXScopeSpec &SS, IdentifierInfo *Name, - SourceLocation NameLoc, AttributeList *Attr, + SourceLocation NameLoc, const ParsedAttributesView &Attr, AccessSpecifier AS, SourceLocation ModulePrivateLoc, MultiTemplateParamsArg TemplateParameterLists, bool &OwnedDecl, bool &IsDependent, SourceLocation ScopedEnumKWLoc, @@ -2194,9 +2202,9 @@ public: Decl *ActOnTemplatedFriendTag(Scope *S, SourceLocation FriendLoc, unsigned TagSpec, SourceLocation TagLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr, MultiTemplateParamsArg TempParamLists); TypeResult ActOnDependentTag(Scope *S, @@ -2218,11 +2226,11 @@ public: InClassInitStyle InitStyle, AccessSpecifier AS); MSPropertyDecl *HandleMSProperty(Scope *S, RecordDecl *TagD, - SourceLocation DeclStart, - Declarator &D, Expr *BitfieldWidth, + SourceLocation DeclStart, Declarator &D, + Expr *BitfieldWidth, InClassInitStyle InitStyle, AccessSpecifier AS, - AttributeList *MSPropertyAttr); + const ParsedAttr &MSPropertyAttr); FieldDecl *CheckFieldDecl(DeclarationName Name, QualType T, TypeSourceInfo *TInfo, @@ -2235,7 +2243,17 @@ public: bool CheckNontrivialField(FieldDecl *FD); void DiagnoseNontrivial(const CXXRecordDecl *Record, CXXSpecialMember CSM); + + enum TrivialABIHandling { + /// The triviality of a method unaffected by "trivial_abi". + TAH_IgnoreTrivialABI, + + /// The triviality of a method affected by "trivial_abi". + TAH_ConsiderTrivialABI + }; + bool SpecialMemberIsTrivial(CXXMethodDecl *MD, CXXSpecialMember CSM, + TrivialABIHandling TAH = TAH_IgnoreTrivialABI, bool Diagnose = false); CXXSpecialMember getSpecialMember(const CXXMethodDecl *MD); void ActOnLastBitfield(SourceLocation DeclStart, @@ -2245,10 +2263,9 @@ public: tok::ObjCKeywordKind visibility); // This is used for both record definitions and ObjC interface declarations. - void ActOnFields(Scope* S, SourceLocation RecLoc, Decl *TagDecl, - ArrayRef<Decl *> Fields, - SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + void ActOnFields(Scope *S, SourceLocation RecLoc, Decl *TagDecl, + ArrayRef<Decl *> Fields, SourceLocation LBrac, + SourceLocation RBrac, const ParsedAttributesView &AttrList); /// ActOnTagStartDefinition - Invoked when we have entered the /// scope of a tag's definition (e.g., for an enumeration, class, @@ -2263,7 +2280,7 @@ public: typedef void *SkippedDefinitionContext; - /// \brief Invoked when we enter a tag definition that we're skipping. + /// Invoked when we enter a tag definition that we're skipping. SkippedDefinitionContext ActOnTagStartSkippedDefinition(Scope *S, Decl *TD); Decl *ActOnObjCContainerStartDefinition(Decl *IDecl); @@ -2285,7 +2302,7 @@ public: void ActOnObjCContainerFinishDefinition(); - /// \brief Invoked when we must temporarily exit the objective-c container + /// Invoked when we must temporarily exit the objective-c container /// scope for parsing/looking-up C constructs. /// /// Must be followed by a call to \see ActOnObjCReenterContainerContext @@ -2303,8 +2320,7 @@ public: Expr *val); bool CheckEnumUnderlyingType(TypeSourceInfo *TI); bool CheckEnumRedeclaration(SourceLocation EnumLoc, bool IsScoped, - QualType EnumUnderlyingTy, - bool EnumUnderlyingIsImplicit, + QualType EnumUnderlyingTy, bool IsFixed, const EnumDecl *Prev); /// Determine whether the body of an anonymous enumeration should be skipped. @@ -2314,12 +2330,11 @@ public: Decl *ActOnEnumConstant(Scope *S, Decl *EnumDecl, Decl *LastEnumConstant, SourceLocation IdLoc, IdentifierInfo *Id, - AttributeList *Attrs, SourceLocation EqualLoc, - Expr *Val); + const ParsedAttributesView &Attrs, + SourceLocation EqualLoc, Expr *Val); void ActOnEnumBody(SourceLocation EnumLoc, SourceRange BraceRange, - Decl *EnumDecl, - ArrayRef<Decl *> Elements, - Scope *S, AttributeList *Attr); + Decl *EnumDecl, ArrayRef<Decl *> Elements, Scope *S, + const ParsedAttributesView &Attr); DeclContext *getContainingDC(DeclContext *DC); @@ -2356,7 +2371,7 @@ public: /// Add this decl to the scope shadowed decl chains. void PushOnScopeChains(NamedDecl *D, Scope *S, bool AddToContext = true); - /// \brief Make the given externally-produced declaration visible at the + /// Make the given externally-produced declaration visible at the /// top level scope. /// /// \param D The externally-produced declaration to push. @@ -2383,18 +2398,18 @@ public: TypeSourceInfo *TInfo); bool isIncompatibleTypedef(TypeDecl *Old, TypedefNameDecl *New); - /// \brief Describes the kind of merge to perform for availability + /// Describes the kind of merge to perform for availability /// attributes (including "deprecated", "unavailable", and "availability"). enum AvailabilityMergeKind { - /// \brief Don't merge availability attributes at all. + /// Don't merge availability attributes at all. AMK_None, - /// \brief Merge availability attributes for a redeclaration, which requires + /// Merge availability attributes for a redeclaration, which requires /// an exact match. AMK_Redeclaration, - /// \brief Merge availability attributes for an override, which requires + /// Merge availability attributes for an override, which requires /// an exact match or a weakening of constraints. AMK_Override, - /// \brief Merge availability attributes for an implementation of + /// Merge availability attributes for an implementation of /// a protocol requirement. AMK_ProtocolImplementation, }; @@ -2432,6 +2447,8 @@ public: int FirstArg, unsigned AttrSpellingListIndex); SectionAttr *mergeSectionAttr(Decl *D, SourceRange Range, StringRef Name, unsigned AttrSpellingListIndex); + CodeSegAttr *mergeCodeSegAttr(Decl *D, SourceRange Range, StringRef Name, + unsigned AttrSpellingListIndex); AlwaysInlineAttr *mergeAlwaysInlineAttr(Decl *D, SourceRange Range, IdentifierInfo *Ident, unsigned AttrSpellingListIndex); @@ -2496,7 +2513,7 @@ public: bool IsOverload(FunctionDecl *New, FunctionDecl *Old, bool IsForUsingDecl, bool ConsiderCudaAttrs = true); - /// \brief Checks availability of the function depending on the current + /// Checks availability of the function depending on the current /// function context.Inside an unavailable function,unavailability is ignored. /// /// \returns true if \p FD is unavailable and current context is inside @@ -2568,6 +2585,11 @@ public: NamedDecl *FoundDecl, CXXMethodDecl *Method); + /// Check that the lifetime of the initializer (and its subobjects) is + /// sufficient for initializing the entity, and perform lifetime extension + /// (when permitted) if not. + void checkInitializerLifetime(const InitializedEntity &Entity, Expr *Init); + ExprResult PerformContextuallyConvertToBool(Expr *From); ExprResult PerformContextuallyConvertToObjCPointer(Expr *From); @@ -2584,7 +2606,7 @@ public: ExprResult CheckConvertedConstantExpression(Expr *From, QualType T, APValue &Value, CCEKind CCE); - /// \brief Abstract base class used to perform a contextual implicit + /// Abstract base class used to perform a contextual implicit /// conversion from an expression to any type passing a filter. class ContextualImplicitConverter { public: @@ -2595,38 +2617,38 @@ public: bool SuppressConversion = false) : Suppress(Suppress), SuppressConversion(SuppressConversion) {} - /// \brief Determine whether the specified type is a valid destination type + /// Determine whether the specified type is a valid destination type /// for this conversion. virtual bool match(QualType T) = 0; - /// \brief Emits a diagnostic complaining that the expression does not have + /// Emits a diagnostic complaining that the expression does not have /// integral or enumeration type. virtual SemaDiagnosticBuilder diagnoseNoMatch(Sema &S, SourceLocation Loc, QualType T) = 0; - /// \brief Emits a diagnostic when the expression has incomplete class type. + /// Emits a diagnostic when the expression has incomplete class type. virtual SemaDiagnosticBuilder diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) = 0; - /// \brief Emits a diagnostic when the only matching conversion function + /// Emits a diagnostic when the only matching conversion function /// is explicit. virtual SemaDiagnosticBuilder diagnoseExplicitConv( Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0; - /// \brief Emits a note for the explicit conversion function. + /// Emits a note for the explicit conversion function. virtual SemaDiagnosticBuilder noteExplicitConv(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; - /// \brief Emits a diagnostic when there are multiple possible conversion + /// Emits a diagnostic when there are multiple possible conversion /// functions. virtual SemaDiagnosticBuilder diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) = 0; - /// \brief Emits a note for one of the candidate conversions. + /// Emits a note for one of the candidate conversions. virtual SemaDiagnosticBuilder noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) = 0; - /// \brief Emits a diagnostic when we picked a conversion function + /// Emits a diagnostic when we picked a conversion function /// (for cases when we are not allowed to pick a conversion function). virtual SemaDiagnosticBuilder diagnoseConversion( Sema &S, SourceLocation Loc, QualType T, QualType ConvTy) = 0; @@ -2651,7 +2673,7 @@ public: return diagnoseNotInt(S, Loc, T); } - /// \brief Emits a diagnostic complaining that the expression does not have + /// Emits a diagnostic complaining that the expression does not have /// integral or enumeration type. virtual SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, QualType T) = 0; @@ -2986,7 +3008,7 @@ public: /// the ability to distinguish among them. //@{ - /// @brief Describes the kind of name lookup to perform. + /// Describes the kind of name lookup to perform. enum LookupNameKind { /// Ordinary name lookup, which finds ordinary names (functions, /// variables, typedefs, etc.) in C and most kinds of names @@ -3028,22 +3050,22 @@ public: LookupObjCProtocolName, /// Look up implicit 'self' parameter of an objective-c method. LookupObjCImplicitSelfParam, - /// \brief Look up the name of an OpenMP user-defined reduction operation. + /// Look up the name of an OpenMP user-defined reduction operation. LookupOMPReductionName, - /// \brief Look up any declaration with any name. + /// Look up any declaration with any name. LookupAnyName }; - /// \brief Specifies whether (or how) name lookup is being performed for a + /// Specifies whether (or how) name lookup is being performed for a /// redeclaration (vs. a reference). enum RedeclarationKind { - /// \brief The lookup is a reference to this name that is not for the + /// The lookup is a reference to this name that is not for the /// purpose of redeclaring the name. NotForRedeclaration = 0, - /// \brief The lookup results will be used for redeclaration of a name, + /// The lookup results will be used for redeclaration of a name, /// if an entity by that name already exists and is visible. ForVisibleRedeclaration, - /// \brief The lookup results will be used for redeclaration of a name + /// The lookup results will be used for redeclaration of a name /// with external linkage; non-visible lookup results with external linkage /// may also be found. ForExternalRedeclaration @@ -3060,23 +3082,23 @@ public: return ForExternalRedeclaration; } - /// \brief The possible outcomes of name lookup for a literal operator. + /// The possible outcomes of name lookup for a literal operator. enum LiteralOperatorLookupResult { - /// \brief The lookup resulted in an error. + /// The lookup resulted in an error. LOLR_Error, - /// \brief The lookup found no match but no diagnostic was issued. + /// The lookup found no match but no diagnostic was issued. LOLR_ErrorNoDiagnostic, - /// \brief The lookup found a single 'cooked' literal operator, which + /// The lookup found a single 'cooked' literal operator, which /// expects a normal literal to be built and passed to it. LOLR_Cooked, - /// \brief The lookup found a single 'raw' literal operator, which expects + /// The lookup found a single 'raw' literal operator, which expects /// a string literal containing the spelling of the literal token. LOLR_Raw, - /// \brief The lookup found an overload set of literal operator templates, + /// The lookup found an overload set of literal operator templates, /// which expect the characters of the spelling of the literal token to be /// passed as a non-type template argument pack. LOLR_Template, - /// \brief The lookup found an overload set of literal operator templates, + /// The lookup found an overload set of literal operator templates, /// which expect the character type and characters of the spelling of the /// string literal token to be passed as template arguments. LOLR_StringTemplate @@ -3106,25 +3128,25 @@ private: TypoExprState &operator=(TypoExprState &&other) noexcept; }; - /// \brief The set of unhandled TypoExprs and their associated state. + /// The set of unhandled TypoExprs and their associated state. llvm::MapVector<TypoExpr *, TypoExprState> DelayedTypos; - /// \brief Creates a new TypoExpr AST node. + /// 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 set of known/encountered (unique, canonicalized) NamespaceDecls. // // The boolean value will be true to indicate that the namespace was loaded // from an AST/PCH file, or false otherwise. llvm::MapVector<NamespaceDecl*, bool> KnownNamespaces; - /// \brief Whether we have already loaded known namespaces from an extenal + /// Whether we have already loaded known namespaces from an extenal /// source. bool LoadedExternalKnownNamespaces; - /// \brief Helper for CorrectTypo and CorrectTypoDelayed used to create and + /// 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> @@ -3139,10 +3161,10 @@ private: public: const TypoExprState &getTypoExprState(TypoExpr *TE) const; - /// \brief Clears the state of the given TypoExpr. + /// Clears the state of the given TypoExpr. void clearDelayedTypo(TypoExpr *TE); - /// \brief Look up a name, looking for a single declaration. Return + /// Look up a name, looking for a single declaration. Return /// null if the results were absent, ambiguous, or overloaded. /// /// It is preferable to use the elaborated form and explicitly handle @@ -3199,11 +3221,13 @@ public: void LookupVisibleDecls(Scope *S, LookupNameKind Kind, VisibleDeclConsumer &Consumer, - bool IncludeGlobalScope = true); + bool IncludeGlobalScope = true, + bool LoadExternal = true); void LookupVisibleDecls(DeclContext *Ctx, LookupNameKind Kind, VisibleDeclConsumer &Consumer, bool IncludeGlobalScope = true, - bool IncludeDependentBases = false); + bool IncludeDependentBases = false, + bool LoadExternal = true); enum CorrectTypoKind { CTK_NonError, // CorrectTypo used in a non error recovery situation. @@ -3230,7 +3254,7 @@ public: bool EnteringContext = false, const ObjCObjectPointerType *OPT = nullptr); - /// \brief Process any TypoExprs in the given Expr and its children, + /// Process any TypoExprs in the given Expr and its children, /// generating diagnostics as appropriate and returning a new Expr if there /// were typos that were all successfully corrected and ExprError if one or /// more typos could not be corrected. @@ -3308,11 +3332,12 @@ public: // Decl attributes - this routine is the top level dispatcher. void ProcessDeclAttributes(Scope *S, Decl *D, const Declarator &PD); // Helper for delayed processing of attributes. - void ProcessDeclAttributeDelayed(Decl *D, const AttributeList *AttrList); - void ProcessDeclAttributeList(Scope *S, Decl *D, const AttributeList *AL, - bool IncludeCXX11Attributes = true); + void ProcessDeclAttributeDelayed(Decl *D, + const ParsedAttributesView &AttrList); + void ProcessDeclAttributeList(Scope *S, Decl *D, const ParsedAttributesView &AL, + bool IncludeCXX11Attributes = true); bool ProcessAccessDeclAttributeList(AccessSpecDecl *ASDecl, - const AttributeList *AttrList); + const ParsedAttributesView &AttrList); void checkUnusedDeclAttributes(Declarator &D); @@ -3322,13 +3347,13 @@ public: /// type as valid. bool isValidPointerAttrType(QualType T, bool RefOkay = false); - bool CheckRegparmAttr(const AttributeList &attr, unsigned &value); - bool CheckCallingConvAttr(const AttributeList &attr, CallingConv &CC, + bool CheckRegparmAttr(const ParsedAttr &attr, unsigned &value); + bool CheckCallingConvAttr(const ParsedAttr &attr, CallingConv &CC, const FunctionDecl *FD = nullptr); - bool CheckNoReturnAttr(const AttributeList &attr); - bool CheckNoCallerSavedRegsAttr(const AttributeList &attr); - bool checkStringLiteralArgumentAttr(const AttributeList &Attr, - unsigned ArgNum, StringRef &Str, + bool CheckAttrTarget(const ParsedAttr &CurrAttr); + bool CheckAttrNoArgs(const ParsedAttr &CurrAttr); + bool checkStringLiteralArgumentAttr(const ParsedAttr &Attr, unsigned ArgNum, + StringRef &Str, SourceLocation *ArgLocation = nullptr); bool checkSectionName(SourceLocation LiteralLoc, StringRef Str); bool checkTargetAttr(SourceLocation LiteralLoc, StringRef Str); @@ -3377,8 +3402,9 @@ public: bool isContextSensitive, bool allowArrayTypes); - /// \brief Stmt attributes - this routine is the top level dispatcher. - StmtResult ProcessStmtAttributes(Stmt *Stmt, AttributeList *Attrs, + /// Stmt attributes - this routine is the top level dispatcher. + StmtResult ProcessStmtAttributes(Stmt *Stmt, + const ParsedAttributesView &Attrs, SourceRange Range); void WarnConflictingTypedMethods(ObjCMethodDecl *Method, @@ -3520,7 +3546,7 @@ public: /// warns each time an exact match is found. void CheckCategoryVsClassMethodMatches(ObjCCategoryImplDecl *CatIMP); - /// \brief Add the given method to the list of globally-known methods. + /// Add the given method to the list of globally-known methods. void addMethodToGlobalList(ObjCMethodList *List, ObjCMethodDecl *Method); private: @@ -3535,7 +3561,7 @@ private: bool instance); public: - /// \brief - Returns instance or factory methods in global method pool for + /// - Returns instance or factory methods in global method pool for /// given selector. It checks the desired kind first, if none is found, and /// parameter checkTheOther is set, it then checks the other kind. If no such /// method or only one method is found, function returns false; otherwise, it @@ -3557,14 +3583,14 @@ public: bool receiverIdOrClass); private: - /// \brief - Returns a selector which best matches given argument list or + /// - Returns a selector which best matches given argument list or /// nullptr if none could be found ObjCMethodDecl *SelectBestMethod(Selector Sel, MultiExprArg Args, bool IsInstance, SmallVectorImpl<ObjCMethodDecl*>& Methods); - /// \brief Record the typo correction failure and return an empty correction. + /// Record the typo correction failure and return an empty correction. TypoCorrection FailedCorrection(IdentifierInfo *Typo, SourceLocation TypoLoc, bool RecordFailure = true) { if (RecordFailure) @@ -3664,16 +3690,16 @@ public: StmtResult ActOnNullStmt(SourceLocation SemiLoc, bool HasLeadingEmptyMacro = false); - void ActOnStartOfCompoundStmt(); + void ActOnStartOfCompoundStmt(bool IsStmtExpr); void ActOnFinishOfCompoundStmt(); StmtResult ActOnCompoundStmt(SourceLocation L, SourceLocation R, ArrayRef<Stmt *> Elts, bool isStmtExpr); - /// \brief A RAII object to enter scope of a compound statement. + /// A RAII object to enter scope of a compound statement. class CompoundScopeRAII { public: - CompoundScopeRAII(Sema &S): S(S) { - S.ActOnStartOfCompoundStmt(); + CompoundScopeRAII(Sema &S, bool IsStmtExpr = false) : S(S) { + S.ActOnStartOfCompoundStmt(IsStmtExpr); } ~CompoundScopeRAII() { @@ -3701,9 +3727,10 @@ public: SourceLocation EndLoc); void ActOnForEachDeclStmt(DeclGroupPtrTy Decl); StmtResult ActOnForEachLValueExpr(Expr *E); - StmtResult ActOnCaseStmt(SourceLocation CaseLoc, Expr *LHSVal, - SourceLocation DotDotDotLoc, Expr *RHSVal, - SourceLocation ColonLoc); + ExprResult ActOnCaseExpr(SourceLocation CaseLoc, ExprResult Val); + StmtResult ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHS, + SourceLocation DotDotDotLoc, ExprResult RHS, + SourceLocation ColonLoc); void ActOnCaseStmtBody(Stmt *CaseStmt, Stmt *SubStmt); StmtResult ActOnDefaultStmt(SourceLocation DefaultLoc, @@ -3797,10 +3824,22 @@ public: RecordDecl *CreateCapturedStmtRecordDecl(CapturedDecl *&CD, SourceLocation Loc, unsigned NumParams); + + enum CopyElisionSemanticsKind { + CES_Strict = 0, + CES_AllowParameters = 1, + CES_AllowDifferentTypes = 2, + CES_AllowExceptionVariables = 4, + CES_FormerDefault = (CES_AllowParameters), + CES_Default = (CES_AllowParameters | CES_AllowDifferentTypes), + CES_AsIfByStdMove = (CES_AllowParameters | CES_AllowDifferentTypes | + CES_AllowExceptionVariables), + }; + VarDecl *getCopyElisionCandidate(QualType ReturnType, Expr *E, - bool AllowParamOrMoveConstructible); + CopyElisionSemanticsKind CESK); bool isCopyElisionCandidate(QualType ReturnType, const VarDecl *VD, - bool AllowParamOrMoveConstructible); + CopyElisionSemanticsKind CESK); StmtResult ActOnReturnStmt(SourceLocation ReturnLoc, Expr *RetValExp, Scope *CurScope); @@ -3889,7 +3928,7 @@ public: bool ShouldWarnIfUnusedFileScopedDecl(const DeclaratorDecl *D) const; - /// \brief If it's a file scoped decl that must warn if not used, keep track + /// If it's a file scoped decl that must warn if not used, keep track /// of it. void MarkUnusedFileScopedDecl(const DeclaratorDecl *D); @@ -3918,7 +3957,7 @@ public: void DiagnoseSelfMove(const Expr *LHSExpr, const Expr *RHSExpr, SourceLocation OpLoc); - /// \brief Warn if we're implicitly casting from a _Nullable pointer type to a + /// Warn if we're implicitly casting from a _Nullable pointer type to a /// _Nonnull one. void diagnoseNullableToNonnullConversion(QualType DstType, QualType SrcType, SourceLocation Loc); @@ -3941,7 +3980,7 @@ public: void redelayDiagnostics(sema::DelayedDiagnosticPool &pool); - void DiagnoseAvailabilityOfDecl(NamedDecl *D, SourceLocation Loc, + void DiagnoseAvailabilityOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass, bool ObjCPropertyAccess, bool AvoidPartialAvailabilityChecks = false); @@ -3949,14 +3988,14 @@ public: bool makeUnavailableInSystemHeader(SourceLocation loc, UnavailableAttr::ImplicitReason reason); - /// \brief Issue any -Wunguarded-availability warnings in \c FD + /// Issue any -Wunguarded-availability warnings in \c FD void DiagnoseUnguardedAvailabilityViolations(Decl *FD); //===--------------------------------------------------------------------===// // Expression Parsing Callbacks: SemaExpr.cpp. bool CanUseDecl(NamedDecl *D, bool TreatUnavailableAsInvalid); - bool DiagnoseUseOfDecl(NamedDecl *D, SourceLocation Loc, + bool DiagnoseUseOfDecl(NamedDecl *D, ArrayRef<SourceLocation> Locs, const ObjCInterfaceDecl *UnknownObjCClass = nullptr, bool ObjCPropertyAccess = false, bool AvoidPartialAvailabilityChecks = false); @@ -3969,13 +4008,15 @@ public: void DiagnoseSentinelCalls(NamedDecl *D, SourceLocation Loc, ArrayRef<Expr *> Args); - void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false); + void PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl = nullptr, + ExpressionEvaluationContextRecord::ExpressionKind Type = + ExpressionEvaluationContextRecord::EK_Other); enum ReuseLambdaContextDecl_t { ReuseLambdaContextDecl }; - void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, - ReuseLambdaContextDecl_t, - bool IsDecltype = false); + void PushExpressionEvaluationContext( + ExpressionEvaluationContext NewContext, ReuseLambdaContextDecl_t, + ExpressionEvaluationContextRecord::ExpressionKind Type = + ExpressionEvaluationContextRecord::EK_Other); void PopExpressionEvaluationContext(); void DiscardCleanupsInEvaluationContext(); @@ -4011,7 +4052,7 @@ public: TryCapture_Implicit, TryCapture_ExplicitByVal, TryCapture_ExplicitByRef }; - /// \brief Try to capture the given variable. + /// Try to capture the given variable. /// /// \param Var The variable to capture. /// @@ -4050,15 +4091,15 @@ public: QualType &DeclRefType, const unsigned *const FunctionScopeIndexToStopAt); - /// \brief Try to capture the given variable. + /// Try to capture the given variable. bool tryCaptureVariable(VarDecl *Var, SourceLocation Loc, TryCaptureKind Kind = TryCapture_Implicit, SourceLocation EllipsisLoc = SourceLocation()); - /// \brief Checks if the variable must be captured. + /// 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 + /// Given a variable, determine the type that a reference to that /// variable will have in the given scope. QualType getCapturedDeclRefType(VarDecl *Var, SourceLocation Loc); @@ -4069,18 +4110,18 @@ public: void MarkDeclarationsReferencedInExpr(Expr *E, bool SkipLocalVariables = false); - /// \brief Try to recover by turning the given expression into a + /// Try to recover by turning the given expression into a /// call. Returns true if recovery was attempted or an error was /// emitted; this may also leave the ExprResult invalid. bool tryToRecoverWithCall(ExprResult &E, const PartialDiagnostic &PD, bool ForceComplain = false, bool (*IsPlausibleResult)(QualType) = nullptr); - /// \brief Figure out if an expression could be turned into a call. + /// Figure out if an expression could be turned into a call. bool tryExprAsCall(Expr &E, QualType &ZeroArgCallReturnTy, UnresolvedSetImpl &NonTemplateOverloads); - /// \brief Conditionally issue a diagnostic based on the current + /// Conditionally issue a diagnostic based on the current /// evaluation context. /// /// \param Statement If Statement is non-null, delay reporting the @@ -4222,6 +4263,7 @@ public: ExprResult ActOnUnaryOp(Scope *S, SourceLocation OpLoc, tok::TokenKind Op, Expr *Input); + bool isQualifiedMemberAccess(Expr *E); QualType CheckAddressOfOperand(ExprResult &Operand, SourceLocation OpLoc); ExprResult CreateUnaryExprOrTypeTraitExpr(TypeSourceInfo *TInfo, @@ -4354,7 +4396,7 @@ public: Expr *Op); CastKind PrepareScalarCast(ExprResult &src, QualType destType); - /// \brief Build an altivec or OpenCL literal. + /// Build an altivec or OpenCL literal. ExprResult BuildVectorLiteral(SourceLocation LParenLoc, SourceLocation RParenLoc, Expr *E, TypeSourceInfo *TInfo); @@ -4446,19 +4488,19 @@ public: bool CheckCaseExpression(Expr *E); - /// \brief Describes the result of an "if-exists" condition check. + /// Describes the result of an "if-exists" condition check. enum IfExistsResult { - /// \brief The symbol exists. + /// The symbol exists. IER_Exists, - /// \brief The symbol does not exist. + /// The symbol does not exist. IER_DoesNotExist, - /// \brief The name is a dependent name, so the results will differ + /// The name is a dependent name, so the results will differ /// from one instantiation to the next. IER_Dependent, - /// \brief An error occurred. + /// An error occurred. IER_Error }; @@ -4520,11 +4562,10 @@ public: // Act on C++ namespaces Decl *ActOnStartNamespaceDef(Scope *S, SourceLocation InlineLoc, SourceLocation NamespaceLoc, - SourceLocation IdentLoc, - IdentifierInfo *Ident, + SourceLocation IdentLoc, IdentifierInfo *Ident, SourceLocation LBrace, - AttributeList *AttrList, - UsingDirectiveDecl * &UsingDecl); + const ParsedAttributesView &AttrList, + UsingDirectiveDecl *&UsingDecl); void ActOnFinishNamespaceDef(Decl *Dcl, SourceLocation RBrace); NamespaceDecl *getStdNamespace() const; @@ -4535,27 +4576,41 @@ public: CXXRecordDecl *getStdBadAlloc() const; EnumDecl *getStdAlignValT() const; - /// \brief Tests whether Ty is an instance of std::initializer_list and, if +private: + // A cache representing if we've fully checked the various comparison category + // types stored in ASTContext. The bit-index corresponds to the integer value + // of a ComparisonCategoryType enumerator. + llvm::SmallBitVector FullyCheckedComparisonCategories; + +public: + /// Lookup the specified comparison category types in the standard + /// library, an check the VarDecls possibly returned by the operator<=> + /// builtins for that type. + /// + /// \return The type of the comparison category type corresponding to the + /// specified Kind, or a null type if an error occurs + QualType CheckComparisonCategoryType(ComparisonCategoryType Kind, + SourceLocation Loc); + + /// Tests whether Ty is an instance of std::initializer_list and, if /// it is and Element is not NULL, assigns the element type to Element. bool isStdInitializerList(QualType Ty, QualType *Element); - /// \brief Looks for the std::initializer_list template and instantiates it + /// Looks for the std::initializer_list template and instantiates it /// with Element, or emits an error if it's not found. /// /// \returns The instantiated template, or null on error. QualType BuildStdInitializerList(QualType Element, SourceLocation Loc); - /// \brief Determine whether Ctor is an initializer-list constructor, as + /// Determine whether Ctor is an initializer-list constructor, as /// defined in [dcl.init.list]p2. bool isInitListConstructor(const FunctionDecl *Ctor); - Decl *ActOnUsingDirective(Scope *CurScope, - SourceLocation UsingLoc, - SourceLocation NamespcLoc, - CXXScopeSpec &SS, + Decl *ActOnUsingDirective(Scope *CurScope, SourceLocation UsingLoc, + SourceLocation NamespcLoc, CXXScopeSpec &SS, SourceLocation IdentLoc, IdentifierInfo *NamespcName, - AttributeList *AttrList); + const ParsedAttributesView &AttrList); void PushUsingDirective(Scope *S, UsingDirectiveDecl *UDir); @@ -4586,15 +4641,11 @@ public: const DeclarationNameInfo &NameInfo, SourceLocation NameLoc); - NamedDecl *BuildUsingDeclaration(Scope *S, AccessSpecifier AS, - SourceLocation UsingLoc, - bool HasTypenameKeyword, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - DeclarationNameInfo NameInfo, - SourceLocation EllipsisLoc, - AttributeList *AttrList, - bool IsInstantiation); + NamedDecl *BuildUsingDeclaration( + Scope *S, AccessSpecifier AS, SourceLocation UsingLoc, + bool HasTypenameKeyword, SourceLocation TypenameLoc, CXXScopeSpec &SS, + DeclarationNameInfo NameInfo, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList, bool IsInstantiation); NamedDecl *BuildUsingPackDecl(NamedDecl *InstantiatedFrom, ArrayRef<NamedDecl *> Expansions); @@ -4607,22 +4658,16 @@ public: findInheritingConstructor(SourceLocation Loc, CXXConstructorDecl *BaseCtor, ConstructorUsingShadowDecl *DerivedShadow); - Decl *ActOnUsingDeclaration(Scope *CurScope, - AccessSpecifier AS, + Decl *ActOnUsingDeclaration(Scope *CurScope, AccessSpecifier AS, SourceLocation UsingLoc, - SourceLocation TypenameLoc, - CXXScopeSpec &SS, - UnqualifiedId &Name, - SourceLocation EllipsisLoc, - AttributeList *AttrList); - Decl *ActOnAliasDeclaration(Scope *CurScope, - AccessSpecifier AS, + SourceLocation TypenameLoc, CXXScopeSpec &SS, + UnqualifiedId &Name, SourceLocation EllipsisLoc, + const ParsedAttributesView &AttrList); + Decl *ActOnAliasDeclaration(Scope *CurScope, AccessSpecifier AS, MultiTemplateParamsArg TemplateParams, - SourceLocation UsingLoc, - UnqualifiedId &Name, - AttributeList *AttrList, - TypeResult Type, - Decl *DeclFromDeclSpec); + SourceLocation UsingLoc, UnqualifiedId &Name, + const ParsedAttributesView &AttrList, + TypeResult Type, Decl *DeclFromDeclSpec); /// BuildCXXConstructExpr - Creates a complete call to a constructor, /// including handling of its default argument expressions. @@ -4677,7 +4722,7 @@ public: /// constructed variable. void FinalizeVarWithDestructor(VarDecl *VD, const RecordType *DeclInitType); - /// \brief Helper class that collects exception specifications for + /// Helper class that collects exception specifications for /// implicitly-declared special member functions. class ImplicitExceptionSpecification { // Pointer to allow copying @@ -4704,26 +4749,26 @@ public: ComputedEST = EST_DynamicNone; } - /// \brief Get the computed exception specification type. + /// Get the computed exception specification type. ExceptionSpecificationType getExceptionSpecType() const { - assert(ComputedEST != EST_ComputedNoexcept && + assert(!isComputedNoexcept(ComputedEST) && "noexcept(expr) should not be a possible result"); return ComputedEST; } - /// \brief The number of exceptions in the exception specification. + /// The number of exceptions in the exception specification. unsigned size() const { return Exceptions.size(); } - /// \brief The set of exceptions in the exception specification. + /// The set of exceptions in the exception specification. const QualType *data() const { return Exceptions.data(); } - /// \brief Integrate another called method into the collected data. + /// Integrate another called method into the collected data. void CalledDecl(SourceLocation CallLoc, const CXXMethodDecl *Method); - /// \brief Integrate an invoked expression into the collected data. + /// Integrate an invoked expression into the collected data. void CalledExpr(Expr *E); - /// \brief Overwrite an EPI's exception specification with this + /// Overwrite an EPI's exception specification with this /// computed exception specification. FunctionProtoType::ExceptionSpecInfo getExceptionSpec() const { FunctionProtoType::ExceptionSpecInfo ESI; @@ -4734,7 +4779,7 @@ public: /// C++11 [except.spec]p14: /// The exception-specification is noexcept(false) if the set of /// potential exceptions of the special member function contains "any" - ESI.Type = EST_ComputedNoexcept; + ESI.Type = EST_NoexceptFalse; ESI.NoexceptExpr = Self->ActOnCXXBoolLiteral(SourceLocation(), tok::kw_false).get(); } @@ -4742,50 +4787,55 @@ public: } }; - /// \brief Determine what sort of exception specification a defaulted + /// Determine what sort of exception specification a defaulted /// copy constructor of a class will have. ImplicitExceptionSpecification ComputeDefaultedDefaultCtorExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD); - /// \brief Determine what sort of exception specification a defaulted + /// Determine what sort of exception specification a defaulted /// default constructor of a class will have, and whether the parameter /// will be const. ImplicitExceptionSpecification ComputeDefaultedCopyCtorExceptionSpec(CXXMethodDecl *MD); - /// \brief Determine what sort of exception specification a defautled + /// Determine what sort of exception specification a defautled /// copy assignment operator of a class will have, and whether the /// parameter will be const. ImplicitExceptionSpecification ComputeDefaultedCopyAssignmentExceptionSpec(CXXMethodDecl *MD); - /// \brief Determine what sort of exception specification a defaulted move + /// Determine what sort of exception specification a defaulted move /// constructor of a class will have. ImplicitExceptionSpecification ComputeDefaultedMoveCtorExceptionSpec(CXXMethodDecl *MD); - /// \brief Determine what sort of exception specification a defaulted move + /// Determine what sort of exception specification a defaulted move /// assignment operator of a class will have. ImplicitExceptionSpecification ComputeDefaultedMoveAssignmentExceptionSpec(CXXMethodDecl *MD); - /// \brief Determine what sort of exception specification a defaulted + /// Determine what sort of exception specification a defaulted /// destructor of a class will have. ImplicitExceptionSpecification ComputeDefaultedDtorExceptionSpec(CXXMethodDecl *MD); - /// \brief Determine what sort of exception specification an inheriting + /// Determine what sort of exception specification an inheriting /// constructor of a class will have. ImplicitExceptionSpecification ComputeInheritingCtorExceptionSpec(SourceLocation Loc, CXXConstructorDecl *CD); - /// \brief Evaluate the implicit exception specification for a defaulted + /// Evaluate the implicit exception specification for a defaulted /// special member function. void EvaluateImplicitExceptionSpec(SourceLocation Loc, CXXMethodDecl *MD); - /// \brief Check the given exception-specification and update the + /// Check the given noexcept-specifier, convert its expression, and compute + /// the appropriate ExceptionSpecificationType. + ExprResult ActOnNoexceptSpec(SourceLocation NoexceptLoc, Expr *NoexceptExpr, + ExceptionSpecificationType &EST); + + /// Check the given exception-specification and update the /// exception specification information with the results. void checkExceptionSpecification(bool IsTopLevel, ExceptionSpecificationType EST, @@ -4795,11 +4845,11 @@ public: SmallVectorImpl<QualType> &Exceptions, FunctionProtoType::ExceptionSpecInfo &ESI); - /// \brief Determine if we're in a case where we need to (incorrectly) eagerly + /// 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 + /// 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, @@ -4811,13 +4861,13 @@ public: class InheritedConstructorInfo; - /// \brief Determine if a special member function should have a deleted + /// Determine if a special member function should have a deleted /// definition when it is defaulted. bool ShouldDeleteSpecialMember(CXXMethodDecl *MD, CXXSpecialMember CSM, InheritedConstructorInfo *ICI = nullptr, bool Diagnose = false); - /// \brief Declare the implicit default constructor for the given class. + /// Declare the implicit default constructor for the given class. /// /// \param ClassDecl The class declaration into which the implicit /// default constructor will be added. @@ -4831,7 +4881,7 @@ public: void DefineImplicitDefaultConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor); - /// \brief Declare the implicit destructor for the given class. + /// Declare the implicit destructor for the given class. /// /// \param ClassDecl The class declaration into which the implicit /// destructor will be added. @@ -4844,18 +4894,18 @@ public: void DefineImplicitDestructor(SourceLocation CurrentLocation, CXXDestructorDecl *Destructor); - /// \brief Build an exception spec for destructors that don't have one. + /// Build an exception spec for destructors that don't have one. /// /// C++11 says that user-defined destructors with no exception spec get one /// that looks as if the destructor was implicitly declared. void AdjustDestructorExceptionSpec(CXXRecordDecl *ClassDecl, CXXDestructorDecl *Destructor); - /// \brief Define the specified inheriting constructor. + /// Define the specified inheriting constructor. void DefineInheritingConstructor(SourceLocation UseLoc, CXXConstructorDecl *Constructor); - /// \brief Declare the implicit copy constructor for the given class. + /// Declare the implicit copy constructor for the given class. /// /// \param ClassDecl The class declaration into which the implicit /// copy constructor will be added. @@ -4868,7 +4918,7 @@ public: void DefineImplicitCopyConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor); - /// \brief Declare the implicit move constructor for the given class. + /// Declare the implicit move constructor for the given class. /// /// \param ClassDecl The Class declaration into which the implicit /// move constructor will be added. @@ -4882,7 +4932,7 @@ public: void DefineImplicitMoveConstructor(SourceLocation CurrentLocation, CXXConstructorDecl *Constructor); - /// \brief Declare the implicit copy assignment operator for the given class. + /// Declare the implicit copy assignment operator for the given class. /// /// \param ClassDecl The class declaration into which the implicit /// copy assignment operator will be added. @@ -4890,11 +4940,11 @@ public: /// \returns The implicitly-declared copy assignment operator. CXXMethodDecl *DeclareImplicitCopyAssignment(CXXRecordDecl *ClassDecl); - /// \brief Defines an implicitly-declared copy assignment operator. + /// Defines an implicitly-declared copy assignment operator. void DefineImplicitCopyAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MethodDecl); - /// \brief Declare the implicit move assignment operator for the given class. + /// Declare the implicit move assignment operator for the given class. /// /// \param ClassDecl The Class declaration into which the implicit /// move assignment operator will be added. @@ -4903,32 +4953,32 @@ public: /// wasn't declared. CXXMethodDecl *DeclareImplicitMoveAssignment(CXXRecordDecl *ClassDecl); - /// \brief Defines an implicitly-declared move assignment operator. + /// Defines an implicitly-declared move assignment operator. void DefineImplicitMoveAssignment(SourceLocation CurrentLocation, CXXMethodDecl *MethodDecl); - /// \brief Force the declaration of any implicitly-declared members of this + /// Force the declaration of any implicitly-declared members of this /// class. void ForceDeclarationOfImplicitMembers(CXXRecordDecl *Class); - /// \brief Check a completed declaration of an implicit special member. + /// Check a completed declaration of an implicit special member. void CheckImplicitSpecialMemberDeclaration(Scope *S, FunctionDecl *FD); - /// \brief Determine whether the given function is an implicitly-deleted + /// Determine whether the given function is an implicitly-deleted /// special member function. bool isImplicitlyDeleted(FunctionDecl *FD); - /// \brief Check whether 'this' shows up in the type of a static member + /// Check whether 'this' shows up in the type of a static member /// function after the (naturally empty) cv-qualifier-seq would be. /// /// \returns true if an error occurred. bool checkThisInStaticMemberFunctionType(CXXMethodDecl *Method); - /// \brief Whether this' shows up in the exception specification of a static + /// Whether this' shows up in the exception specification of a static /// member function. bool checkThisInStaticMemberFunctionExceptionSpec(CXXMethodDecl *Method); - /// \brief Check whether 'this' shows up in the attributes of the given + /// Check whether 'this' shows up in the attributes of the given /// static member function. /// /// \returns true if an error occurred. @@ -4950,6 +5000,9 @@ public: SourceLocation NameLoc, IdentifierInfo &Name); + ParsedType getConstructorName(IdentifierInfo &II, SourceLocation NameLoc, + Scope *S, CXXScopeSpec &SS, + bool EnteringContext); ParsedType getDestructorName(SourceLocation TildeLoc, IdentifierInfo &II, SourceLocation NameLoc, Scope *S, CXXScopeSpec &SS, @@ -5010,7 +5063,7 @@ public: void *TyOrExpr, SourceLocation RParenLoc); - /// \brief Handle a C++1z fold-expression: ( expr op ... op expr ). + /// Handle a C++1z fold-expression: ( expr op ... op expr ). ExprResult ActOnCXXFoldExpr(SourceLocation LParenLoc, Expr *LHS, tok::TokenKind Operator, SourceLocation EllipsisLoc, Expr *RHS, @@ -5025,17 +5078,17 @@ public: //// ActOnCXXThis - Parse 'this' pointer. ExprResult ActOnCXXThis(SourceLocation loc); - /// \brief Try to retrieve the type of the 'this' pointer. + /// Try to retrieve the type of the 'this' pointer. /// /// \returns The type of 'this', if possible. Otherwise, returns a NULL type. QualType getCurrentThisType(); - /// \brief When non-NULL, the C++ 'this' expression is allowed despite the + /// When non-NULL, the C++ 'this' expression is allowed despite the /// current context not being a non-static member function. In such cases, /// this provides the type used for 'this'. QualType CXXThisTypeOverride; - /// \brief RAII object used to temporarily allow the C++ 'this' expression + /// RAII object used to temporarily allow the C++ 'this' expression /// to be used, with the given qualifiers on the current class type. class CXXThisScopeRAII { Sema &S; @@ -5043,7 +5096,7 @@ public: bool Enabled; public: - /// \brief Introduce a new scope where 'this' may be allowed (when enabled), + /// Introduce a new scope where 'this' may be allowed (when enabled), /// using the given declaration (which is either a class template or a /// class) along with the given qualifiers. /// along with the qualifiers placed on '*this'. @@ -5053,7 +5106,7 @@ public: ~CXXThisScopeRAII(); }; - /// \brief Make sure the value of 'this' is actually available in the current + /// Make sure the value of 'this' is actually available in the current /// context, if it is a potentially evaluated context. /// /// \param Loc The location at which the capture of 'this' occurs. @@ -5073,7 +5126,7 @@ public: const unsigned *const FunctionScopeIndexToStopAt = nullptr, bool ByCopy = false); - /// \brief Determine whether the given type is the type of *this that is used + /// Determine whether the given type is the type of *this that is used /// outside of the body of a member function for a type that is currently /// being defined. bool isThisOutsideMemberFunctionBody(QualType BaseType); @@ -5103,14 +5156,16 @@ public: /// or class type construction ("ClassType(x,y,z)") /// or creation of a value-initialized type ("int()"). ExprResult ActOnCXXTypeConstructExpr(ParsedType TypeRep, - SourceLocation LParenLoc, + SourceLocation LParenOrBraceLoc, MultiExprArg Exprs, - SourceLocation RParenLoc); + SourceLocation RParenOrBraceLoc, + bool ListInitialization); ExprResult BuildCXXTypeConstructExpr(TypeSourceInfo *Type, SourceLocation LParenLoc, MultiExprArg Exprs, - SourceLocation RParenLoc); + SourceLocation RParenLoc, + bool ListInitialization); /// ActOnCXXNew - Parsed a C++ 'new' expression. ExprResult ActOnCXXNew(SourceLocation StartLoc, bool UseGlobal, @@ -5132,11 +5187,29 @@ public: bool CheckAllocatedType(QualType AllocType, SourceLocation Loc, SourceRange R); + + /// The scope in which to find allocation functions. + enum AllocationFunctionScope { + /// Only look for allocation functions in the global scope. + AFS_Global, + /// Only look for allocation functions in the scope of the + /// allocated class. + AFS_Class, + /// Look for allocation functions in both the global scope + /// and in the scope of the allocated class. + AFS_Both + }; + + /// Finds the overloads of operator new and delete that are appropriate + /// for the allocation. bool FindAllocationFunctions(SourceLocation StartLoc, SourceRange Range, - bool UseGlobal, QualType AllocType, bool IsArray, + AllocationFunctionScope NewScope, + AllocationFunctionScope DeleteScope, + QualType AllocType, bool IsArray, bool &PassAlignment, MultiExprArg PlaceArgs, FunctionDecl *&OperatorNew, - FunctionDecl *&OperatorDelete); + FunctionDecl *&OperatorDelete, + bool Diagnose = true); void DeclareGlobalNewDelete(); void DeclareGlobalAllocationFunction(DeclarationName Name, QualType Return, ArrayRef<QualType> Params); @@ -5165,7 +5238,7 @@ public: ExprResult BuildCXXNoexceptExpr(SourceLocation KeyLoc, Expr *Operand, SourceLocation RParen); - /// \brief Parsed one of the type trait support pseudo-functions. + /// Parsed one of the type trait support pseudo-functions. ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc, ArrayRef<ParsedType> Args, SourceLocation RParenLoc); @@ -5260,7 +5333,7 @@ public: bool isDependentScopeSpecifier(const CXXScopeSpec &SS); CXXRecordDecl *getCurrentInstantiationOf(NestedNameSpecifier *NNS); - /// \brief The parser has parsed a global nested-name-specifier '::'. + /// The parser has parsed a global nested-name-specifier '::'. /// /// \param CCLoc The location of the '::'. /// @@ -5270,7 +5343,7 @@ public: /// \returns true if an error occurred, false otherwise. bool ActOnCXXGlobalScopeSpecifier(SourceLocation CCLoc, CXXScopeSpec &SS); - /// \brief The parser has parsed a '__super' nested-name-specifier. + /// The parser has parsed a '__super' nested-name-specifier. /// /// \param SuperLoc The location of the '__super' keyword. /// @@ -5287,23 +5360,23 @@ public: bool *CanCorrect = nullptr); NamedDecl *FindFirstQualifierInScope(Scope *S, NestedNameSpecifier *NNS); - /// \brief Keeps information about an identifier in a nested-name-spec. + /// Keeps information about an identifier in a nested-name-spec. /// struct NestedNameSpecInfo { - /// \brief The type of the object, if we're parsing nested-name-specifier in + /// The type of the object, if we're parsing nested-name-specifier in /// a member access expression. ParsedType ObjectType; - /// \brief The identifier preceding the '::'. + /// The identifier preceding the '::'. IdentifierInfo *Identifier; - /// \brief The location of the identifier. + /// The location of the identifier. SourceLocation IdentifierLoc; - /// \brief The location of the '::'. + /// The location of the '::'. SourceLocation CCLoc; - /// \brief Creates info object for the most typical case. + /// Creates info object for the most typical case. NestedNameSpecInfo(IdentifierInfo *II, SourceLocation IdLoc, SourceLocation ColonColonLoc, ParsedType ObjectType = ParsedType()) : ObjectType(ObjectType), Identifier(II), IdentifierLoc(IdLoc), @@ -5329,7 +5402,7 @@ public: bool *IsCorrectedToColon = nullptr, bool OnlyNamespace = false); - /// \brief The parser has parsed a nested-name-specifier 'identifier::'. + /// The parser has parsed a nested-name-specifier 'identifier::'. /// /// \param S The scope in which this nested-name-specifier occurs. /// @@ -5372,7 +5445,7 @@ public: NestedNameSpecInfo &IdInfo, bool EnteringContext); - /// \brief The parser has parsed a nested-name-specifier + /// The parser has parsed a nested-name-specifier /// 'template[opt] template-name < template-args >::'. /// /// \param S The scope in which this nested-name-specifier occurs. @@ -5406,7 +5479,7 @@ public: SourceLocation CCLoc, bool EnteringContext); - /// \brief Given a C++ nested-name-specifier, produce an annotation value + /// Given a C++ nested-name-specifier, produce an annotation value /// that the parser can use later to reconstruct the given /// nested-name-specifier. /// @@ -5416,7 +5489,7 @@ public: /// nested-name-specifier \p SS. void *SaveNestedNameSpecifierAnnotation(CXXScopeSpec &SS); - /// \brief Given an annotation pointer for a nested-name-specifier, restore + /// Given an annotation pointer for a nested-name-specifier, restore /// the nested-name-specifier structure. /// /// \param Annotation The annotation pointer, produced by @@ -5458,13 +5531,13 @@ public: /// initializer for the declaration 'Dcl'. void ActOnCXXExitDeclInitializer(Scope *S, Decl *Dcl); - /// \brief Create a new lambda closure type. + /// Create a new lambda closure type. CXXRecordDecl *createLambdaClosureType(SourceRange IntroducerRange, TypeSourceInfo *Info, bool KnownDependent, LambdaCaptureDefault CaptureDefault); - /// \brief Start the definition of a lambda expression. + /// Start the definition of a lambda expression. CXXMethodDecl *startLambdaDefinition(CXXRecordDecl *Class, SourceRange IntroducerRange, TypeSourceInfo *MethodType, @@ -5472,7 +5545,7 @@ public: ArrayRef<ParmVarDecl *> Params, bool IsConstexprSpecified); - /// \brief Endow the lambda scope info with the relevant properties. + /// Endow the lambda scope info with the relevant properties. void buildLambdaScope(sema::LambdaScopeInfo *LSI, CXXMethodDecl *CallOperator, SourceRange IntroducerRange, @@ -5482,7 +5555,7 @@ public: bool ExplicitResultType, bool Mutable); - /// \brief Perform initialization analysis of the init-capture and perform + /// Perform initialization analysis of the init-capture and perform /// any implicit conversions such as an lvalue-to-rvalue conversion if /// not being used to initialize a reference. ParsedType actOnLambdaInitCaptureInitialization( @@ -5495,7 +5568,7 @@ public: IdentifierInfo *Id, bool DirectInit, Expr *&Init); - /// \brief Create a dummy variable within the declcontext of the lambda's + /// Create a dummy variable within the declcontext of the lambda's /// call operator, for name lookup purposes for a lambda init capture. /// /// CodeGen handles emission of lambda captures, ignoring these dummy @@ -5505,17 +5578,17 @@ public: IdentifierInfo *Id, unsigned InitStyle, Expr *Init); - /// \brief Build the implicit field for an init-capture. + /// Build the implicit field for an init-capture. FieldDecl *buildInitCaptureField(sema::LambdaScopeInfo *LSI, VarDecl *Var); - /// \brief Note that we have finished the explicit captures for the + /// Note that we have finished the explicit captures for the /// given lambda. void finishLambdaExplicitCaptures(sema::LambdaScopeInfo *LSI); - /// \brief Introduce the lambda parameters into scope. + /// Introduce the lambda parameters into scope. void addLambdaParameters(CXXMethodDecl *CallOperator, Scope *CurScope); - /// \brief Deduce a block or lambda's return type based on the return + /// Deduce a block or lambda's return type based on the return /// statements present in the body. void deduceClosureReturnType(sema::CapturingScopeInfo &CSI); @@ -5536,18 +5609,25 @@ public: ExprResult ActOnLambdaExpr(SourceLocation StartLoc, Stmt *Body, Scope *CurScope); - /// \brief Does copying/destroying the captured variable have side effects? - bool CaptureHasSideEffects(const sema::LambdaScopeInfo::Capture &From); + /// Does copying/destroying the captured variable have side effects? + bool CaptureHasSideEffects(const sema::Capture &From); - /// \brief Diagnose if an explicit lambda capture is unused. - void DiagnoseUnusedLambdaCapture(const sema::LambdaScopeInfo::Capture &From); + /// Diagnose if an explicit lambda capture is unused. Returns true if a + /// diagnostic is emitted. + bool DiagnoseUnusedLambdaCapture(SourceRange CaptureRange, + const sema::Capture &From); - /// \brief Complete a lambda-expression having processed and attached the + /// Complete a lambda-expression having processed and attached the /// lambda body. ExprResult BuildLambdaExpr(SourceLocation StartLoc, SourceLocation EndLoc, sema::LambdaScopeInfo *LSI); - /// \brief Define the "body" of the conversion from a lambda object to a + /// Get the return type to use for a lambda's conversion function(s) to + /// function pointer type, given the type of the call operator. + QualType + getLambdaConversionFunctionResultType(const FunctionProtoType *CallOpType); + + /// Define the "body" of the conversion from a lambda object to a /// function pointer. /// /// This routine doesn't actually define a sensible body; rather, it fills @@ -5557,7 +5637,7 @@ public: void DefineImplicitLambdaToFunctionPointerConversion( SourceLocation CurrentLoc, CXXConversionDecl *Conv); - /// \brief Define the "body" of the conversion from a lambda object to a + /// Define the "body" of the conversion from a lambda object to a /// block pointer. /// /// This routine doesn't actually define a sensible body; rather, it fills @@ -5645,14 +5725,14 @@ public: //===--------------------------------------------------------------------===// // C++ Classes // + CXXRecordDecl *getCurrentClass(Scope *S, const CXXScopeSpec *SS); bool isCurrentClassName(const IdentifierInfo &II, Scope *S, const CXXScopeSpec *SS = nullptr); bool isCurrentClassNameTypo(IdentifierInfo *&II, const CXXScopeSpec *SS); - bool ActOnAccessSpecifier(AccessSpecifier Access, - SourceLocation ASLoc, + bool ActOnAccessSpecifier(AccessSpecifier Access, SourceLocation ASLoc, SourceLocation ColonLoc, - AttributeList *Attrs = nullptr); + const ParsedAttributesView &Attrs); NamedDecl *ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, @@ -5726,30 +5806,30 @@ public: void MarkBaseAndMemberDestructorsReferenced(SourceLocation Loc, CXXRecordDecl *Record); - /// \brief The list of classes whose vtables have been used within + /// The list of classes whose vtables have been used within /// this translation unit, and the source locations at which the /// first use occurred. typedef std::pair<CXXRecordDecl*, SourceLocation> VTableUse; - /// \brief The list of vtables that are required but have not yet been + /// The list of vtables that are required but have not yet been /// materialized. SmallVector<VTableUse, 16> VTableUses; - /// \brief The set of classes whose vtables have been used within + /// The set of classes whose vtables have been used within /// this translation unit, and a bit that will be true if the vtable is /// required to be emitted (otherwise, it should be emitted only if needed /// by code generation). llvm::DenseMap<CXXRecordDecl *, bool> VTablesUsed; - /// \brief Load any externally-stored vtable uses. + /// Load any externally-stored vtable uses. void LoadExternalVTableUses(); - /// \brief Note that the vtable for the given class was used at the + /// Note that the vtable for the given class was used at the /// given location. void MarkVTableUsed(SourceLocation Loc, CXXRecordDecl *Class, bool DefinitionRequired = false); - /// \brief Mark the exception specifications of all virtual member functions + /// Mark the exception specifications of all virtual member functions /// in the given class as needed. void MarkVirtualMemberExceptionSpecsNeeded(SourceLocation Loc, const CXXRecordDecl *RD); @@ -5759,7 +5839,7 @@ public: void MarkVirtualMembersReferenced(SourceLocation Loc, const CXXRecordDecl *RD); - /// \brief Define all of the vtables that have been used in this + /// Define all of the vtables that have been used in this /// translation unit and reference any virtual members used by those /// vtables. /// @@ -5773,10 +5853,11 @@ public: ArrayRef<CXXCtorInitializer*> MemInits, bool AnyErrors); - /// \brief Check class-level dllimport/dllexport attribute. The caller must + /// Check class-level dllimport/dllexport attribute. The caller must /// ensure that referenceDLLExportedClassMethods is called some point later /// when all outer classes of Class are complete. void checkClassLevelDLLAttribute(CXXRecordDecl *Class); + void checkClassLevelCodeSegAttribute(CXXRecordDecl *Class); void referenceDLLExportedClassMethods(); @@ -5786,11 +5867,15 @@ public: SourceLocation BaseLoc); void CheckCompletedCXXClass(CXXRecordDecl *Record); - void ActOnFinishCXXMemberSpecification(Scope* S, SourceLocation RLoc, - Decl *TagDecl, - SourceLocation LBrac, + + /// Check that the C++ class annoated with "trivial_abi" satisfies all the + /// conditions that are needed for the attribute to have an effect. + void checkIllFormedTrivialABIStruct(CXXRecordDecl &RD); + + void ActOnFinishCXXMemberSpecification(Scope *S, SourceLocation RLoc, + Decl *TagDecl, SourceLocation LBrac, SourceLocation RBrac, - AttributeList *AttrList); + const ParsedAttributesView &AttrList); void ActOnFinishCXXMemberDecls(); void ActOnFinishCXXNonNestedClass(Decl *D); @@ -5984,7 +6069,7 @@ public: void HandleDelayedAccessCheck(sema::DelayedDiagnostic &DD, Decl *Ctx); - /// \brief When true, access checking violations are treated as SFINAE + /// When true, access checking violations are treated as SFINAE /// failures rather than hard errors. bool AccessCheckingSFINAE; @@ -6027,14 +6112,15 @@ public: bool hasAnyAcceptableTemplateNames(LookupResult &R, bool AllowFunctionTemplates = true); - void LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, + bool LookupTemplateName(LookupResult &R, Scope *S, CXXScopeSpec &SS, QualType ObjectType, bool EnteringContext, - bool &MemberOfUnknownSpecialization); + bool &MemberOfUnknownSpecialization, + SourceLocation TemplateKWLoc = SourceLocation()); TemplateNameKind isTemplateName(Scope *S, CXXScopeSpec &SS, bool hasTemplateKeyword, - UnqualifiedId &Name, + const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, TemplateTy &Template, @@ -6102,7 +6188,7 @@ public: SourceLocation RAngleLoc, Expr *RequiresClause); - /// \brief The context in which we are checking a template parameter list. + /// The context in which we are checking a template parameter list. enum TemplateParamListContext { TPC_ClassTemplate, TPC_VarTemplate, @@ -6123,17 +6209,14 @@ public: ArrayRef<TemplateParameterList *> ParamLists, bool IsFriend, bool &IsMemberSpecialization, bool &Invalid); - DeclResult CheckClassTemplate(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, CXXScopeSpec &SS, - IdentifierInfo *Name, SourceLocation NameLoc, - AttributeList *Attr, - TemplateParameterList *TemplateParams, - AccessSpecifier AS, - SourceLocation ModulePrivateLoc, - SourceLocation FriendLoc, - unsigned NumOuterTemplateParamLists, - TemplateParameterList **OuterTemplateParamLists, - SkipBodyInfo *SkipBody = nullptr); + DeclResult CheckClassTemplate( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, SourceLocation NameLoc, + const ParsedAttributesView &Attr, TemplateParameterList *TemplateParams, + AccessSpecifier AS, SourceLocation ModulePrivateLoc, + SourceLocation FriendLoc, unsigned NumOuterTemplateParamLists, + TemplateParameterList **OuterTemplateParamLists, + SkipBodyInfo *SkipBody = nullptr); TemplateArgumentLoc getTrivialTemplateArgumentLoc(const TemplateArgument &Arg, QualType NTTPType, @@ -6142,6 +6225,8 @@ public: void translateTemplateArguments(const ASTTemplateArgsPtr &In, TemplateArgumentListInfo &Out); + ParsedTemplateArgument ActOnTemplateTypeArgument(TypeResult ParsedType); + void NoteAllFoundTemplates(TemplateName Name); QualType CheckTemplateIdType(TemplateName Template, @@ -6158,7 +6243,7 @@ public: bool IsCtorOrDtorName = false, bool IsClassName = false); - /// \brief Parsed an elaborated-type-specifier that refers to a template-id, + /// Parsed an elaborated-type-specifier that refers to a template-id, /// such as \c class T::template apply<U>. TypeResult ActOnTagTemplateIdType(TagUseKind TUK, TypeSpecifierType TagSpec, @@ -6187,6 +6272,8 @@ public: SourceLocation TemplateLoc, const TemplateArgumentListInfo *TemplateArgs); + void diagnoseMissingTemplateArguments(TemplateName Name, SourceLocation Loc); + ExprResult BuildTemplateIdExpr(const CXXScopeSpec &SS, SourceLocation TemplateKWLoc, LookupResult &R, @@ -6200,17 +6287,15 @@ public: TemplateNameKind ActOnDependentTemplateName( Scope *S, CXXScopeSpec &SS, SourceLocation TemplateKWLoc, - UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, + const UnqualifiedId &Name, ParsedType ObjectType, bool EnteringContext, TemplateTy &Template, bool AllowInjectedClassName = false); - DeclResult - ActOnClassTemplateSpecialization(Scope *S, unsigned TagSpec, TagUseKind TUK, - SourceLocation KWLoc, - SourceLocation ModulePrivateLoc, - TemplateIdAnnotation &TemplateId, - AttributeList *Attr, - MultiTemplateParamsArg TemplateParameterLists, - SkipBodyInfo *SkipBody = nullptr); + DeclResult ActOnClassTemplateSpecialization( + Scope *S, unsigned TagSpec, TagUseKind TUK, SourceLocation KWLoc, + SourceLocation ModulePrivateLoc, TemplateIdAnnotation &TemplateId, + const ParsedAttributesView &Attr, + MultiTemplateParamsArg TemplateParameterLists, + SkipBodyInfo *SkipBody = nullptr); bool CheckTemplatePartialSpecializationArgs(SourceLocation Loc, TemplateDecl *PrimaryTemplate, @@ -6243,30 +6328,19 @@ public: bool CheckMemberSpecialization(NamedDecl *Member, LookupResult &Previous); void CompleteMemberSpecialization(NamedDecl *Member, LookupResult &Previous); - DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - const CXXScopeSpec &SS, - TemplateTy Template, - SourceLocation TemplateNameLoc, - SourceLocation LAngleLoc, - ASTTemplateArgsPtr TemplateArgs, - SourceLocation RAngleLoc, - AttributeList *Attr); + DeclResult ActOnExplicitInstantiation( + Scope *S, SourceLocation ExternLoc, SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, const CXXScopeSpec &SS, + TemplateTy Template, SourceLocation TemplateNameLoc, + SourceLocation LAngleLoc, ASTTemplateArgsPtr TemplateArgs, + SourceLocation RAngleLoc, const ParsedAttributesView &Attr); - DeclResult - ActOnExplicitInstantiation(Scope *S, - SourceLocation ExternLoc, - SourceLocation TemplateLoc, - unsigned TagSpec, - SourceLocation KWLoc, - CXXScopeSpec &SS, - IdentifierInfo *Name, - SourceLocation NameLoc, - AttributeList *Attr); + DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, + SourceLocation TemplateLoc, + unsigned TagSpec, SourceLocation KWLoc, + CXXScopeSpec &SS, IdentifierInfo *Name, + SourceLocation NameLoc, + const ParsedAttributesView &Attr); DeclResult ActOnExplicitInstantiation(Scope *S, SourceLocation ExternLoc, @@ -6282,18 +6356,18 @@ public: &Converted, bool &HasDefaultArg); - /// \brief Specifies the context in which a particular template + /// Specifies the context in which a particular template /// argument is being checked. enum CheckTemplateArgumentKind { - /// \brief The template argument was specified in the code or was + /// The template argument was specified in the code or was /// instantiated with some deduced template arguments. CTAK_Specified, - /// \brief The template argument was deduced via template argument + /// The template argument was deduced via template argument /// deduction. CTAK_Deduced, - /// \brief The template argument was deduced from an array bound + /// The template argument was deduced from an array bound /// via template argument deduction. CTAK_DeducedFromArrayBound }; @@ -6307,7 +6381,7 @@ public: SmallVectorImpl<TemplateArgument> &Converted, CheckTemplateArgumentKind CTAK = CTAK_Specified); - /// \brief Check that the given template arguments can be be provided to + /// Check that the given template arguments can be be provided to /// the given template, converting the arguments along the way. /// /// \param Template The template to which the template arguments are being @@ -6349,9 +6423,8 @@ public: QualType InstantiatedParamType, Expr *Arg, TemplateArgument &Converted, CheckTemplateArgumentKind CTAK = CTAK_Specified); - bool CheckTemplateArgument(TemplateTemplateParmDecl *Param, - TemplateArgumentLoc &Arg, - unsigned ArgumentPackIndex); + bool CheckTemplateTemplateArgument(TemplateParameterList *Params, + TemplateArgumentLoc &Arg); ExprResult BuildExpressionFromDeclTemplateArgument(const TemplateArgument &Arg, @@ -6361,10 +6434,10 @@ public: BuildExpressionFromIntegralTemplateArgument(const TemplateArgument &Arg, SourceLocation Loc); - /// \brief Enumeration describing how template parameter lists are compared + /// Enumeration describing how template parameter lists are compared /// for equality. enum TemplateParameterListEqualKind { - /// \brief We are matching the template parameter lists of two templates + /// We are matching the template parameter lists of two templates /// that might be redeclarations. /// /// \code @@ -6373,7 +6446,7 @@ public: /// \endcode TPL_TemplateMatch, - /// \brief We are matching the template parameter lists of two template + /// We are matching the template parameter lists of two template /// template parameters as part of matching the template parameter lists /// of two templates that might be redeclarations. /// @@ -6383,7 +6456,7 @@ public: /// \endcode TPL_TemplateTemplateParmMatch, - /// \brief We are matching the template parameter lists of a template + /// We are matching the template parameter lists of a template /// template argument against the template parameter lists of a template /// template parameter. /// @@ -6404,7 +6477,7 @@ public: bool CheckTemplateDeclScope(Scope *S, TemplateParameterList *TemplateParams); - /// \brief Called when the parser has parsed a C++ typename + /// Called when the parser has parsed a C++ typename /// specifier, e.g., "typename T::type". /// /// \param S The scope in which this typename type occurs. @@ -6417,7 +6490,7 @@ public: const CXXScopeSpec &SS, const IdentifierInfo &II, SourceLocation IdLoc); - /// \brief Called when the parser has parsed a C++ typename + /// Called when the parser has parsed a C++ typename /// specifier that ends in a template-id, e.g., /// "typename MetaFun::template apply<T1, T2>". /// @@ -6474,74 +6547,74 @@ public: /// location. Useful for error recovery. bool isUnexpandedParameterPackPermitted(); - /// \brief The context in which an unexpanded parameter pack is + /// The context in which an unexpanded parameter pack is /// being diagnosed. /// /// Note that the values of this enumeration line up with the first /// argument to the \c err_unexpanded_parameter_pack diagnostic. enum UnexpandedParameterPackContext { - /// \brief An arbitrary expression. + /// An arbitrary expression. UPPC_Expression = 0, - /// \brief The base type of a class type. + /// The base type of a class type. UPPC_BaseType, - /// \brief The type of an arbitrary declaration. + /// The type of an arbitrary declaration. UPPC_DeclarationType, - /// \brief The type of a data member. + /// The type of a data member. UPPC_DataMemberType, - /// \brief The size of a bit-field. + /// The size of a bit-field. UPPC_BitFieldWidth, - /// \brief The expression in a static assertion. + /// The expression in a static assertion. UPPC_StaticAssertExpression, - /// \brief The fixed underlying type of an enumeration. + /// The fixed underlying type of an enumeration. UPPC_FixedUnderlyingType, - /// \brief The enumerator value. + /// The enumerator value. UPPC_EnumeratorValue, - /// \brief A using declaration. + /// A using declaration. UPPC_UsingDeclaration, - /// \brief A friend declaration. + /// A friend declaration. UPPC_FriendDeclaration, - /// \brief A declaration qualifier. + /// A declaration qualifier. UPPC_DeclarationQualifier, - /// \brief An initializer. + /// An initializer. UPPC_Initializer, - /// \brief A default argument. + /// A default argument. UPPC_DefaultArgument, - /// \brief The type of a non-type template parameter. + /// The type of a non-type template parameter. UPPC_NonTypeTemplateParameterType, - /// \brief The type of an exception. + /// The type of an exception. UPPC_ExceptionType, - /// \brief Partial specialization. + /// Partial specialization. UPPC_PartialSpecialization, - /// \brief Microsoft __if_exists. + /// Microsoft __if_exists. UPPC_IfExists, - /// \brief Microsoft __if_not_exists. + /// Microsoft __if_not_exists. UPPC_IfNotExists, - /// \brief Lambda expression. + /// Lambda expression. UPPC_Lambda, - /// \brief Block expression, + /// Block expression, UPPC_Block }; - /// \brief Diagnose unexpanded parameter packs. + /// Diagnose unexpanded parameter packs. /// /// \param Loc The location at which we should emit the diagnostic. /// @@ -6555,7 +6628,7 @@ public: UnexpandedParameterPackContext UPPC, ArrayRef<UnexpandedParameterPack> Unexpanded); - /// \brief If the given type contains an unexpanded parameter pack, + /// If the given type contains an unexpanded parameter pack, /// diagnose the error. /// /// \param Loc The source location where a diagnostc should be emitted. @@ -6567,7 +6640,7 @@ public: bool DiagnoseUnexpandedParameterPack(SourceLocation Loc, TypeSourceInfo *T, UnexpandedParameterPackContext UPPC); - /// \brief If the given expression contains an unexpanded parameter + /// If the given expression contains an unexpanded parameter /// pack, diagnose the error. /// /// \param E The expression that is being checked for unexpanded @@ -6577,7 +6650,7 @@ public: bool DiagnoseUnexpandedParameterPack(Expr *E, UnexpandedParameterPackContext UPPC = UPPC_Expression); - /// \brief If the given nested-name-specifier contains an unexpanded + /// If the given nested-name-specifier contains an unexpanded /// parameter pack, diagnose the error. /// /// \param SS The nested-name-specifier that is being checked for @@ -6587,7 +6660,7 @@ public: bool DiagnoseUnexpandedParameterPack(const CXXScopeSpec &SS, UnexpandedParameterPackContext UPPC); - /// \brief If the given name contains an unexpanded parameter pack, + /// If the given name contains an unexpanded parameter pack, /// diagnose the error. /// /// \param NameInfo The name (with source location information) that @@ -6597,7 +6670,7 @@ public: bool DiagnoseUnexpandedParameterPack(const DeclarationNameInfo &NameInfo, UnexpandedParameterPackContext UPPC); - /// \brief If the given template name contains an unexpanded parameter pack, + /// If the given template name contains an unexpanded parameter pack, /// diagnose the error. /// /// \param Loc The location of the template name. @@ -6610,7 +6683,7 @@ public: TemplateName Template, UnexpandedParameterPackContext UPPC); - /// \brief If the given template argument contains an unexpanded parameter + /// If the given template argument contains an unexpanded parameter /// pack, diagnose the error. /// /// \param Arg The template argument that is being checked for unexpanded @@ -6620,7 +6693,7 @@ public: bool DiagnoseUnexpandedParameterPack(TemplateArgumentLoc Arg, UnexpandedParameterPackContext UPPC); - /// \brief Collect the set of unexpanded parameter packs within the given + /// Collect the set of unexpanded parameter packs within the given /// template argument. /// /// \param Arg The template argument that will be traversed to find @@ -6628,7 +6701,7 @@ public: void collectUnexpandedParameterPacks(TemplateArgument Arg, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); - /// \brief Collect the set of unexpanded parameter packs within the given + /// Collect the set of unexpanded parameter packs within the given /// template argument. /// /// \param Arg The template argument that will be traversed to find @@ -6636,7 +6709,7 @@ public: void collectUnexpandedParameterPacks(TemplateArgumentLoc Arg, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); - /// \brief Collect the set of unexpanded parameter packs within the given + /// Collect the set of unexpanded parameter packs within the given /// type. /// /// \param T The type that will be traversed to find @@ -6644,7 +6717,7 @@ public: void collectUnexpandedParameterPacks(QualType T, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); - /// \brief Collect the set of unexpanded parameter packs within the given + /// Collect the set of unexpanded parameter packs within the given /// type. /// /// \param TL The type that will be traversed to find @@ -6652,7 +6725,7 @@ public: void collectUnexpandedParameterPacks(TypeLoc TL, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); - /// \brief Collect the set of unexpanded parameter packs within the given + /// Collect the set of unexpanded parameter packs within the given /// nested-name-specifier. /// /// \param NNS The nested-name-specifier that will be traversed to find @@ -6660,7 +6733,7 @@ public: void collectUnexpandedParameterPacks(NestedNameSpecifierLoc NNS, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); - /// \brief Collect the set of unexpanded parameter packs within the given + /// Collect the set of unexpanded parameter packs within the given /// name. /// /// \param NameInfo The name that will be traversed to find @@ -6668,7 +6741,7 @@ public: void collectUnexpandedParameterPacks(const DeclarationNameInfo &NameInfo, SmallVectorImpl<UnexpandedParameterPack> &Unexpanded); - /// \brief Invoked when parsing a template argument followed by an + /// Invoked when parsing a template argument followed by an /// ellipsis, which creates a pack expansion. /// /// \param Arg The template argument preceding the ellipsis, which @@ -6678,7 +6751,7 @@ public: ParsedTemplateArgument ActOnPackExpansion(const ParsedTemplateArgument &Arg, SourceLocation EllipsisLoc); - /// \brief Invoked when parsing a type followed by an ellipsis, which + /// Invoked when parsing a type followed by an ellipsis, which /// creates a pack expansion. /// /// \param Type The type preceding the ellipsis, which will become @@ -6687,20 +6760,20 @@ public: /// \param EllipsisLoc The location of the ellipsis. TypeResult ActOnPackExpansion(ParsedType Type, SourceLocation EllipsisLoc); - /// \brief Construct a pack expansion type from the pattern of the pack + /// Construct a pack expansion type from the pattern of the pack /// expansion. TypeSourceInfo *CheckPackExpansion(TypeSourceInfo *Pattern, SourceLocation EllipsisLoc, Optional<unsigned> NumExpansions); - /// \brief Construct a pack expansion type from the pattern of the pack + /// Construct a pack expansion type from the pattern of the pack /// expansion. QualType CheckPackExpansion(QualType Pattern, SourceRange PatternRange, SourceLocation EllipsisLoc, Optional<unsigned> NumExpansions); - /// \brief Invoked when parsing an expression followed by an ellipsis, which + /// Invoked when parsing an expression followed by an ellipsis, which /// creates a pack expansion. /// /// \param Pattern The expression preceding the ellipsis, which will become @@ -6709,7 +6782,7 @@ public: /// \param EllipsisLoc The location of the ellipsis. ExprResult ActOnPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc); - /// \brief Invoked when parsing an expression followed by an ellipsis, which + /// Invoked when parsing an expression followed by an ellipsis, which /// creates a pack expansion. /// /// \param Pattern The expression preceding the ellipsis, which will become @@ -6719,7 +6792,7 @@ public: ExprResult CheckPackExpansion(Expr *Pattern, SourceLocation EllipsisLoc, Optional<unsigned> NumExpansions); - /// \brief Determine whether we could expand a pack expansion with the + /// Determine whether we could expand a pack expansion with the /// given set of parameter packs into separate arguments by repeatedly /// transforming the pattern. /// @@ -6761,7 +6834,7 @@ public: bool &RetainExpansion, Optional<unsigned> &NumExpansions); - /// \brief Determine the number of arguments in the given pack expansion + /// Determine the number of arguments in the given pack expansion /// type. /// /// This routine assumes that the number of arguments in the expansion is @@ -6771,7 +6844,7 @@ public: Optional<unsigned> getNumArgumentsInExpansion(QualType T, const MultiLevelTemplateArgumentList &TemplateArgs); - /// \brief Determine whether the given declarator contains any unexpanded + /// Determine whether the given declarator contains any unexpanded /// parameter packs. /// /// This routine is used by the parser to disambiguate function declarators @@ -6788,7 +6861,7 @@ public: /// false otherwise. bool containsUnexpandedParameterPacks(Declarator &D); - /// \brief Returns the pattern of the pack expansion for a template argument. + /// Returns the pattern of the pack expansion for a template argument. /// /// \param OrigLoc The template argument to expand. /// @@ -6820,7 +6893,7 @@ public: QualType adjustCCAndNoReturn(QualType ArgFunctionType, QualType FunctionType, bool AdjustExceptionSpec = false); - /// \brief Describes the result of template argument deduction. + /// Describes the result of template argument deduction. /// /// The TemplateDeductionResult enumeration describes the result of /// template argument deduction, as returned from @@ -6830,51 +6903,54 @@ public: /// list (if successful) or the specific template parameters or /// deduced arguments that were involved in the failure. enum TemplateDeductionResult { - /// \brief Template argument deduction was successful. + /// Template argument deduction was successful. TDK_Success = 0, - /// \brief The declaration was invalid; do nothing. + /// The declaration was invalid; do nothing. TDK_Invalid, - /// \brief Template argument deduction exceeded the maximum template + /// Template argument deduction exceeded the maximum template /// instantiation depth (which has already been diagnosed). TDK_InstantiationDepth, - /// \brief Template argument deduction did not deduce a value + /// Template argument deduction did not deduce a value /// for every template parameter. TDK_Incomplete, - /// \brief Template argument deduction produced inconsistent + /// Template argument deduction did not deduce a value for every + /// expansion of an expanded template parameter pack. + TDK_IncompletePack, + /// Template argument deduction produced inconsistent /// deduced values for the given template parameter. TDK_Inconsistent, - /// \brief Template argument deduction failed due to inconsistent + /// Template argument deduction failed due to inconsistent /// cv-qualifiers on a template parameter type that would /// otherwise be deduced, e.g., we tried to deduce T in "const T" /// but were given a non-const "X". TDK_Underqualified, - /// \brief Substitution of the deduced template argument values + /// Substitution of the deduced template argument values /// resulted in an error. TDK_SubstitutionFailure, - /// \brief After substituting deduced template arguments, a dependent + /// After substituting deduced template arguments, a dependent /// parameter type did not match the corresponding argument. TDK_DeducedMismatch, - /// \brief After substituting deduced template arguments, an element of + /// After substituting deduced template arguments, an element of /// a dependent parameter type did not match the corresponding element /// of the corresponding argument (when deducing from an initializer list). TDK_DeducedMismatchNested, - /// \brief A non-depnedent component of the parameter did not match the + /// A non-depnedent component of the parameter did not match the /// corresponding component of the argument. TDK_NonDeducedMismatch, - /// \brief When performing template argument deduction for a function + /// When performing template argument deduction for a function /// template, there were too many call arguments. TDK_TooManyArguments, - /// \brief When performing template argument deduction for a function + /// When performing template argument deduction for a function /// template, there were too few call arguments. TDK_TooFewArguments, - /// \brief The explicitly-specified template arguments were not valid + /// The explicitly-specified template arguments were not valid /// template arguments for the given template. TDK_InvalidExplicitArguments, - /// \brief Checking non-dependent argument conversions failed. + /// Checking non-dependent argument conversions failed. TDK_NonDependentConversionFailure, - /// \brief Deduction failed; that's all we know. + /// Deduction failed; that's all we know. TDK_MiscellaneousDeductionFailure, - /// \brief CUDA Target attributes do not match. + /// CUDA Target attributes do not match. TDK_CUDATargetMismatch }; @@ -6947,16 +7023,16 @@ public: sema::TemplateDeductionInfo &Info, bool IsAddressOfFunction = false); - /// \brief Substitute Replacement for \p auto in \p TypeWithAuto + /// Substitute Replacement for \p auto in \p TypeWithAuto QualType SubstAutoType(QualType TypeWithAuto, QualType Replacement); - /// \brief Substitute Replacement for auto in TypeWithAuto + /// Substitute Replacement for auto in TypeWithAuto TypeSourceInfo* SubstAutoTypeSourceInfo(TypeSourceInfo *TypeWithAuto, QualType Replacement); - /// \brief Completely replace the \c auto in \p TypeWithAuto by + /// Completely replace the \c auto in \p TypeWithAuto by /// \p Replacement. This does not retain any \c auto type sugar. QualType ReplaceAutoType(QualType TypeWithAuto, QualType Replacement); - /// \brief Result type of DeduceAutoType. + /// Result type of DeduceAutoType. enum DeduceAutoResult { DAR_Succeeded, DAR_Failed, @@ -6973,7 +7049,7 @@ public: bool DeduceReturnType(FunctionDecl *FD, SourceLocation Loc, bool Diagnose = true); - /// \brief Declare implicit deduction guides for a class template if we've + /// Declare implicit deduction guides for a class template if we've /// not already done so. void DeclareImplicitDeductionGuides(TemplateDecl *Template, SourceLocation Loc); @@ -7054,7 +7130,7 @@ public: /// alone is not sufficient to identify the context). This covers template /// instantiation and various forms of implicitly-generated functions. struct CodeSynthesisContext { - /// \brief The kind of template instantiation we are performing + /// The kind of template instantiation we are performing enum SynthesisKind { /// We are instantiating a template declaration. The entity is /// the declaration we're instantiating (e.g., a CXXRecordDecl). @@ -7102,33 +7178,39 @@ public: /// We are defining a synthesized function (such as a defaulted special /// member). DefiningSynthesizedFunction, + + /// Added for Template instantiation observation. + /// Memoization means we are _not_ instantiating a template because + /// it is already instantiated (but we entered a context where we + /// would have had to if it was not already instantiated). + Memoization } Kind; - /// \brief Was the enclosing context a non-instantiation SFINAE context? + /// Was the enclosing context a non-instantiation SFINAE context? bool SavedInNonInstantiationSFINAEContext; - /// \brief The point of instantiation or synthesis within the source code. + /// The point of instantiation or synthesis within the source code. SourceLocation PointOfInstantiation; - /// \brief The entity that is being synthesized. + /// The entity that is being synthesized. Decl *Entity; - /// \brief The template (or partial specialization) in which we are + /// The template (or partial specialization) in which we are /// performing the instantiation, for substitutions of prior template /// arguments. NamedDecl *Template; - /// \brief The list of template arguments we are substituting, if they + /// The list of template arguments we are substituting, if they /// are not part of the entity. const TemplateArgument *TemplateArgs; // FIXME: Wrap this union around more members, or perhaps store the // kind-specific members in the RAII object owning the context. union { - /// \brief The number of template arguments in TemplateArgs. + /// The number of template arguments in TemplateArgs. unsigned NumTemplateArgs; - /// \brief The special member being declared or defined. + /// The special member being declared or defined. CXXSpecialMember SpecialMember; }; @@ -7137,11 +7219,11 @@ public: return {TemplateArgs, NumTemplateArgs}; } - /// \brief The template deduction info object associated with the + /// The template deduction info object associated with the /// substitution or checking of explicit or deduced template arguments. sema::TemplateDeductionInfo *DeductionInfo; - /// \brief The source range that covers the construct that cause + /// The source range that covers the construct that cause /// the instantiation, e.g., the template-id that causes a class /// template instantiation. SourceRange InstantiationRange; @@ -7150,12 +7232,12 @@ public: : Kind(TemplateInstantiation), Entity(nullptr), Template(nullptr), TemplateArgs(nullptr), NumTemplateArgs(0), DeductionInfo(nullptr) {} - /// \brief Determines whether this template is an actual instantiation + /// Determines whether this template is an actual instantiation /// that should be counted toward the maximum instantiation depth. bool isInstantiationRecord() const; }; - /// \brief List of active code synthesis contexts. + /// List of active code synthesis contexts. /// /// This vector is treated as a stack. As synthesis of one entity requires /// synthesis of another, additional contexts are pushed onto the stack. @@ -7168,32 +7250,32 @@ public: /// by some template instantiation. llvm::DenseSet<QualType> InstantiatedNonDependentTypes; - /// \brief Extra modules inspected when performing a lookup during a template + /// Extra modules inspected when performing a lookup during a template /// instantiation. Computed lazily. SmallVector<Module*, 16> CodeSynthesisContextLookupModules; - /// \brief Cache of additional modules that should be used for name lookup + /// Cache of additional modules that should be used for name lookup /// within the current template instantiation. Computed lazily; use /// getLookupModules() to get a complete set. llvm::DenseSet<Module*> LookupModulesCache; - /// \brief Get the set of additional modules that should be checked during + /// Get the set of additional modules that should be checked during /// name lookup. A module and its imports become visible when instanting a /// template defined within it. llvm::DenseSet<Module*> &getLookupModules(); - /// \brief Map from the most recent declaration of a namespace to the most + /// Map from the most recent declaration of a namespace to the most /// recent visible declaration of that namespace. llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache; - /// \brief Whether we are in a SFINAE context that is not associated with + /// Whether we are in a SFINAE context that is not associated with /// template instantiation. /// /// This is used when setting up a SFINAE trap (\c see SFINAETrap) outside /// of a template instantiation or template argument deduction. bool InNonInstantiationSFINAEContext; - /// \brief The number of \p CodeSynthesisContexts that are not template + /// The number of \p CodeSynthesisContexts that are not template /// instantiations and, therefore, should not be counted as part of the /// instantiation depth. /// @@ -7202,7 +7284,7 @@ public: // FIXME: Should we have a similar limit for other forms of synthesis? unsigned NonInstantiationEntries; - /// \brief The depth of the context stack at the point when the most recent + /// The depth of the context stack at the point when the most recent /// error or warning was produced. /// /// This value is used to suppress printing of redundant context stacks @@ -7210,7 +7292,15 @@ public: // FIXME: Does this belong in Sema? It's tough to implement it anywhere else. unsigned LastEmittedCodeSynthesisContextDepth = 0; - /// \brief The current index into pack expansion arguments that will be + /// The template instantiation callbacks to trace or track + /// instantiations (objects can be chained). + /// + /// This callbacks is used to print, trace or track template + /// instantiations as they are being constructed. + std::vector<std::unique_ptr<TemplateInstantiationCallback>> + TemplateInstCallbacks; + + /// The current index into pack expansion arguments that will be /// used for substitution of parameter packs. /// /// The pack expansion index will be -1 to indicate that parameter packs @@ -7218,7 +7308,7 @@ public: /// which argument within the parameter pack will be used for substitution. int ArgumentPackSubstitutionIndex; - /// \brief RAII object used to change the argument pack substitution index + /// RAII object used to change the argument pack substitution index /// within a \c Sema object. /// /// See \c ArgumentPackSubstitutionIndex for more information. @@ -7239,7 +7329,7 @@ public: friend class ArgumentPackSubstitutionRAII; - /// \brief For each declaration that involved template argument deduction, the + /// For each declaration that involved template argument deduction, the /// set of diagnostics that were suppressed during that template argument /// deduction. /// @@ -7248,7 +7338,7 @@ public: SuppressedDiagnosticsMap; SuppressedDiagnosticsMap SuppressedDiagnostics; - /// \brief A stack object to be created when performing template + /// A stack object to be created when performing template /// instantiation. /// /// Construction of an object of type \c InstantiatingTemplate @@ -7260,7 +7350,7 @@ public: /// Destruction of this object will pop the named instantiation off /// the stack. struct InstantiatingTemplate { - /// \brief Note that we are instantiating a class template, + /// Note that we are instantiating a class template, /// function template, variable template, alias template, /// or a member thereof. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, @@ -7268,20 +7358,20 @@ public: SourceRange InstantiationRange = SourceRange()); struct ExceptionSpecification {}; - /// \brief Note that we are instantiating an exception specification + /// Note that we are instantiating an exception specification /// of a function template. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionDecl *Entity, ExceptionSpecification, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are instantiating a default argument in a + /// Note that we are instantiating a default argument in a /// template-id. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateParameter Param, TemplateDecl *Template, ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are substituting either explicitly-specified or + /// Note that we are substituting either explicitly-specified or /// deduced template arguments during function template argument deduction. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, FunctionTemplateDecl *FunctionTemplate, @@ -7290,7 +7380,7 @@ public: sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are instantiating as part of template + /// Note that we are instantiating as part of template /// argument deduction for a class template declaration. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, @@ -7298,7 +7388,7 @@ public: sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are instantiating as part of template + /// Note that we are instantiating as part of template /// argument deduction for a class template partial /// specialization. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, @@ -7307,7 +7397,7 @@ public: sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are instantiating as part of template + /// Note that we are instantiating as part of template /// argument deduction for a variable template partial /// specialization. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, @@ -7316,14 +7406,14 @@ public: sema::TemplateDeductionInfo &DeductionInfo, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are instantiating a default argument for a function + /// Note that we are instantiating a default argument for a function /// parameter. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, ParmVarDecl *Param, ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange = SourceRange()); - /// \brief Note that we are substituting prior template arguments into a + /// Note that we are substituting prior template arguments into a /// non-type parameter. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, @@ -7331,7 +7421,7 @@ public: ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange); - /// \brief Note that we are substituting prior template arguments into a + /// Note that we are substituting prior template arguments into a /// template template parameter. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, NamedDecl *Template, @@ -7339,7 +7429,7 @@ public: ArrayRef<TemplateArgument> TemplateArgs, SourceRange InstantiationRange); - /// \brief Note that we are checking the default template argument + /// Note that we are checking the default template argument /// against the template parameter for a given template-id. InstantiatingTemplate(Sema &SemaRef, SourceLocation PointOfInstantiation, TemplateDecl *Template, @@ -7348,16 +7438,16 @@ public: SourceRange InstantiationRange); - /// \brief Note that we have finished instantiating this template. + /// Note that we have finished instantiating this template. void Clear(); ~InstantiatingTemplate() { Clear(); } - /// \brief Determines whether we have exceeded the maximum + /// Determines whether we have exceeded the maximum /// recursive template instantiations. bool isInvalid() const { return Invalid; } - /// \brief Determine whether we are already instantiating this + /// Determine whether we are already instantiating this /// specialization in some surrounding active instantiation. bool isAlreadyInstantiating() const { return AlreadyInstantiating; } @@ -7402,7 +7492,7 @@ public: void PrintPragmaAttributeInstantiationPoint(); - /// \brief Determines whether we are currently in a context where + /// Determines whether we are currently in a context where /// template argument substitution failures are not considered /// errors. /// @@ -7412,7 +7502,7 @@ public: /// diagnostics that will be suppressed. Optional<sema::TemplateDeductionInfo *> isSFINAEContext() const; - /// \brief Determines whether we are currently in a context that + /// Determines whether we are currently in a context that /// is not evaluated as per C++ [expr] p5. bool isUnevaluatedContext() const { assert(!ExprEvalContexts.empty() && @@ -7420,7 +7510,7 @@ public: return ExprEvalContexts.back().isUnevaluated(); } - /// \brief RAII class used to determine whether SFINAE has + /// RAII class used to determine whether SFINAE has /// trapped any errors that occur during template argument /// deduction. class SFINAETrap { @@ -7453,13 +7543,13 @@ public: PrevLastDiagnosticIgnored); } - /// \brief Determine whether any SFINAE errors have been trapped. + /// Determine whether any SFINAE errors have been trapped. bool hasErrorOccurred() const { return SemaRef.NumSFINAEErrors > PrevSFINAEErrors; } }; - /// \brief RAII class used to indicate that we are performing provisional + /// RAII class used to indicate that we are performing provisional /// semantic analysis to determine the validity of a construct, so /// typo-correction and diagnostics in the immediate context (not within /// implicitly-instantiated templates) should be suppressed. @@ -7479,30 +7569,30 @@ public: } }; - /// \brief The current instantiation scope used to store local + /// The current instantiation scope used to store local /// variables. LocalInstantiationScope *CurrentInstantiationScope; - /// \brief Tracks whether we are in a context where typo correction is + /// Tracks whether we are in a context where typo correction is /// disabled. bool DisableTypoCorrection; - /// \brief The number of typos corrected by CorrectTypo. + /// The number of typos corrected by CorrectTypo. unsigned TyposCorrected; typedef llvm::SmallSet<SourceLocation, 2> SrcLocSet; typedef llvm::DenseMap<IdentifierInfo *, SrcLocSet> IdentifierSourceLocations; - /// \brief A cache containing identifiers for which typo correction failed and + /// A cache containing identifiers for which typo correction failed and /// their locations, so that repeated attempts to correct an identifier in a /// given location are ignored if typo correction already failed for it. IdentifierSourceLocations TypoCorrectionFailures; - /// \brief Worker object for performing CFG-based warnings. + /// Worker object for performing CFG-based warnings. sema::AnalysisBasedWarnings AnalysisWarnings; threadSafety::BeforeSet *ThreadSafetyDeclCache; - /// \brief An entity for which implicit template instantiation is required. + /// An entity for which implicit template instantiation is required. /// /// The source location associated with the declaration is the first place in /// the source code where the declaration was "used". It is not necessarily @@ -7512,10 +7602,14 @@ public: /// because users will need to know what code triggered the instantiation. typedef std::pair<ValueDecl *, SourceLocation> PendingImplicitInstantiation; - /// \brief The queue of implicit template instantiations that are required + /// The queue of implicit template instantiations that are required /// but have not yet been performed. std::deque<PendingImplicitInstantiation> PendingInstantiations; + /// Queue of implicit template instantiations that cannot be performed + /// eagerly. + SmallVector<PendingImplicitInstantiation, 1> LateParsedInstantiations; + class GlobalEagerInstantiationScope { public: GlobalEagerInstantiationScope(Sema &S, bool Enabled) @@ -7554,7 +7648,7 @@ public: bool Enabled; }; - /// \brief The queue of implicit template instantiations that are required + /// The queue of implicit template instantiations that are required /// and must be performed within the current local scope. /// /// This queue is only used for member functions of local classes in @@ -7653,7 +7747,7 @@ public: ExprResult SubstExpr(Expr *E, const MultiLevelTemplateArgumentList &TemplateArgs); - /// \brief Substitute the given template arguments into a list of + /// Substitute the given template arguments into a list of /// expressions, expanding pack expansions if required. /// /// \param Exprs The list of expressions to substitute into. @@ -7673,6 +7767,10 @@ public: StmtResult SubstStmt(Stmt *S, const MultiLevelTemplateArgumentList &TemplateArgs); + TemplateParameterList * + SubstTemplateParams(TemplateParameterList *Params, DeclContext *Owner, + const MultiLevelTemplateArgumentList &TemplateArgs); + Decl *SubstDecl(Decl *D, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs); @@ -7760,6 +7858,9 @@ public: void InstantiateExceptionSpec(SourceLocation PointOfInstantiation, FunctionDecl *Function); + FunctionDecl *InstantiateFunctionDeclaration(FunctionTemplateDecl *FTD, + const TemplateArgumentList *Args, + SourceLocation Loc); void InstantiateFunctionDefinition(SourceLocation PointOfInstantiation, FunctionDecl *Function, bool Recursive = false, @@ -7827,20 +7928,14 @@ public: SourceLocation rAngleLoc); void popObjCTypeParamList(Scope *S, ObjCTypeParamList *typeParamList); - Decl *ActOnStartClassInterface(Scope *S, - SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *SuperName, - SourceLocation SuperLoc, - ArrayRef<ParsedType> SuperTypeArgs, - SourceRange SuperTypeArgsRange, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); + Decl *ActOnStartClassInterface( + Scope *S, SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *SuperName, SourceLocation SuperLoc, + ArrayRef<ParsedType> SuperTypeArgs, SourceRange SuperTypeArgsRange, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); void ActOnSuperClassOfClassInterface(Scope *S, SourceLocation AtInterfaceLoc, @@ -7868,24 +7963,18 @@ public: const ObjCList<ObjCProtocolDecl> &PList); Decl *ActOnStartProtocolInterface( - SourceLocation AtProtoInterfaceLoc, - IdentifierInfo *ProtocolName, SourceLocation ProtocolLoc, - Decl * const *ProtoRefNames, unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); - - Decl *ActOnStartCategoryInterface(SourceLocation AtInterfaceLoc, - IdentifierInfo *ClassName, - SourceLocation ClassLoc, - ObjCTypeParamList *typeParamList, - IdentifierInfo *CategoryName, - SourceLocation CategoryLoc, - Decl * const *ProtoRefs, - unsigned NumProtoRefs, - const SourceLocation *ProtoLocs, - SourceLocation EndProtoLoc, - AttributeList *AttrList); + SourceLocation AtProtoInterfaceLoc, IdentifierInfo *ProtocolName, + SourceLocation ProtocolLoc, Decl *const *ProtoRefNames, + unsigned NumProtoRefs, const SourceLocation *ProtoLocs, + SourceLocation EndProtoLoc, const ParsedAttributesView &AttrList); + + Decl *ActOnStartCategoryInterface( + SourceLocation AtInterfaceLoc, IdentifierInfo *ClassName, + SourceLocation ClassLoc, ObjCTypeParamList *typeParamList, + IdentifierInfo *CategoryName, SourceLocation CategoryLoc, + Decl *const *ProtoRefs, unsigned NumProtoRefs, + const SourceLocation *ProtoLocs, SourceLocation EndProtoLoc, + const ParsedAttributesView &AttrList); Decl *ActOnStartClassImplementation( SourceLocation AtClassImplLoc, @@ -7908,9 +7997,10 @@ public: ArrayRef<ObjCTypeParamList *> TypeParamLists, unsigned NumElts); - DeclGroupPtrTy ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, - ArrayRef<IdentifierLocPair> IdentList, - AttributeList *attrList); + DeclGroupPtrTy + ActOnForwardProtocolDeclaration(SourceLocation AtProtoclLoc, + ArrayRef<IdentifierLocPair> IdentList, + const ParsedAttributesView &attrList); void FindProtocolDeclaration(bool WarnOnDeclarations, bool ForObjCContainer, ArrayRef<IdentifierLocPair> ProtocolId, @@ -8045,22 +8135,21 @@ public: ObjCDeclSpec DeclSpec; /// ArgAttrs - Attribute list for this argument. - AttributeList *ArgAttrs; + ParsedAttributesView ArgAttrs; }; Decl *ActOnMethodDeclaration( - Scope *S, - SourceLocation BeginLoc, // location of the + or -. - SourceLocation EndLoc, // location of the ; or {. - tok::TokenKind MethodType, - ObjCDeclSpec &ReturnQT, ParsedType ReturnType, - ArrayRef<SourceLocation> SelectorLocs, Selector Sel, - // optional arguments. The number of types/arguments is obtained - // from the Sel.getNumArgs(). - ObjCArgInfo *ArgInfo, - DeclaratorChunk::ParamInfo *CParamInfo, unsigned CNumArgs, // c-style args - AttributeList *AttrList, tok::ObjCKeywordKind MethodImplKind, - bool isVariadic, bool MethodDefinition); + Scope *S, + SourceLocation BeginLoc, // location of the + or -. + SourceLocation EndLoc, // location of the ; or {. + tok::TokenKind MethodType, ObjCDeclSpec &ReturnQT, ParsedType ReturnType, + ArrayRef<SourceLocation> SelectorLocs, Selector Sel, + // optional arguments. The number of types/arguments is obtained + // from the Sel.getNumArgs(). + ObjCArgInfo *ArgInfo, DeclaratorChunk::ParamInfo *CParamInfo, + unsigned CNumArgs, // c-style args + const ParsedAttributesView &AttrList, tok::ObjCKeywordKind MethodImplKind, + bool isVariadic, bool MethodDefinition); ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, const ObjCObjectPointerType *OPT, @@ -8088,14 +8177,14 @@ public: ObjCMethodDecl *tryCaptureObjCSelf(SourceLocation Loc); - /// \brief Describes the kind of message expression indicated by a message + /// Describes the kind of message expression indicated by a message /// send that starts with an identifier. enum ObjCMessageKind { - /// \brief The message is sent to 'super'. + /// The message is sent to 'super'. ObjCSuperMessage, - /// \brief The message is an instance message. + /// The message is an instance message. ObjCInstanceMessage, - /// \brief The message is a class message, and the identifier is a type + /// The message is a class message, and the identifier is a type /// name. ObjCClassMessage }; @@ -8204,12 +8293,12 @@ public: bool checkInitMethod(ObjCMethodDecl *method, QualType receiverTypeIfCall); - /// \brief Check whether the given new method is a valid override of the + /// Check whether the given new method is a valid override of the /// given overridden method, and set any properties that should be inherited. void CheckObjCMethodOverride(ObjCMethodDecl *NewMethod, const ObjCMethodDecl *Overridden); - /// \brief Describes the compatibility of a result type with its method. + /// Describes the compatibility of a result type with its method. enum ResultTypeCompatibilityKind { RTC_Compatible, RTC_Incompatible, @@ -8266,7 +8355,7 @@ public: LangOptions::PragmaMSPointersToMembersKind Kind, SourceLocation PragmaLoc); - /// \brief Called on well formed \#pragma vtordisp(). + /// Called on well formed \#pragma vtordisp(). void ActOnPragmaMSVtorDisp(PragmaMsStackAction Action, SourceLocation PragmaLoc, MSVtorDispAttr::Mode Value); @@ -8285,22 +8374,22 @@ public: int SectionFlags, SourceLocation PragmaSectionLocation); - /// \brief Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg. + /// Called on well formed \#pragma bss_seg/data_seg/const_seg/code_seg. void ActOnPragmaMSSeg(SourceLocation PragmaLocation, PragmaMsStackAction Action, llvm::StringRef StackSlotLabel, StringLiteral *SegmentName, llvm::StringRef PragmaName); - /// \brief Called on well formed \#pragma section(). + /// Called on well formed \#pragma section(). void ActOnPragmaMSSection(SourceLocation PragmaLocation, int SectionFlags, StringLiteral *SegmentName); - /// \brief Called on well-formed \#pragma init_seg(). + /// Called on well-formed \#pragma init_seg(). void ActOnPragmaMSInitSeg(SourceLocation PragmaLocation, StringLiteral *SegmentName); - /// \brief Called on #pragma clang __debug dump II + /// Called on #pragma clang __debug dump II void ActOnPragmaDump(Scope *S, SourceLocation Loc, IdentifierInfo *II); /// ActOnPragmaDetectMismatch - Call on well-formed \#pragma detect_mismatch @@ -8376,35 +8465,34 @@ public: /// the appropriate attribute. void AddCFAuditedAttribute(Decl *D); - /// \brief Called on well-formed '\#pragma clang attribute push'. - void ActOnPragmaAttributePush(AttributeList &Attribute, - SourceLocation PragmaLoc, + /// Called on well-formed '\#pragma clang attribute push'. + void ActOnPragmaAttributePush(ParsedAttr &Attribute, SourceLocation PragmaLoc, attr::ParsedSubjectMatchRuleSet Rules); - /// \brief Called on well-formed '\#pragma clang attribute pop'. + /// Called on well-formed '\#pragma clang attribute pop'. void ActOnPragmaAttributePop(SourceLocation PragmaLoc); - /// \brief Adds the attributes that have been specified using the + /// Adds the attributes that have been specified using the /// '\#pragma clang attribute push' directives to the given declaration. void AddPragmaAttributes(Scope *S, Decl *D); void DiagnoseUnterminatedPragmaAttribute(); - /// \brief Called on well formed \#pragma clang optimize. + /// Called on well formed \#pragma clang optimize. void ActOnPragmaOptimize(bool On, SourceLocation PragmaLoc); - /// \brief Get the location for the currently active "\#pragma clang optimize + /// Get the location for the currently active "\#pragma clang optimize /// off". If this location is invalid, then the state of the pragma is "on". SourceLocation getOptimizeOffPragmaLocation() const { return OptimizeOffPragmaLocation; } - /// \brief Only called on function definitions; if there is a pragma in scope + /// Only called on function definitions; if there is a pragma in scope /// with the effect of a range-based optnone, consider marking the function /// with attribute optnone. void AddRangeBasedOptnone(FunctionDecl *FD); - /// \brief Adds the 'optnone' attribute to the function declaration if there + /// Adds the 'optnone' attribute to the function declaration if there /// are no conflicts; Loc represents the location causing the 'optnone' /// attribute to be added (usually because of a pragma). void AddOptnoneAttributeIfNoConflicts(FunctionDecl *FD, SourceLocation Loc); @@ -8465,8 +8553,11 @@ public: StmtResult BuildCoreturnStmt(SourceLocation KwLoc, Expr *E, bool IsImplicit = false); StmtResult BuildCoroutineBodyStmt(CoroutineBodyStmt::CtorArgs); + bool buildCoroutineParameterMoves(SourceLocation Loc); VarDecl *buildCoroutinePromise(SourceLocation Loc); void CheckCompletedCoroutineBody(FunctionDecl *FD, Stmt *&Body); + ClassTemplateDecl *lookupCoroutineTraits(SourceLocation KwLoc, + SourceLocation FuncLoc); //===--------------------------------------------------------------------===// // OpenCL extensions. @@ -8485,36 +8576,36 @@ public: CurrOpenCLExtension = Ext; } - /// \brief Set OpenCL extensions for a type which can only be used when these + /// Set OpenCL extensions for a type which can only be used when these /// OpenCL extensions are enabled. If \p Exts is empty, do nothing. /// \param Exts A space separated list of OpenCL extensions. void setOpenCLExtensionForType(QualType T, llvm::StringRef Exts); - /// \brief Set OpenCL extensions for a declaration which can only be + /// Set OpenCL extensions for a declaration which can only be /// used when these OpenCL extensions are enabled. If \p Exts is empty, do /// nothing. /// \param Exts A space separated list of OpenCL extensions. void setOpenCLExtensionForDecl(Decl *FD, llvm::StringRef Exts); - /// \brief Set current OpenCL extensions for a type which can only be used + /// Set current OpenCL extensions for a type which can only be used /// when these OpenCL extensions are enabled. If current OpenCL extension is /// empty, do nothing. void setCurrentOpenCLExtensionForType(QualType T); - /// \brief Set current OpenCL extensions for a declaration which + /// Set current OpenCL extensions for a declaration which /// can only be used when these OpenCL extensions are enabled. If current /// OpenCL extension is empty, do nothing. void setCurrentOpenCLExtensionForDecl(Decl *FD); bool isOpenCLDisabledDecl(Decl *FD); - /// \brief Check if type \p T corresponding to declaration specifier \p DS + /// Check if type \p T corresponding to declaration specifier \p DS /// is disabled due to required OpenCL extensions being disabled. If so, /// emit diagnostics. /// \return true if type is disabled. bool checkOpenCLDisabledTypeDeclSpec(const DeclSpec &DS, QualType T); - /// \brief Check if declaration \p D used by expression \p E + /// Check if declaration \p D used by expression \p E /// is disabled due to required OpenCL extensions being disabled. If so, /// emit diagnostics. /// \return true if type is disabled. @@ -8527,7 +8618,7 @@ private: void *VarDataSharingAttributesStack; /// Set to true inside '#pragma omp declare target' region. bool IsInOpenMPDeclareTargetContext = false; - /// \brief Initialization of data-sharing attributes stack. + /// Initialization of data-sharing attributes stack. void InitDataSharingAttributesStack(); void DestroyDataSharingAttributesStack(); ExprResult @@ -8562,87 +8653,86 @@ private: SourceRange SrcRange = SourceRange()); public: - /// \brief Return true if the provided declaration \a VD should be captured by + /// Return true if the provided declaration \a VD should be captured by /// reference. /// \param Level Relative level of nested OpenMP construct for that the check /// is performed. - bool IsOpenMPCapturedByRef(ValueDecl *D, unsigned Level); + bool isOpenMPCapturedByRef(const ValueDecl *D, unsigned Level) const; - /// \brief Check if the specified variable is used in one of the private + /// Check if the specified variable is used in one of the private /// clauses (private, firstprivate, lastprivate, reduction etc.) in OpenMP /// constructs. - VarDecl *IsOpenMPCapturedDecl(ValueDecl *D); + VarDecl *isOpenMPCapturedDecl(ValueDecl *D) const; ExprResult getOpenMPCapturedExpr(VarDecl *Capture, ExprValueKind VK, ExprObjectKind OK, SourceLocation Loc); - /// \brief Check if the specified variable is used in 'private' clause. + /// Check if the specified variable is used in 'private' clause. /// \param Level Relative level of nested OpenMP construct for that the check /// is performed. - bool isOpenMPPrivateDecl(ValueDecl *D, unsigned Level); + bool isOpenMPPrivateDecl(const ValueDecl *D, unsigned Level) const; /// Sets OpenMP capture kind (OMPC_private, OMPC_firstprivate, OMPC_map etc.) /// for \p FD based on DSA for the provided corresponding captured declaration /// \p D. - void setOpenMPCaptureKind(FieldDecl *FD, ValueDecl *D, unsigned Level); + void setOpenMPCaptureKind(FieldDecl *FD, const ValueDecl *D, unsigned Level); - /// \brief Check if the specified variable is captured by 'target' directive. + /// Check if the specified variable is captured by 'target' directive. /// \param Level Relative level of nested OpenMP construct for that the check /// is performed. - bool isOpenMPTargetCapturedDecl(ValueDecl *D, unsigned Level); + bool isOpenMPTargetCapturedDecl(const ValueDecl *D, unsigned Level) const; ExprResult PerformOpenMPImplicitIntegerConversion(SourceLocation OpLoc, Expr *Op); - /// \brief Called on start of new data sharing attribute block. + /// Called on start of new data sharing attribute block. void StartOpenMPDSABlock(OpenMPDirectiveKind K, const DeclarationNameInfo &DirName, Scope *CurScope, SourceLocation Loc); - /// \brief Start analysis of clauses. + /// Start analysis of clauses. void StartOpenMPClause(OpenMPClauseKind K); - /// \brief End analysis of clauses. + /// End analysis of clauses. void EndOpenMPClause(); - /// \brief Called on end of data sharing attribute block. + /// Called on end of data sharing attribute block. void EndOpenMPDSABlock(Stmt *CurDirective); - /// \brief Check if the current region is an OpenMP loop region and if it is, + /// Check if the current region is an OpenMP loop region and if it is, /// mark loop control variable, used in \p Init for loop initialization, as /// private by default. /// \param Init First part of the for loop. void ActOnOpenMPLoopInitialization(SourceLocation ForLoc, Stmt *Init); // OpenMP directives and clauses. - /// \brief Called on correct id-expression from the '#pragma omp + /// Called on correct id-expression from the '#pragma omp /// threadprivate'. ExprResult ActOnOpenMPIdExpression(Scope *CurScope, CXXScopeSpec &ScopeSpec, const DeclarationNameInfo &Id); - /// \brief Called on well-formed '#pragma omp threadprivate'. + /// Called on well-formed '#pragma omp threadprivate'. DeclGroupPtrTy ActOnOpenMPThreadprivateDirective( SourceLocation Loc, ArrayRef<Expr *> VarList); - /// \brief Builds a new OpenMPThreadPrivateDecl and checks its correctness. - OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl( - SourceLocation Loc, - ArrayRef<Expr *> VarList); - /// \brief Check if the specified type is allowed to be used in 'omp declare + /// Builds a new OpenMPThreadPrivateDecl and checks its correctness. + OMPThreadPrivateDecl *CheckOMPThreadPrivateDecl(SourceLocation Loc, + ArrayRef<Expr *> VarList); + /// Check if the specified type is allowed to be used in 'omp declare /// reduction' construct. QualType ActOnOpenMPDeclareReductionType(SourceLocation TyLoc, TypeResult ParsedType); - /// \brief Called on start of '#pragma omp declare reduction'. + /// Called on start of '#pragma omp declare reduction'. DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveStart( Scope *S, DeclContext *DC, DeclarationName Name, ArrayRef<std::pair<QualType, SourceLocation>> ReductionTypes, AccessSpecifier AS, Decl *PrevDeclInScope = nullptr); - /// \brief Initialize declare reduction construct initializer. + /// Initialize declare reduction construct initializer. void ActOnOpenMPDeclareReductionCombinerStart(Scope *S, Decl *D); - /// \brief Finish current declare reduction construct initializer. + /// Finish current declare reduction construct initializer. void ActOnOpenMPDeclareReductionCombinerEnd(Decl *D, Expr *Combiner); - /// \brief Initialize declare reduction construct initializer. + /// Initialize declare reduction construct initializer. /// \return omp_priv variable. VarDecl *ActOnOpenMPDeclareReductionInitializerStart(Scope *S, Decl *D); - /// \brief Finish current declare reduction construct initializer. + /// Finish current declare reduction construct initializer. void ActOnOpenMPDeclareReductionInitializerEnd(Decl *D, Expr *Initializer, VarDecl *OmpPrivParm); - /// \brief Called at the end of '#pragma omp declare reduction'. + /// Called at the end of '#pragma omp declare reduction'. DeclGroupPtrTy ActOnOpenMPDeclareReductionDirectiveEnd( Scope *S, DeclGroupPtrTy DeclReductions, bool IsValid); @@ -8674,9 +8764,9 @@ public: /// Return the number of captured regions created for an OpenMP directive. static int getOpenMPCaptureLevels(OpenMPDirectiveKind Kind); - /// \brief Initialization of captured region for OpenMP region. + /// Initialization of captured region for OpenMP region. void ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope); - /// \brief End of OpenMP region. + /// End of OpenMP region. /// /// \param S Statement associated with the current OpenMP region. /// \param Clauses List of clauses for the current OpenMP region. @@ -8687,230 +8777,220 @@ public: OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName, OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp parallel' after parsing + /// Called on well-formed '\#pragma omp parallel' after parsing /// of the associated statement. StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp simd' after parsing + using VarsWithInheritedDSAType = + llvm::SmallDenseMap<const ValueDecl *, const Expr *, 4>; + /// Called on well-formed '\#pragma omp simd' after parsing /// of the associated statement. - StmtResult ActOnOpenMPSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp for' after parsing + StmtResult + ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp for' after parsing /// of the associated statement. - StmtResult ActOnOpenMPForDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp for simd' after parsing + StmtResult + ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// 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<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp sections' after parsing + StmtResult + ActOnOpenMPForSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp sections' after parsing /// of the associated statement. StmtResult ActOnOpenMPSectionsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp section' after parsing of the + /// Called on well-formed '\#pragma omp section' after parsing of the /// associated statement. StmtResult ActOnOpenMPSectionDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp single' after parsing of the + /// Called on well-formed '\#pragma omp single' after parsing of the /// associated statement. StmtResult ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp master' after parsing of the + /// Called on well-formed '\#pragma omp master' after parsing of the /// associated statement. StmtResult ActOnOpenMPMasterDirective(Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp critical' after parsing of the + /// Called on well-formed '\#pragma omp critical' after parsing of the /// associated statement. StmtResult ActOnOpenMPCriticalDirective(const DeclarationNameInfo &DirName, ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp parallel for' after parsing + /// Called on well-formed '\#pragma omp parallel for' after parsing /// of the associated statement. StmtResult ActOnOpenMPParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp parallel for simd' after + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// 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<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp parallel sections' after + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp parallel sections' after /// parsing of the associated statement. StmtResult ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp task' after parsing of the + /// Called on well-formed '\#pragma omp task' after parsing of the /// associated statement. StmtResult ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp taskyield'. + /// Called on well-formed '\#pragma omp taskyield'. StmtResult ActOnOpenMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp barrier'. + /// Called on well-formed '\#pragma omp barrier'. StmtResult ActOnOpenMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp taskwait'. + /// Called on well-formed '\#pragma omp taskwait'. StmtResult ActOnOpenMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp taskgroup'. + /// Called on well-formed '\#pragma omp taskgroup'. StmtResult ActOnOpenMPTaskgroupDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp flush'. + /// Called on well-formed '\#pragma omp flush'. StmtResult ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp ordered' after parsing of the + /// Called on well-formed '\#pragma omp ordered' after parsing of the /// associated statement. StmtResult ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp atomic' after parsing of the + /// 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 + /// 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 target data' after parsing of + /// Called on well-formed '\#pragma omp target data' after parsing of /// the associated statement. StmtResult ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp target enter data' after + /// Called on well-formed '\#pragma omp target enter data' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetEnterDataDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt); - /// \brief Called on well-formed '\#pragma omp target exit data' after + /// Called on well-formed '\#pragma omp target exit data' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetExitDataDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt); - /// \brief Called on well-formed '\#pragma omp target parallel' after + /// Called on well-formed '\#pragma omp target parallel' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetParallelDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp target parallel for' after + /// Called on well-formed '\#pragma omp target parallel for' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp teams' after parsing of the + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp teams' after parsing of the /// associated statement. StmtResult ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed '\#pragma omp cancellation point'. + /// Called on well-formed '\#pragma omp cancellation point'. StmtResult ActOnOpenMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion); - /// \brief Called on well-formed '\#pragma omp cancel'. + /// Called on well-formed '\#pragma omp cancel'. StmtResult ActOnOpenMPCancelDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc, OpenMPDirectiveKind CancelRegion); - /// \brief Called on well-formed '\#pragma omp taskloop' after parsing of the + /// Called on well-formed '\#pragma omp taskloop' after parsing of the /// associated statement. - StmtResult ActOnOpenMPTaskLoopDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp taskloop simd' after parsing of + StmtResult + ActOnOpenMPTaskLoopDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp taskloop simd' after parsing of /// the associated statement. StmtResult ActOnOpenMPTaskLoopSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp distribute' after parsing + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp distribute' after parsing /// of the associated statement. - StmtResult ActOnOpenMPDistributeDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp target update'. + StmtResult + ActOnOpenMPDistributeDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target update'. StmtResult ActOnOpenMPTargetUpdateDirective(ArrayRef<OMPClause *> Clauses, SourceLocation StartLoc, SourceLocation EndLoc, Stmt *AStmt); - /// \brief Called on well-formed '\#pragma omp distribute parallel for' after + /// Called on well-formed '\#pragma omp distribute parallel for' after /// parsing of the associated statement. StmtResult ActOnOpenMPDistributeParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp distribute parallel for simd' + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp distribute parallel for simd' /// after parsing of the associated statement. StmtResult ActOnOpenMPDistributeParallelForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp distribute simd' after + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp distribute simd' after /// parsing of the associated statement. StmtResult ActOnOpenMPDistributeSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp target parallel for simd' after + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target parallel for simd' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetParallelForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); - /// \brief Called on well-formed '\#pragma omp target simd' after parsing of + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); + /// Called on well-formed '\#pragma omp target simd' after parsing of /// the associated statement. - StmtResult ActOnOpenMPTargetSimdDirective( - ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + StmtResult + ActOnOpenMPTargetSimdDirective(ArrayRef<OMPClause *> Clauses, Stmt *AStmt, + SourceLocation StartLoc, SourceLocation EndLoc, + VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp teams distribute' after parsing of /// the associated statement. StmtResult ActOnOpenMPTeamsDistributeDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp teams distribute simd' after parsing /// of the associated statement. StmtResult ActOnOpenMPTeamsDistributeSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp teams distribute parallel for simd' /// after parsing of the associated statement. StmtResult ActOnOpenMPTeamsDistributeParallelForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp teams distribute parallel for' /// after parsing of the associated statement. StmtResult ActOnOpenMPTeamsDistributeParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp target teams' after parsing of the /// associated statement. StmtResult ActOnOpenMPTargetTeamsDirective(ArrayRef<OMPClause *> Clauses, @@ -8921,36 +9001,32 @@ public: /// of the associated statement. StmtResult ActOnOpenMPTargetTeamsDistributeDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp target teams distribute parallel for' /// after parsing of the associated statement. StmtResult ActOnOpenMPTargetTeamsDistributeParallelForDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp target teams distribute parallel for /// simd' after parsing of the associated statement. StmtResult ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Called on well-formed '\#pragma omp target teams distribute simd' after /// parsing of the associated statement. StmtResult ActOnOpenMPTargetTeamsDistributeSimdDirective( ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc, - llvm::DenseMap<ValueDecl *, Expr *> &VarsWithImplicitDSA); + SourceLocation EndLoc, VarsWithInheritedDSAType &VarsWithImplicitDSA); /// Checks correctness of linear modifiers. bool CheckOpenMPLinearModifier(OpenMPLinearClauseKind LinKind, SourceLocation LinLoc); /// Checks that the specified declaration matches requirements for the linear /// decls. - bool CheckOpenMPLinearDecl(ValueDecl *D, SourceLocation ELoc, + bool CheckOpenMPLinearDecl(const ValueDecl *D, SourceLocation ELoc, OpenMPLinearClauseKind LinKind, QualType Type); - /// \brief Called on well-formed '\#pragma omp declare simd' after parsing of + /// Called on well-formed '\#pragma omp declare simd' after parsing of /// the associated method/function. DeclGroupPtrTy ActOnOpenMPDeclareSimdDirective( DeclGroupPtrTy DG, OMPDeclareSimdDeclAttr::BranchStateTy BS, @@ -8963,50 +9039,50 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'if' clause. + /// Called on well-formed 'if' clause. OMPClause *ActOnOpenMPIfClause(OpenMPDirectiveKind NameModifier, Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation NameModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'final' clause. + /// Called on well-formed 'final' clause. OMPClause *ActOnOpenMPFinalClause(Expr *Condition, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'num_threads' clause. + /// Called on well-formed 'num_threads' clause. OMPClause *ActOnOpenMPNumThreadsClause(Expr *NumThreads, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'safelen' clause. + /// Called on well-formed 'safelen' clause. OMPClause *ActOnOpenMPSafelenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'simdlen' clause. + /// Called on well-formed 'simdlen' clause. OMPClause *ActOnOpenMPSimdlenClause(Expr *Length, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'collapse' clause. + /// Called on well-formed 'collapse' clause. OMPClause *ActOnOpenMPCollapseClause(Expr *NumForLoops, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'ordered' clause. + /// Called on well-formed 'ordered' clause. OMPClause * ActOnOpenMPOrderedClause(SourceLocation StartLoc, SourceLocation EndLoc, SourceLocation LParenLoc = SourceLocation(), Expr *NumForLoops = nullptr); - /// \brief Called on well-formed 'grainsize' clause. + /// Called on well-formed 'grainsize' clause. OMPClause *ActOnOpenMPGrainsizeClause(Expr *Size, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'num_tasks' clause. + /// Called on well-formed 'num_tasks' clause. OMPClause *ActOnOpenMPNumTasksClause(Expr *NumTasks, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'hint' clause. + /// Called on well-formed 'hint' clause. OMPClause *ActOnOpenMPHintClause(Expr *Hint, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); @@ -9017,13 +9093,13 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'default' clause. + /// Called on well-formed 'default' clause. OMPClause *ActOnOpenMPDefaultClause(OpenMPDefaultClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'proc_bind' clause. + /// Called on well-formed 'proc_bind' clause. OMPClause *ActOnOpenMPProcBindClause(OpenMPProcBindClauseKind Kind, SourceLocation KindLoc, SourceLocation StartLoc, @@ -9035,7 +9111,7 @@ public: SourceLocation StartLoc, SourceLocation LParenLoc, ArrayRef<SourceLocation> ArgumentsLoc, SourceLocation DelimLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'schedule' clause. + /// Called on well-formed 'schedule' clause. OMPClause *ActOnOpenMPScheduleClause( OpenMPScheduleClauseModifier M1, OpenMPScheduleClauseModifier M2, OpenMPScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, @@ -9044,37 +9120,37 @@ public: OMPClause *ActOnOpenMPClause(OpenMPClauseKind Kind, SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'nowait' clause. + /// Called on well-formed 'nowait' clause. OMPClause *ActOnOpenMPNowaitClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'untied' clause. + /// Called on well-formed 'untied' clause. OMPClause *ActOnOpenMPUntiedClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'mergeable' clause. + /// Called on well-formed 'mergeable' clause. OMPClause *ActOnOpenMPMergeableClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'read' clause. + /// Called on well-formed 'read' clause. OMPClause *ActOnOpenMPReadClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'write' clause. + /// Called on well-formed 'write' clause. OMPClause *ActOnOpenMPWriteClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'update' clause. + /// Called on well-formed 'update' clause. OMPClause *ActOnOpenMPUpdateClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'capture' clause. + /// Called on well-formed 'capture' clause. OMPClause *ActOnOpenMPCaptureClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'seq_cst' clause. + /// Called on well-formed 'seq_cst' clause. OMPClause *ActOnOpenMPSeqCstClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'threads' clause. + /// Called on well-formed 'threads' clause. OMPClause *ActOnOpenMPThreadsClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'simd' clause. + /// Called on well-formed 'simd' clause. OMPClause *ActOnOpenMPSIMDClause(SourceLocation StartLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'nogroup' clause. + /// Called on well-formed 'nogroup' clause. OMPClause *ActOnOpenMPNogroupClause(SourceLocation StartLoc, SourceLocation EndLoc); @@ -9087,27 +9163,27 @@ public: OpenMPLinearClauseKind LinKind, OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation DepLinMapLoc); - /// \brief Called on well-formed 'private' clause. + /// Called on well-formed 'private' clause. OMPClause *ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'firstprivate' clause. + /// Called on well-formed 'firstprivate' clause. OMPClause *ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'lastprivate' clause. + /// Called on well-formed 'lastprivate' clause. OMPClause *ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'shared' clause. + /// Called on well-formed 'shared' clause. OMPClause *ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'reduction' clause. + /// Called on well-formed 'reduction' clause. OMPClause *ActOnOpenMPReductionClause( ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc, @@ -9128,80 +9204,80 @@ public: CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId, ArrayRef<Expr *> UnresolvedReductions = llvm::None); - /// \brief Called on well-formed 'linear' clause. + /// Called on well-formed 'linear' clause. OMPClause * ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, SourceLocation StartLoc, SourceLocation LParenLoc, OpenMPLinearClauseKind LinKind, SourceLocation LinLoc, SourceLocation ColonLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'aligned' clause. + /// Called on well-formed 'aligned' clause. OMPClause *ActOnOpenMPAlignedClause(ArrayRef<Expr *> VarList, Expr *Alignment, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation ColonLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'copyin' clause. + /// Called on well-formed 'copyin' clause. OMPClause *ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'copyprivate' clause. + /// Called on well-formed 'copyprivate' clause. OMPClause *ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'flush' pseudo clause. + /// Called on well-formed 'flush' pseudo clause. OMPClause *ActOnOpenMPFlushClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'depend' clause. + /// Called on well-formed 'depend' clause. OMPClause * ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'device' clause. + /// Called on well-formed 'device' clause. OMPClause *ActOnOpenMPDeviceClause(Expr *Device, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'map' clause. + /// Called on well-formed 'map' clause. OMPClause * ActOnOpenMPMapClause(OpenMPMapClauseKind MapTypeModifier, OpenMPMapClauseKind MapType, bool IsMapTypeImplicit, SourceLocation MapLoc, SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'num_teams' clause. + /// Called on well-formed 'num_teams' clause. OMPClause *ActOnOpenMPNumTeamsClause(Expr *NumTeams, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'thread_limit' clause. + /// Called on well-formed 'thread_limit' clause. OMPClause *ActOnOpenMPThreadLimitClause(Expr *ThreadLimit, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'priority' clause. + /// Called on well-formed 'priority' clause. OMPClause *ActOnOpenMPPriorityClause(Expr *Priority, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'dist_schedule' clause. + /// Called on well-formed 'dist_schedule' clause. OMPClause *ActOnOpenMPDistScheduleClause( OpenMPDistScheduleClauseKind Kind, Expr *ChunkSize, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation KindLoc, SourceLocation CommaLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'defaultmap' clause. + /// Called on well-formed 'defaultmap' clause. OMPClause *ActOnOpenMPDefaultmapClause( OpenMPDefaultmapClauseModifier M, OpenMPDefaultmapClauseKind Kind, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation MLoc, SourceLocation KindLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'to' clause. + /// Called on well-formed 'to' clause. OMPClause *ActOnOpenMPToClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief Called on well-formed 'from' clause. + /// Called on well-formed 'from' clause. OMPClause *ActOnOpenMPFromClause(ArrayRef<Expr *> VarList, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -9217,18 +9293,25 @@ public: SourceLocation LParenLoc, SourceLocation EndLoc); - /// \brief The kind of conversion being performed. + /// The kind of conversion being performed. enum CheckedConversionKind { - /// \brief An implicit conversion. + /// An implicit conversion. CCK_ImplicitConversion, - /// \brief A C-style cast. + /// A C-style cast. CCK_CStyleCast, - /// \brief A functional-style cast. + /// A functional-style cast. CCK_FunctionalCast, - /// \brief A cast other than a C-style cast. - CCK_OtherCast + /// A cast other than a C-style cast. + CCK_OtherCast, + /// A conversion for an operand of a builtin overloaded operator. + CCK_ForBuiltinOverloadedOp }; + static bool isCast(CheckedConversionKind CCK) { + return CCK == CCK_CStyleCast || CCK == CCK_FunctionalCast || + CCK == CCK_OtherCast; + } + /// ImpCastExprToType - If Expr is not of type 'Type', insert an implicit /// cast. If there is already an implicit cast, merge into the existing one. /// If isLvalue, the result of the cast is an lvalue. @@ -9462,7 +9545,7 @@ public: QualType LHSType, ExprResult &RHS, bool Diagnose = true, bool DiagnoseCFAudited = false, bool ConvertRHS = true); - // \brief If the lhs type is a transparent union, check whether we + // If the lhs type is a transparent union, check whether we // can initialize the transparent union with the given expression. AssignConvertType CheckTransparentUnionArgumentConstraints(QualType ArgType, ExprResult &RHS); @@ -9515,8 +9598,8 @@ public: ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc, bool IsCompAssign = false); QualType CheckCompareOperands( // C99 6.5.8/9 - ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, - BinaryOperatorKind Opc, bool isRelational); + ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, + BinaryOperatorKind Opc); QualType CheckBitwiseOperands( // C99 6.5.[10...12] ExprResult &LHS, ExprResult &RHS, SourceLocation Loc, BinaryOperatorKind Opc); @@ -9572,7 +9655,8 @@ public: bool AllowBothBool, bool AllowBoolConversion); QualType GetSignedVectorType(QualType V); QualType CheckVectorCompareOperands(ExprResult &LHS, ExprResult &RHS, - SourceLocation Loc, bool isRelational); + SourceLocation Loc, + BinaryOperatorKind Opc); QualType CheckVectorLogicalOperands(ExprResult &LHS, ExprResult &RHS, SourceLocation Loc); @@ -9609,11 +9693,11 @@ public: Expr *CastExpr, CastKind &CastKind, ExprValueKind &VK, CXXCastPath &Path); - /// \brief Force an expression with unknown-type to an expression of the + /// Force an expression with unknown-type to an expression of the /// given type. ExprResult forceUnknownAnyToType(Expr *E, QualType ToType); - /// \brief Type-check an expression that's being passed to an + /// Type-check an expression that's being passed to an /// __unknown_anytype parameter. ExprResult checkUnknownAnyArg(SourceLocation callLoc, Expr *result, QualType ¶mType); @@ -9625,7 +9709,7 @@ public: bool CheckVectorCast(SourceRange R, QualType VectorTy, QualType Ty, CastKind &Kind); - /// \brief Prepare `SplattedExpr` for a vector splat operation, adding + /// Prepare `SplattedExpr` for a vector splat operation, adding /// implicit casts if necessary. ExprResult prepareVectorSplat(QualType VectorTy, Expr *SplattedExpr); @@ -9644,7 +9728,7 @@ public: enum ARCConversionResult { ACR_okay, ACR_unbridged, ACR_error }; - /// \brief Checks for invalid conversions and casts between + /// Checks for invalid conversions and casts between /// retainable pointers and other pointer kinds for ARC and Weak. ARCConversionResult CheckObjCConversion(SourceRange castRange, QualType castType, Expr *&op, @@ -9687,18 +9771,18 @@ public: SourceRange RecRange, QualType &ReturnType, ExprValueKind &VK); - /// \brief Determine the result of a message send expression based on + /// Determine the result of a message send expression based on /// the type of the receiver, the method expected to receive the message, /// and the form of the message send. QualType getMessageSendResultType(QualType ReceiverType, ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage); - /// \brief If the given expression involves a message send to a method + /// If the given expression involves a message send to a method /// with a related result type, emit a note describing what happened. void EmitRelatedResultTypeNote(const Expr *E); - /// \brief Given that we had incompatible pointer types in a return + /// Given that we had incompatible pointer types in a return /// statement, check whether we're in a method with a related result /// type, and if so, emit a note describing what happened. void EmitRelatedResultTypeNoteForReturn(QualType destType); @@ -9772,7 +9856,7 @@ public: /// being used as a boolean condition, warn if it's an assignment. void DiagnoseAssignmentAsCondition(Expr *E); - /// \brief Redundant parentheses over an equality comparison can indicate + /// Redundant parentheses over an equality comparison can indicate /// that the user intended an assignment used as condition. void DiagnoseEqualityWithExtraParens(ParenExpr *ParenE); @@ -9791,7 +9875,7 @@ public: /// in the global scope. bool CheckObjCDeclScope(Decl *D); - /// \brief Abstract base class used for diagnosing integer constant + /// Abstract base class used for diagnosing integer constant /// expression violations. class VerifyICEDiagnoser { public: @@ -9987,7 +10071,7 @@ public: /// will get it wrong. Returns CFT_Host if D is null. CUDAFunctionTarget IdentifyCUDATarget(const FunctionDecl *D, bool IgnoreImplicitHDAttr = false); - CUDAFunctionTarget IdentifyCUDATarget(const AttributeList *Attr); + CUDAFunctionTarget IdentifyCUDATarget(const ParsedAttributesView &Attrs); /// Gets the CUDA target for the current context. CUDAFunctionTarget CurrentCUDATarget() { @@ -10086,6 +10170,16 @@ public: bool isEmptyCudaConstructor(SourceLocation Loc, CXXConstructorDecl *CD); bool isEmptyCudaDestructor(SourceLocation Loc, CXXDestructorDecl *CD); + // \brief Checks that initializers of \p Var satisfy CUDA restrictions. In + // case of error emits appropriate diagnostic and invalidates \p Var. + // + // \details CUDA allows only empty constructors as initializers for global + // variables (see E.2.3.1, CUDA 7.5). The same restriction also applies to all + // __shared__ variables whether they are local or not (they all are implicitly + // static in CUDA). One exception is that CUDA allows constant initializers + // for __constant__ and __device__ variables. + void checkAllowedCUDAInitializer(VarDecl *VD); + /// Check whether NewFD is a valid overload for CUDA. Emits /// diagnostics and invalidates NewFD if not. void checkCUDATargetOverload(FunctionDecl *NewFD, @@ -10095,48 +10189,48 @@ public: /// \name Code completion //@{ - /// \brief Describes the context in which code completion occurs. + /// Describes the context in which code completion occurs. enum ParserCompletionContext { - /// \brief Code completion occurs at top-level or namespace context. + /// Code completion occurs at top-level or namespace context. PCC_Namespace, - /// \brief Code completion occurs within a class, struct, or union. + /// Code completion occurs within a class, struct, or union. PCC_Class, - /// \brief Code completion occurs within an Objective-C interface, protocol, + /// Code completion occurs within an Objective-C interface, protocol, /// or category. PCC_ObjCInterface, - /// \brief Code completion occurs within an Objective-C implementation or + /// Code completion occurs within an Objective-C implementation or /// category implementation PCC_ObjCImplementation, - /// \brief Code completion occurs within the list of instance variables + /// Code completion occurs within the list of instance variables /// in an Objective-C interface, protocol, category, or implementation. PCC_ObjCInstanceVariableList, - /// \brief Code completion occurs following one or more template + /// Code completion occurs following one or more template /// headers. PCC_Template, - /// \brief Code completion occurs following one or more template + /// Code completion occurs following one or more template /// headers within a class. PCC_MemberTemplate, - /// \brief Code completion occurs within an expression. + /// Code completion occurs within an expression. PCC_Expression, - /// \brief Code completion occurs within a statement, which may + /// Code completion occurs within a statement, which may /// also be an expression or a declaration. PCC_Statement, - /// \brief Code completion occurs at the beginning of the + /// Code completion occurs at the beginning of the /// initialization statement (or expression) in a for loop. PCC_ForInit, - /// \brief Code completion occurs within the condition of an if, + /// Code completion occurs within the condition of an if, /// while, switch, or for statement. PCC_Condition, - /// \brief Code completion occurs within the body of a function on a + /// Code completion occurs within the body of a function on a /// recovery path, where we do not have a specific handle on our position /// in the grammar. PCC_RecoveryInFunction, - /// \brief Code completion occurs where only a type is permitted. + /// Code completion occurs where only a type is permitted. PCC_Type, - /// \brief Code completion occurs in a parenthesized expression, which + /// Code completion occurs in a parenthesized expression, which /// might also be a type cast. PCC_ParenthesizedExpression, - /// \brief Code completion occurs within a sequence of declaration + /// Code completion occurs within a sequence of declaration /// specifiers within a function, method, or block. PCC_LocalDeclarationSpecifiers }; @@ -10151,7 +10245,7 @@ public: struct CodeCompleteExpressionData; void CodeCompleteExpression(Scope *S, const CodeCompleteExpressionData &Data); - void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, + void CodeCompleteMemberReferenceExpr(Scope *S, Expr *Base, Expr *OtherOpBase, SourceLocation OpLoc, bool IsArrow, bool IsBaseExprStatement); void CodeCompletePostfixExpression(Scope *S, ExprResult LHS); @@ -10301,6 +10395,9 @@ private: bool CheckARMBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckAArch64BuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinCpu(unsigned BuiltinID, CallExpr *TheCall); + bool CheckHexagonBuiltinArgument(unsigned BuiltinID, CallExpr *TheCall); bool CheckMipsBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckSystemZBuiltinFunctionCall(unsigned BuiltinID, CallExpr *TheCall); bool CheckX86BuiltinRoundingOrSAE(unsigned BuiltinID, CallExpr *TheCall); @@ -10333,10 +10430,12 @@ private: ExprResult SemaBuiltinNontemporalOverloaded(ExprResult TheCallResult); ExprResult SemaAtomicOpsOverloaded(ExprResult TheCallResult, AtomicExpr::AtomicOp Op); + ExprResult SemaBuiltinOperatorNewDeleteOverloaded(ExprResult TheCallResult, + bool IsDelete); bool SemaBuiltinConstantArg(CallExpr *TheCall, int ArgNum, llvm::APSInt &Result); - bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, - int Low, int High); + bool SemaBuiltinConstantArgRange(CallExpr *TheCall, int ArgNum, int Low, + int High, bool RangeIsError = true); bool SemaBuiltinConstantArgMultiple(CallExpr *TheCall, int ArgNum, unsigned Multiple); bool SemaBuiltinARMSpecialReg(unsigned BuiltinID, CallExpr *TheCall, @@ -10396,13 +10495,16 @@ private: const AttrVec *Attrs = nullptr, const FunctionDecl *FD = nullptr); - void CheckFloatComparison(SourceLocation Loc, Expr* LHS, Expr* RHS); +public: + void CheckFloatComparison(SourceLocation Loc, Expr *LHS, Expr *RHS); + +private: void CheckImplicitConversions(Expr *E, SourceLocation CC = SourceLocation()); void CheckBoolLikeConversion(Expr *E, SourceLocation CC); void CheckForIntOverflow(Expr *E); void CheckUnsequencedOperations(Expr *E); - /// \brief Perform semantic checks on a completed expression. This will either + /// Perform semantic checks on a completed expression. This will either /// be a full-expression or a default argument expression. void CheckCompletedExpr(Expr *E, SourceLocation CheckLoc = SourceLocation(), bool IsConstexpr = false); @@ -10415,11 +10517,11 @@ private: DeclarationName FieldName, const CXXRecordDecl *RD); - /// \brief Check if the given expression contains 'break' or 'continue' + /// Check if the given expression contains 'break' or 'continue' /// statement that produces control flow different from GCC. void CheckBreakContinueBinding(Expr *E); - /// \brief Check whether receiver is mutable ObjC container which + /// Check whether receiver is mutable ObjC container which /// attempts to add itself into the container void CheckObjCCircularContainer(ObjCMessageExpr *Message); @@ -10427,7 +10529,7 @@ private: void AnalyzeDeleteExprMismatch(FieldDecl *Field, SourceLocation DeleteLoc, bool DeleteWasArrayForm); public: - /// \brief Register a magic integral constant to be used as a type tag. + /// Register a magic integral constant to be used as a type tag. void RegisterTypeTagForDatatype(const IdentifierInfo *ArgumentKind, uint64_t MagicValue, QualType Type, bool LayoutCompatible, bool MustBeNull); @@ -10453,21 +10555,21 @@ public: typedef std::pair<const IdentifierInfo *, uint64_t> TypeTagMagicValue; private: - /// \brief A map from magic value to type information. + /// A map from magic value to type information. std::unique_ptr<llvm::DenseMap<TypeTagMagicValue, TypeTagData>> TypeTagForDatatypeMagicValues; - /// \brief Peform checks on a call of a function with argument_with_type_tag + /// Peform checks on a call of a function with argument_with_type_tag /// or pointer_with_type_tag attributes. void CheckArgumentWithTypeTag(const ArgumentWithTypeTagAttr *Attr, const ArrayRef<const Expr *> ExprArgs, SourceLocation CallSiteLoc); - /// \brief Check if we are taking the address of a packed field + /// Check if we are taking the address of a packed field /// as this may be a problem if the pointer value is dereferenced. void CheckAddressOfPackedMember(Expr *rhs); - /// \brief The parser's current scope. + /// The parser's current scope. /// /// The parser maintains this state here. Scope *CurScope; @@ -10482,7 +10584,7 @@ private: IdentifierInfo *Ident_NSError = nullptr; - /// \brief The handler for the FileChanged preprocessor events. + /// The handler for the FileChanged preprocessor events. /// /// Used for diagnostics that implement custom semantic analysis for #include /// directives, like -Wpragma-pack. @@ -10505,7 +10607,7 @@ public: /// Retrieve the identifier "NSError". IdentifierInfo *getNSErrorIdent(); - /// \brief Retrieve the parser's current scope. + /// Retrieve the parser's current scope. /// /// This routine must only be used when it is certain that semantic analysis /// and the parser are in precisely the same context, which is not the case @@ -10536,7 +10638,7 @@ public: return DC; } - /// \brief To be used for checking whether the arguments being passed to + /// To be used for checking whether the arguments being passed to /// function exceeds the number of parameters expected for it. static bool TooManyArguments(size_t NumParams, size_t NumArgs, bool PartialOverloading = false) { @@ -10581,7 +10683,7 @@ private: } }; - /// \brief Helper class that collects misaligned member designations and + /// Helper class that collects misaligned member designations and /// their location info for delayed diagnostics. struct MisalignedMember { Expr *E; @@ -10598,28 +10700,28 @@ private: bool operator==(const MisalignedMember &m) { return this->E == m.E; } }; - /// \brief Small set of gathered accesses to potentially misaligned members + /// Small set of gathered accesses to potentially misaligned members /// due to the packed attribute. SmallVector<MisalignedMember, 4> MisalignedMembers; - /// \brief Adds an expression to the set of gathered misaligned members. + /// Adds an expression to the set of gathered misaligned members. void AddPotentialMisalignedMembers(Expr *E, RecordDecl *RD, ValueDecl *MD, CharUnits Alignment); public: - /// \brief Diagnoses the current set of gathered accesses. This typically + /// Diagnoses the current set of gathered accesses. This typically /// happens at full expression level. The set is cleared after emitting the /// diagnostics. void DiagnoseMisalignedMembers(); - /// \brief This function checks if the expression is in the sef of potentially + /// This function checks if the expression is in the sef of potentially /// misaligned members and it is converted to some pointer type T with lower /// or equal alignment requirements. If so it removes it. This is used when /// we do not want to diagnose such misaligned access (e.g. in conversions to /// void*). void DiscardMisalignedMemberAddress(const Type *T, Expr *E); - /// \brief This function calls Action when it determines that E designates a + /// This function calls Action when it determines that E designates a /// misaligned member due to the packed attribute. This is used to emit /// local diagnostics like in reference binding. void RefersToMemberWithReducedAlignment( @@ -10628,31 +10730,31 @@ public: Action); }; -/// \brief RAII object that enters a new expression evaluation context. +/// RAII object that enters a new expression evaluation context. class EnterExpressionEvaluationContext { Sema &Actions; bool Entered = true; public: - - EnterExpressionEvaluationContext(Sema &Actions, - Sema::ExpressionEvaluationContext NewContext, - Decl *LambdaContextDecl = nullptr, - bool IsDecltype = false, - bool ShouldEnter = true) + EnterExpressionEvaluationContext( + Sema &Actions, Sema::ExpressionEvaluationContext NewContext, + Decl *LambdaContextDecl = nullptr, + Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = + Sema::ExpressionEvaluationContextRecord::EK_Other, + bool ShouldEnter = true) : Actions(Actions), Entered(ShouldEnter) { if (Entered) Actions.PushExpressionEvaluationContext(NewContext, LambdaContextDecl, - IsDecltype); + ExprContext); } - EnterExpressionEvaluationContext(Sema &Actions, - Sema::ExpressionEvaluationContext NewContext, - Sema::ReuseLambdaContextDecl_t, - bool IsDecltype = false) - : Actions(Actions) { - Actions.PushExpressionEvaluationContext(NewContext, - Sema::ReuseLambdaContextDecl, - IsDecltype); + EnterExpressionEvaluationContext( + Sema &Actions, Sema::ExpressionEvaluationContext NewContext, + Sema::ReuseLambdaContextDecl_t, + Sema::ExpressionEvaluationContextRecord::ExpressionKind ExprContext = + Sema::ExpressionEvaluationContextRecord::EK_Other) + : Actions(Actions) { + Actions.PushExpressionEvaluationContext( + NewContext, Sema::ReuseLambdaContextDecl, ExprContext); } enum InitListTag { InitList }; @@ -10666,7 +10768,7 @@ public: if (ShouldEnter && Actions.isUnevaluatedContext() && Actions.getLangOpts().CPlusPlus11) { Actions.PushExpressionEvaluationContext( - Sema::ExpressionEvaluationContext::UnevaluatedList, nullptr, false); + Sema::ExpressionEvaluationContext::UnevaluatedList); Entered = true; } } @@ -10681,11 +10783,11 @@ DeductionFailureInfo MakeDeductionFailureInfo(ASTContext &Context, Sema::TemplateDeductionResult TDK, sema::TemplateDeductionInfo &Info); -/// \brief Contains a late templated function. +/// Contains a late templated function. /// Will be parsed at the end of the translation unit, used by Sema & Parser. struct LateParsedTemplate { CachedTokens Toks; - /// \brief The template function declaration to be late parsed. + /// The template function declaration to be late parsed. Decl *D; }; diff --git a/include/clang/Sema/SemaConsumer.h b/include/clang/Sema/SemaConsumer.h index 676646afbd595..a2caf86c36533 100644 --- a/include/clang/Sema/SemaConsumer.h +++ b/include/clang/Sema/SemaConsumer.h @@ -20,7 +20,7 @@ namespace clang { class Sema; - /// \brief An abstract interface that should be implemented by + /// An abstract interface that should be implemented by /// clients that read ASTs and then require further semantic /// analysis of the entities in those ASTs. class SemaConsumer : public ASTConsumer { @@ -30,12 +30,12 @@ namespace clang { ASTConsumer::SemaConsumer = true; } - /// \brief Initialize the semantic consumer with the Sema instance + /// Initialize the semantic consumer with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. virtual void InitializeSema(Sema &S) {} - /// \brief Inform the semantic consumer that Sema is no longer available. + /// Inform the semantic consumer that Sema is no longer available. virtual void ForgetSema() {} // isa/cast/dyn_cast support diff --git a/include/clang/Sema/SemaFixItUtils.h b/include/clang/Sema/SemaFixItUtils.h index 343ccfb3d6307..84dc58754b7be 100644 --- a/include/clang/Sema/SemaFixItUtils.h +++ b/include/clang/Sema/SemaFixItUtils.h @@ -1,4 +1,4 @@ -//===--- SemaFixItUtils.h - Sema FixIts -----------------------------------===// +//===--- SemaFixItUtils.h - Sema FixIts -------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/Sema/SemaInternal.h b/include/clang/Sema/SemaInternal.h index 4dc215ba21cb7..86ab703a5b3af 100644 --- a/include/clang/Sema/SemaInternal.h +++ b/include/clang/Sema/SemaInternal.h @@ -101,6 +101,27 @@ inline InheritableAttr *getDLLAttr(Decl *D) { return nullptr; } +/// Retrieve the depth and index of a template parameter. +inline std::pair<unsigned, unsigned> getDepthAndIndex(NamedDecl *ND) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(ND)) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(ND)) + return std::make_pair(NTTP->getDepth(), NTTP->getIndex()); + + const auto *TTP = cast<TemplateTemplateParmDecl>(ND); + return std::make_pair(TTP->getDepth(), TTP->getIndex()); +} + +/// Retrieve the depth and index of an unexpanded parameter pack. +inline std::pair<unsigned, unsigned> +getDepthAndIndex(UnexpandedParameterPack UPP) { + if (const auto *TTP = UPP.first.dyn_cast<const TemplateTypeParmType *>()) + return std::make_pair(TTP->getDepth(), TTP->getIndex()); + + return getDepthAndIndex(UPP.first.get<NamedDecl *>()); +} + class TypoCorrectionConsumer : public VisibleDeclConsumer { typedef SmallVector<TypoCorrection, 1> TypoResultList; typedef llvm::StringMap<TypoResultList> TypoResultsMap; @@ -139,13 +160,13 @@ public: return CorrectionResults.empty() && ValidatedCorrections.size() == 1; } - /// \brief Return the list of TypoCorrections for the given identifier from + /// 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 + /// 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()) @@ -155,28 +176,28 @@ public: return Normalized ? TypoCorrection::NormalizeEditDistance(BestED) : BestED; } - /// \brief Set-up method to add to the consumer the set of namespaces to use + /// 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 + /// 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(). + /// 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 + /// 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). @@ -187,27 +208,27 @@ public: return TC; } - /// \brief Reset the consumer's position in the stream of viable corrections + /// 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 + /// Return whether the end of the stream of corrections has been /// reached. bool finished() { return CorrectionResults.empty() && CurrentTCIndex >= ValidatedCorrections.size(); } - /// \brief Save the current position in the correction stream (overwriting any + /// Save the current position in the correction stream (overwriting any /// previously saved position). void saveCurrentPosition() { SavedTCIndex = CurrentTCIndex; } - /// \brief Restore the saved position in the correction stream. + /// Restore the saved position in the correction stream. void restoreSavedPosition() { CurrentTCIndex = SavedTCIndex; } @@ -241,7 +262,7 @@ private: std::map<unsigned, SpecifierInfoList> DistanceMap; - /// \brief Helper for building the list of DeclContexts between the current + /// Helper for building the list of DeclContexts between the current /// context and the top of the translation unit static DeclContextList buildContextChain(DeclContext *Start); @@ -252,11 +273,11 @@ private: NamespaceSpecifierSet(ASTContext &Context, DeclContext *CurContext, CXXScopeSpec *CurScopeSpec); - /// \brief Add the DeclContext (a namespace or record) to the set, computing + /// Add the DeclContext (a namespace or record) to the set, computing /// the corresponding NestedNameSpecifier and its distance in the process. void addNameSpecifier(DeclContext *Ctx); - /// \brief Provides flat iteration over specifiers, sorted by distance. + /// Provides flat iteration over specifiers, sorted by distance. class iterator : public llvm::iterator_facade_base<iterator, std::forward_iterator_tag, SpecifierInfo> { @@ -295,21 +316,21 @@ private: void addName(StringRef Name, NamedDecl *ND, NestedNameSpecifier *NNS = nullptr, bool isKeyword = false); - /// \brief Find any visible decls for the given typo correction candidate. + /// 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 + /// 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. + /// The name written that is a typo in the source. IdentifierInfo *Typo; - /// \brief The results found that have the smallest edit distance + /// 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 diff --git a/include/clang/Sema/SemaLambda.h b/include/clang/Sema/SemaLambda.h index df40b134f0a7d..dfdc4ebc3643d 100644 --- a/include/clang/Sema/SemaLambda.h +++ b/include/clang/Sema/SemaLambda.h @@ -8,19 +8,23 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file provides some common utility functions for processing +/// This file provides some common utility functions for processing /// Lambdas. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_SEMA_SEMALAMBDA_H #define LLVM_CLANG_SEMA_SEMALAMBDA_H + #include "clang/AST/ASTLambda.h" -#include "clang/Sema/ScopeInfo.h" + namespace clang { +namespace sema { +class FunctionScopeInfo; +} class Sema; -/// \brief Examines the FunctionScopeInfo stack to determine the nearest +/// Examines the FunctionScopeInfo stack to determine the nearest /// enclosing lambda (to the current lambda) that is 'capture-capable' for /// the variable referenced in the current lambda (i.e. \p VarToCapture). /// If successful, returns the index into Sema's FunctionScopeInfo stack diff --git a/include/clang/Sema/Template.h b/include/clang/Sema/Template.h index 644d55b93f1b1..c0dee3e82d58a 100644 --- a/include/clang/Sema/Template.h +++ b/include/clang/Sema/Template.h @@ -1,26 +1,49 @@ -//===------- SemaTemplate.h - C++ Templates ---------------------*- C++ -*-===/ +//===- SemaTemplate.h - C++ Templates ---------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===/ +//===----------------------------------------------------------------------===// // -// This file provides types used in the semantic analysis of C++ templates. +// This file provides types used in the semantic analysis of C++ templates. // -//===----------------------------------------------------------------------===/ +//===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SEMA_TEMPLATE_H #define LLVM_CLANG_SEMA_TEMPLATE_H #include "clang/AST/DeclTemplate.h" #include "clang/AST/DeclVisitor.h" +#include "clang/AST/TemplateBase.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" #include "clang/Sema/Sema.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerUnion.h" #include "llvm/ADT/SmallVector.h" #include <cassert> #include <utility> namespace clang { - /// \brief Data structure that captures multiple levels of template argument + +class ASTContext; +class BindingDecl; +class CXXMethodDecl; +class Decl; +class DeclaratorDecl; +class DeclContext; +class EnumDecl; +class FunctionDecl; +class NamedDecl; +class ParmVarDecl; +class TagDecl; +class TypedefNameDecl; +class TypeSourceInfo; +class VarDecl; + + /// Data structure that captures multiple levels of template argument /// lists for use in template instantiation. /// /// Multiple levels of template arguments occur when instantiating the @@ -40,47 +63,47 @@ namespace clang { /// list will contain a template argument list (int) at depth 0 and a /// template argument list (17) at depth 1. class MultiLevelTemplateArgumentList { - /// \brief The template argument list at a certain template depth - typedef ArrayRef<TemplateArgument> ArgList; + /// The template argument list at a certain template depth + using ArgList = ArrayRef<TemplateArgument>; - /// \brief The template argument lists, stored from the innermost template + /// The template argument lists, stored from the innermost template /// argument list (first) to the outermost template argument list (last). SmallVector<ArgList, 4> TemplateArgumentLists; - /// \brief The number of outer levels of template arguments that are not + /// The number of outer levels of template arguments that are not /// being substituted. unsigned NumRetainedOuterLevels = 0; public: - /// \brief Construct an empty set of template argument lists. - MultiLevelTemplateArgumentList() { } + /// Construct an empty set of template argument lists. + MultiLevelTemplateArgumentList() = default; - /// \brief Construct a single-level template argument list. + /// Construct a single-level template argument list. explicit MultiLevelTemplateArgumentList(const TemplateArgumentList &TemplateArgs) { addOuterTemplateArguments(&TemplateArgs); } - /// \brief Determine the number of levels in this template argument + /// Determine the number of levels in this template argument /// list. unsigned getNumLevels() const { return TemplateArgumentLists.size() + NumRetainedOuterLevels; } - /// \brief Determine the number of substituted levels in this template + /// Determine the number of substituted levels in this template /// argument list. unsigned getNumSubstitutedLevels() const { return TemplateArgumentLists.size(); } - /// \brief Retrieve the template argument at a given depth and index. + /// Retrieve the template argument at a given depth and index. const TemplateArgument &operator()(unsigned Depth, unsigned Index) const { assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); assert(Index < TemplateArgumentLists[getNumLevels() - Depth - 1].size()); return TemplateArgumentLists[getNumLevels() - Depth - 1][Index]; } - /// \brief Determine whether there is a non-NULL template argument at the + /// Determine whether there is a non-NULL template argument at the /// given depth and index. /// /// There must exist a template argument list at the given depth. @@ -96,7 +119,7 @@ namespace clang { return !(*this)(Depth, Index).isNull(); } - /// \brief Clear out a specific template argument. + /// Clear out a specific template argument. void setArgument(unsigned Depth, unsigned Index, TemplateArgument Arg) { assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels()); @@ -106,14 +129,14 @@ namespace clang { = Arg; } - /// \brief Add a new outermost level to the multi-level template argument + /// Add a new outermost level to the multi-level template argument /// list. void addOuterTemplateArguments(const TemplateArgumentList *TemplateArgs) { addOuterTemplateArguments(ArgList(TemplateArgs->data(), TemplateArgs->size())); } - /// \brief Add a new outmost level to the multi-level template argument + /// Add a new outmost level to the multi-level template argument /// list. void addOuterTemplateArguments(ArgList Args) { assert(!NumRetainedOuterLevels && @@ -121,27 +144,29 @@ namespace clang { TemplateArgumentLists.push_back(Args); } - /// \brief Add an outermost level that we are not substituting. We have no + /// Add an outermost level that we are not substituting. We have no /// arguments at this level, and do not remove it from the depth of inner /// template parameters that we instantiate. void addOuterRetainedLevel() { ++NumRetainedOuterLevels; } - /// \brief Retrieve the innermost template argument list. - const ArgList &getInnermost() const { + /// Retrieve the innermost template argument list. + const ArgList &getInnermost() const { return TemplateArgumentLists.front(); } }; - /// \brief The context in which partial ordering of function templates occurs. + /// The context in which partial ordering of function templates occurs. enum TPOC { - /// \brief Partial ordering of function templates for a function call. + /// Partial ordering of function templates for a function call. TPOC_Call, - /// \brief Partial ordering of function templates for a call to a + + /// Partial ordering of function templates for a call to a /// conversion function. TPOC_Conversion, - /// \brief Partial ordering of function templates in other contexts, e.g., + + /// Partial ordering of function templates in other contexts, e.g., /// taking the address of a function template or matching a function /// template specialization to a function template. TPOC_Other @@ -153,47 +178,48 @@ namespace clang { // making Sema.h declare things as enums). class TemplatePartialOrderingContext { TPOC Value; + public: TemplatePartialOrderingContext(TPOC Value) : Value(Value) {} + operator TPOC() const { return Value; } }; - /// \brief Captures a template argument whose value has been deduced + /// Captures a template argument whose value has been deduced /// via c++ template argument deduction. class DeducedTemplateArgument : public TemplateArgument { - /// \brief For a non-type template argument, whether the value was + /// For a non-type template argument, whether the value was /// deduced from an array bound. - bool DeducedFromArrayBound; + bool DeducedFromArrayBound = false; public: - DeducedTemplateArgument() - : TemplateArgument(), DeducedFromArrayBound(false) { } + DeducedTemplateArgument() = default; DeducedTemplateArgument(const TemplateArgument &Arg, bool DeducedFromArrayBound = false) - : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) { } + : TemplateArgument(Arg), DeducedFromArrayBound(DeducedFromArrayBound) {} - /// \brief Construct an integral non-type template argument that + /// Construct an integral non-type template argument that /// has been deduced, possibly from an array bound. DeducedTemplateArgument(ASTContext &Ctx, const llvm::APSInt &Value, QualType ValueType, bool DeducedFromArrayBound) - : TemplateArgument(Ctx, Value, ValueType), - DeducedFromArrayBound(DeducedFromArrayBound) { } + : TemplateArgument(Ctx, Value, ValueType), + DeducedFromArrayBound(DeducedFromArrayBound) {} - /// \brief For a non-type template argument, determine whether the + /// For a non-type template argument, determine whether the /// template argument was deduced from an array bound. bool wasDeducedFromArrayBound() const { return DeducedFromArrayBound; } - /// \brief Specify whether the given non-type template argument + /// Specify whether the given non-type template argument /// was deduced from an array bound. void setDeducedFromArrayBound(bool Deduced) { DeducedFromArrayBound = Deduced; } }; - /// \brief A stack-allocated class that identifies which local + /// A stack-allocated class that identifies which local /// variable declaration instantiations are present in this scope. /// /// A new instance of this class type will be created whenever we @@ -201,19 +227,19 @@ namespace clang { /// set of parameter declarations. class LocalInstantiationScope { public: - /// \brief A set of declarations. - typedef SmallVector<ParmVarDecl *, 4> DeclArgumentPack; + /// A set of declarations. + using DeclArgumentPack = SmallVector<ParmVarDecl *, 4>; private: - /// \brief Reference to the semantic analysis that is performing + /// Reference to the semantic analysis that is performing /// this template instantiation. Sema &SemaRef; - typedef llvm::SmallDenseMap< - const Decl *, llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4> - LocalDeclsMap; + using LocalDeclsMap = + llvm::SmallDenseMap<const Decl *, + llvm::PointerUnion<Decl *, DeclArgumentPack *>, 4>; - /// \brief A mapping from local declarations that occur + /// A mapping from local declarations that occur /// within a template to their instantiations. /// /// This mapping is used during instantiation to keep track of, @@ -233,55 +259,52 @@ namespace clang { /// pointer. LocalDeclsMap LocalDecls; - /// \brief The set of argument packs we've allocated. + /// The set of argument packs we've allocated. SmallVector<DeclArgumentPack *, 1> ArgumentPacks; - /// \brief The outer scope, which contains local variable + /// The outer scope, which contains local variable /// definitions from some other instantiation (that may not be /// relevant to this particular scope). LocalInstantiationScope *Outer; - /// \brief Whether we have already exited this scope. - bool Exited; + /// Whether we have already exited this scope. + bool Exited = false; - /// \brief Whether to combine this scope with the outer scope, such that + /// Whether to combine this scope with the outer scope, such that /// lookup will search our outer scope. bool CombineWithOuterScope; - /// \brief If non-NULL, the template parameter pack that has been + /// If non-NULL, the template parameter pack that has been /// partially substituted per C++0x [temp.arg.explicit]p9. - NamedDecl *PartiallySubstitutedPack; + NamedDecl *PartiallySubstitutedPack = nullptr; - /// \brief If \c PartiallySubstitutedPack is non-null, the set of + /// If \c PartiallySubstitutedPack is non-null, the set of /// explicitly-specified template arguments in that pack. const TemplateArgument *ArgsInPartiallySubstitutedPack; - /// \brief If \c PartiallySubstitutedPack, the number of + /// If \c PartiallySubstitutedPack, the number of /// explicitly-specified template arguments in /// ArgsInPartiallySubstitutedPack. unsigned NumArgsInPartiallySubstitutedPack; - // This class is non-copyable - LocalInstantiationScope( - const LocalInstantiationScope &) = delete; - void operator=(const LocalInstantiationScope &) = delete; - public: LocalInstantiationScope(Sema &SemaRef, bool CombineWithOuterScope = false) - : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), - Exited(false), CombineWithOuterScope(CombineWithOuterScope), - PartiallySubstitutedPack(nullptr) - { + : SemaRef(SemaRef), Outer(SemaRef.CurrentInstantiationScope), + CombineWithOuterScope(CombineWithOuterScope) { SemaRef.CurrentInstantiationScope = this; } + LocalInstantiationScope(const LocalInstantiationScope &) = delete; + LocalInstantiationScope & + operator=(const LocalInstantiationScope &) = delete; + ~LocalInstantiationScope() { Exit(); } const Sema &getSema() const { return SemaRef; } - /// \brief Exit this local instantiation scope early. + /// Exit this local instantiation scope early. void Exit() { if (Exited) return; @@ -293,7 +316,7 @@ namespace clang { Exited = true; } - /// \brief Clone this scope, and all outer scopes, down to the given + /// Clone this scope, and all outer scopes, down to the given /// outermost scope. LocalInstantiationScope *cloneScopes(LocalInstantiationScope *Outermost) { if (this == Outermost) return this; @@ -333,7 +356,7 @@ namespace clang { return newScope; } - /// \brief deletes the given scope, and all otuer scopes, down to the + /// deletes the given scope, and all otuer scopes, down to the /// given outermost scope. static void deleteScopes(LocalInstantiationScope *Scope, LocalInstantiationScope *Outermost) { @@ -344,7 +367,7 @@ namespace clang { } } - /// \brief Find the instantiation of the declaration D within the current + /// Find the instantiation of the declaration D within the current /// instantiation scope. /// /// \param D The declaration whose instantiation we are searching for. @@ -359,7 +382,7 @@ namespace clang { void InstantiatedLocalPackArg(const Decl *D, ParmVarDecl *Inst); void MakeInstantiatedLocalArgPack(const Decl *D); - /// \brief Note that the given parameter pack has been partially substituted + /// Note that the given parameter pack has been partially substituted /// via explicit specification of template arguments /// (C++0x [temp.arg.explicit]p9). /// @@ -375,7 +398,7 @@ namespace clang { const TemplateArgument *ExplicitArgs, unsigned NumExplicitArgs); - /// \brief Reset the partially-substituted pack when it is no longer of + /// Reset the partially-substituted pack when it is no longer of /// interest. void ResetPartiallySubstitutedPack() { assert(PartiallySubstitutedPack && "No partially-substituted pack"); @@ -384,7 +407,7 @@ namespace clang { NumArgsInPartiallySubstitutedPack = 0; } - /// \brief Retrieve the partially-substitued template parameter pack. + /// Retrieve the partially-substitued template parameter pack. /// /// If there is no partially-substituted parameter pack, returns NULL. NamedDecl * @@ -399,17 +422,17 @@ namespace clang { Sema::ArgumentPackSubstitutionIndexRAII SubstIndex; DeclContext *Owner; const MultiLevelTemplateArgumentList &TemplateArgs; - Sema::LateInstantiatedAttrVec* LateAttrs; - LocalInstantiationScope *StartingScope; + Sema::LateInstantiatedAttrVec* LateAttrs = nullptr; + LocalInstantiationScope *StartingScope = nullptr; - /// \brief A list of out-of-line class template partial + /// A list of out-of-line class template partial /// specializations that will need to be instantiated after the /// enclosing class's instantiation is complete. SmallVector<std::pair<ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>, 4> OutOfLinePartialSpecs; - /// \brief A list of out-of-line variable template partial + /// A list of out-of-line variable template partial /// specializations that will need to be instantiated after the /// enclosing variable's instantiation is complete. /// FIXME: Verify that this is needed. @@ -420,10 +443,9 @@ namespace clang { public: TemplateDeclInstantiator(Sema &SemaRef, DeclContext *Owner, const MultiLevelTemplateArgumentList &TemplateArgs) - : SemaRef(SemaRef), - SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), - Owner(Owner), TemplateArgs(TemplateArgs), LateAttrs(nullptr), - StartingScope(nullptr) {} + : SemaRef(SemaRef), + SubstIndex(SemaRef, SemaRef.ArgumentPackSubstitutionIndex), + Owner(Owner), TemplateArgs(TemplateArgs) {} // Define all the decl visitors using DeclNodes.inc #define DECL(DERIVED, BASE) \ @@ -476,17 +498,13 @@ namespace clang { LocalInstantiationScope *getStartingScope() const { return StartingScope; } - typedef - SmallVectorImpl<std::pair<ClassTemplateDecl *, - ClassTemplatePartialSpecializationDecl *> > - ::iterator - delayed_partial_spec_iterator; + using delayed_partial_spec_iterator = SmallVectorImpl<std::pair< + ClassTemplateDecl *, ClassTemplatePartialSpecializationDecl *>>::iterator; - typedef SmallVectorImpl<std::pair< - VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> >::iterator - delayed_var_partial_spec_iterator; + using delayed_var_partial_spec_iterator = SmallVectorImpl<std::pair< + VarTemplateDecl *, VarTemplatePartialSpecializationDecl *>>::iterator; - /// \brief Return an iterator to the beginning of the set of + /// Return an iterator to the beginning of the set of /// "delayed" partial specializations, which must be passed to /// InstantiateClassTemplatePartialSpecialization once the class /// definition has been completed. @@ -498,7 +516,7 @@ namespace clang { return OutOfLineVarPartialSpecs.begin(); } - /// \brief Return an iterator to the end of the set of + /// Return an iterator to the end of the set of /// "delayed" partial specializations, which must be passed to /// InstantiateClassTemplatePartialSpecialization once the class /// definition has been completed. @@ -545,6 +563,7 @@ namespace clang { Decl *instantiateUnresolvedUsingDecl(T *D, bool InstantiatingPackElement = false); }; -} + +} // namespace clang #endif // LLVM_CLANG_SEMA_TEMPLATE_H diff --git a/include/clang/Sema/TemplateDeduction.h b/include/clang/Sema/TemplateDeduction.h index cd9ed6abfaf9d..93395b4945d5b 100644 --- a/include/clang/Sema/TemplateDeduction.h +++ b/include/clang/Sema/TemplateDeduction.h @@ -1,80 +1,95 @@ -//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===/ +//===- TemplateDeduction.h - C++ template argument deduction ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. -//===----------------------------------------------------------------------===/ // -// This file provides types used with Sema's template argument deduction +//===----------------------------------------------------------------------===// +// +// This file provides types used with Sema's template argument deduction // routines. // -//===----------------------------------------------------------------------===/ +//===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H #define LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H +#include "clang/AST/DeclAccessPair.h" #include "clang/AST/DeclTemplate.h" +#include "clang/AST/TemplateBase.h" #include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallVector.h" +#include <cassert> +#include <cstddef> +#include <utility> namespace clang { +class Decl; struct DeducedPack; -class TemplateArgumentList; class Sema; namespace sema { -/// \brief Provides information about an attempted template argument +/// Provides information about an attempted template argument /// deduction, whose success or failure was described by a /// TemplateDeductionResult value. class TemplateDeductionInfo { - /// \brief The deduced template argument list. - /// - TemplateArgumentList *Deduced; + /// The deduced template argument list. + TemplateArgumentList *Deduced = nullptr; - /// \brief The source location at which template argument + /// The source location at which template argument /// deduction is occurring. SourceLocation Loc; - /// \brief Have we suppressed an error during deduction? - bool HasSFINAEDiagnostic; + /// Have we suppressed an error during deduction? + bool HasSFINAEDiagnostic = false; - /// \brief The template parameter depth for which we're performing deduction. + /// The template parameter depth for which we're performing deduction. unsigned DeducedDepth; - /// \brief Warnings (and follow-on notes) that were suppressed due to + /// The number of parameters with explicitly-specified template arguments, + /// up to and including the partially-specified pack (if any). + unsigned ExplicitArgs = 0; + + /// Warnings (and follow-on notes) that were suppressed due to /// SFINAE while performing template argument deduction. SmallVector<PartialDiagnosticAt, 4> SuppressedDiagnostics; - TemplateDeductionInfo(const TemplateDeductionInfo &) = delete; - void operator=(const TemplateDeductionInfo &) = delete; - public: TemplateDeductionInfo(SourceLocation Loc, unsigned DeducedDepth = 0) - : Deduced(nullptr), Loc(Loc), HasSFINAEDiagnostic(false), - DeducedDepth(DeducedDepth), CallArgIndex(0) {} + : Loc(Loc), DeducedDepth(DeducedDepth) {} + TemplateDeductionInfo(const TemplateDeductionInfo &) = delete; + TemplateDeductionInfo &operator=(const TemplateDeductionInfo &) = delete; - /// \brief Returns the location at which template argument is + /// Returns the location at which template argument is /// occurring. SourceLocation getLocation() const { return Loc; } - /// \brief The depth of template parameters for which deduction is being + /// The depth of template parameters for which deduction is being /// performed. unsigned getDeducedDepth() const { return DeducedDepth; } - /// \brief Take ownership of the deduced template argument list. + /// Get the number of explicitly-specified arguments. + unsigned getNumExplicitArgs() const { + return ExplicitArgs; + } + + /// Take ownership of the deduced template argument list. TemplateArgumentList *take() { TemplateArgumentList *Result = Deduced; Deduced = nullptr; return Result; } - /// \brief Take ownership of the SFINAE diagnostic. + /// Take ownership of the SFINAE diagnostic. void takeSFINAEDiagnostic(PartialDiagnosticAt &PD) { assert(HasSFINAEDiagnostic); PD.first = SuppressedDiagnostics.front().first; @@ -82,7 +97,7 @@ public: clearSFINAEDiagnostic(); } - /// \brief Discard any SFINAE diagnostics. + /// Discard any SFINAE diagnostics. void clearSFINAEDiagnostic() { SuppressedDiagnostics.clear(); HasSFINAEDiagnostic = false; @@ -94,18 +109,25 @@ public: return SuppressedDiagnostics.front(); } - /// \brief Provide a new template argument list that contains the + /// Provide an initial template argument list that contains the + /// explicitly-specified arguments. + void setExplicitArgs(TemplateArgumentList *NewDeduced) { + Deduced = NewDeduced; + ExplicitArgs = Deduced->size(); + } + + /// Provide a new template argument list that contains the /// results of template argument deduction. void reset(TemplateArgumentList *NewDeduced) { Deduced = NewDeduced; } - /// \brief Is a SFINAE diagnostic available? + /// Is a SFINAE diagnostic available? bool hasSFINAEDiagnostic() const { return HasSFINAEDiagnostic; } - /// \brief Set the diagnostic which caused the SFINAE failure. + /// Set the diagnostic which caused the SFINAE failure. void addSFINAEDiagnostic(SourceLocation Loc, PartialDiagnostic PD) { // Only collect the first diagnostic. if (HasSFINAEDiagnostic) @@ -115,7 +137,7 @@ public: HasSFINAEDiagnostic = true; } - /// \brief Add a new diagnostic to the set of diagnostics + /// Add a new diagnostic to the set of diagnostics void addSuppressedDiagnostic(SourceLocation Loc, PartialDiagnostic PD) { if (HasSFINAEDiagnostic) @@ -123,19 +145,18 @@ public: SuppressedDiagnostics.emplace_back(Loc, std::move(PD)); } - /// \brief Iterator over the set of suppressed diagnostics. - typedef SmallVectorImpl<PartialDiagnosticAt>::const_iterator - diag_iterator; + /// Iterator over the set of suppressed diagnostics. + using diag_iterator = SmallVectorImpl<PartialDiagnosticAt>::const_iterator; - /// \brief Returns an iterator at the beginning of the sequence of suppressed + /// Returns an iterator at the beginning of the sequence of suppressed /// diagnostics. diag_iterator diag_begin() const { return SuppressedDiagnostics.begin(); } - /// \brief Returns an iterator at the end of the sequence of suppressed + /// Returns an iterator at the end of the sequence of suppressed /// diagnostics. diag_iterator diag_end() const { return SuppressedDiagnostics.end(); } - /// \brief The template parameter to which a template argument + /// The template parameter to which a template argument /// deduction failure refers. /// /// Depending on the result of template argument deduction, this @@ -144,16 +165,22 @@ public: /// TDK_Incomplete: this is the first template parameter whose /// corresponding template argument was not deduced. /// + /// TDK_IncompletePack: this is the expanded parameter pack for + /// which we deduced too few arguments. + /// /// TDK_Inconsistent: this is the template parameter for which /// two different template argument values were deduced. TemplateParameter Param; - /// \brief The first template argument to which the template + /// The first template argument to which the template /// argument deduction failure refers. /// /// Depending on the result of the template argument deduction, /// this template argument may have different meanings: /// + /// TDK_IncompletePack: this is the number of arguments we deduced + /// for the pack. + /// /// TDK_Inconsistent: this argument is the first value deduced /// for the corresponding template parameter. /// @@ -167,7 +194,7 @@ public: /// of the deduction, directly provided in the source code. TemplateArgument FirstArg; - /// \brief The second template argument to which the template + /// The second template argument to which the template /// argument deduction failure refers. /// /// TDK_Inconsistent: this argument is the second value deduced @@ -181,20 +208,20 @@ public: /// FIXME: Finish documenting this. TemplateArgument SecondArg; - /// \brief The index of the function argument that caused a deduction + /// The index of the function argument that caused a deduction /// failure. /// /// TDK_DeducedMismatch: this is the index of the argument that had a /// different argument type from its substituted parameter type. - unsigned CallArgIndex; + unsigned CallArgIndex = 0; - /// \brief Information on packs that we're currently expanding. + /// Information on packs that we're currently expanding. /// /// FIXME: This should be kept internal to SemaTemplateDeduction. SmallVector<DeducedPack *, 8> PendingDeducedPacks; }; -} // end namespace sema +} // namespace sema /// A structure used to record information about a failed /// template argument deduction, for diagnosis. @@ -202,41 +229,41 @@ struct DeductionFailureInfo { /// A Sema::TemplateDeductionResult. unsigned Result : 8; - /// \brief Indicates whether a diagnostic is stored in Diagnostic. + /// Indicates whether a diagnostic is stored in Diagnostic. unsigned HasDiagnostic : 1; - /// \brief Opaque pointer containing additional data about + /// Opaque pointer containing additional data about /// this deduction failure. void *Data; - /// \brief A diagnostic indicating why deduction failed. + /// A diagnostic indicating why deduction failed. alignas(PartialDiagnosticAt) char Diagnostic[sizeof(PartialDiagnosticAt)]; - /// \brief Retrieve the diagnostic which caused this deduction failure, + /// Retrieve the diagnostic which caused this deduction failure, /// if any. PartialDiagnosticAt *getSFINAEDiagnostic(); - /// \brief Retrieve the template parameter this deduction failure + /// Retrieve the template parameter this deduction failure /// refers to, if any. TemplateParameter getTemplateParameter(); - /// \brief Retrieve the template argument list associated with this + /// Retrieve the template argument list associated with this /// deduction failure, if any. TemplateArgumentList *getTemplateArgumentList(); - /// \brief Return the first template argument this deduction failure + /// Return the first template argument this deduction failure /// refers to, if any. const TemplateArgument *getFirstArg(); - /// \brief Return the second template argument this deduction failure + /// Return the second template argument this deduction failure /// refers to, if any. const TemplateArgument *getSecondArg(); - /// \brief Return the index of the call argument that this deduction + /// Return the index of the call argument that this deduction /// failure refers to, if any. llvm::Optional<unsigned> getCallArgIndex(); - /// \brief Free any memory associated with this deduction failure. + /// Free any memory associated with this deduction failure. void Destroy(); }; @@ -248,7 +275,7 @@ struct DeductionFailureInfo { /// TODO: In the future, we may need to unify/generalize this with /// OverloadCandidate. struct TemplateSpecCandidate { - /// \brief The declaration that was looked up, together with its access. + /// The declaration that was looked up, together with its access. /// Might be a UsingShadowDecl, but usually a FunctionTemplateDecl. DeclAccessPair FoundDecl; @@ -276,36 +303,37 @@ struct TemplateSpecCandidate { class TemplateSpecCandidateSet { SmallVector<TemplateSpecCandidate, 16> Candidates; SourceLocation Loc; + // Stores whether we're taking the address of these candidates. This helps us // produce better error messages when dealing with the pass_object_size // attribute on parameters. bool ForTakingAddress; - TemplateSpecCandidateSet( - const TemplateSpecCandidateSet &) = delete; - void operator=(const TemplateSpecCandidateSet &) = delete; - void destroyCandidates(); public: TemplateSpecCandidateSet(SourceLocation Loc, bool ForTakingAddress = false) : Loc(Loc), ForTakingAddress(ForTakingAddress) {} + TemplateSpecCandidateSet(const TemplateSpecCandidateSet &) = delete; + TemplateSpecCandidateSet & + operator=(const TemplateSpecCandidateSet &) = delete; ~TemplateSpecCandidateSet() { destroyCandidates(); } SourceLocation getLocation() const { return Loc; } - /// \brief Clear out all of the candidates. + /// Clear out all of the candidates. /// TODO: This may be unnecessary. void clear(); - typedef SmallVector<TemplateSpecCandidate, 16>::iterator iterator; + using iterator = SmallVector<TemplateSpecCandidate, 16>::iterator; + iterator begin() { return Candidates.begin(); } iterator end() { return Candidates.end(); } size_t size() const { return Candidates.size(); } bool empty() const { return Candidates.empty(); } - /// \brief Add a new candidate with NumConversions conversion sequence slots + /// Add a new candidate with NumConversions conversion sequence slots /// to the overload set. TemplateSpecCandidate &addCandidate() { Candidates.emplace_back(); @@ -319,6 +347,6 @@ public: } }; -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_TEMPLATEDEDUCTION_H diff --git a/include/clang/Sema/TemplateInstCallback.h b/include/clang/Sema/TemplateInstCallback.h new file mode 100644 index 0000000000000..dc729d52243c5 --- /dev/null +++ b/include/clang/Sema/TemplateInstCallback.h @@ -0,0 +1,83 @@ +//===- TemplateInstCallback.h - Template Instantiation Callback - 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 TemplateInstantiationCallback class, which is the +// base class for callbacks that will be notified at template instantiations. +// +//===---------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TEMPLATE_INST_CALLBACK_H +#define LLVM_CLANG_TEMPLATE_INST_CALLBACK_H + +#include "clang/Sema/Sema.h" + +namespace clang { + +/// This is a base class for callbacks that will be notified at every +/// template instantiation. +class TemplateInstantiationCallback { +public: + virtual ~TemplateInstantiationCallback() = default; + + /// Called before doing AST-parsing. + virtual void initialize(const Sema &TheSema) = 0; + + /// Called after AST-parsing is completed. + virtual void finalize(const Sema &TheSema) = 0; + + /// Called when instantiation of a template just began. + virtual void atTemplateBegin(const Sema &TheSema, + const Sema::CodeSynthesisContext &Inst) = 0; + + /// Called when instantiation of a template is just about to end. + virtual void atTemplateEnd(const Sema &TheSema, + const Sema::CodeSynthesisContext &Inst) = 0; +}; + +template <class TemplateInstantiationCallbackPtrs> +void initialize(TemplateInstantiationCallbackPtrs &Callbacks, + const Sema &TheSema) { + for (auto &C : Callbacks) { + if (C) + C->initialize(TheSema); + } +} + +template <class TemplateInstantiationCallbackPtrs> +void finalize(TemplateInstantiationCallbackPtrs &Callbacks, + const Sema &TheSema) { + for (auto &C : Callbacks) { + if (C) + C->finalize(TheSema); + } +} + +template <class TemplateInstantiationCallbackPtrs> +void atTemplateBegin(TemplateInstantiationCallbackPtrs &Callbacks, + const Sema &TheSema, + const Sema::CodeSynthesisContext &Inst) { + for (auto &C : Callbacks) { + if (C) + C->atTemplateBegin(TheSema, Inst); + } +} + +template <class TemplateInstantiationCallbackPtrs> +void atTemplateEnd(TemplateInstantiationCallbackPtrs &Callbacks, + const Sema &TheSema, + const Sema::CodeSynthesisContext &Inst) { + for (auto &C : Callbacks) { + if (C) + C->atTemplateEnd(TheSema, Inst); + } +} + +} // namespace clang + +#endif diff --git a/include/clang/Sema/TypoCorrection.h b/include/clang/Sema/TypoCorrection.h index 5bebe52325c63..d8fe827998454 100644 --- a/include/clang/Sema/TypoCorrection.h +++ b/include/clang/Sema/TypoCorrection.h @@ -1,4 +1,4 @@ -//===--- TypoCorrection.h - Class for typo correction results ---*- C++ -*-===// +//===- TypoCorrection.h - Class for typo correction results -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,18 +15,36 @@ #ifndef LLVM_CLANG_SEMA_TYPOCORRECTION_H #define LLVM_CLANG_SEMA_TYPOCORRECTION_H -#include "clang/AST/DeclCXX.h" +#include "clang/AST/Decl.h" +#include "clang/AST/DeclarationName.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/PartialDiagnostic.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Sema/DeclSpec.h" -#include "clang/Sema/Ownership.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include <cstddef> +#include <limits> +#include <string> +#include <utility> +#include <vector> namespace clang { -/// @brief Simple class containing the result of Sema::CorrectTypo +class DeclContext; +class IdentifierInfo; +class LangOptions; +class MemberExpr; +class NestedNameSpecifier; +class Sema; + +/// Simple class containing the result of Sema::CorrectTypo class TypoCorrection { public: // "Distance" for unusable corrections - static const unsigned InvalidDistance = ~0U; + static const unsigned InvalidDistance = std::numeric_limits<unsigned>::max(); + // The largest distance still considered valid (larger edit distances are // mapped to InvalidDistance by getEditDistance). static const unsigned MaximumDistance = 10000U; @@ -43,9 +61,7 @@ public: NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0, unsigned QualifierDistance = 0) : CorrectionName(Name), CorrectionNameSpec(NNS), - CharDistance(CharDistance), QualifierDistance(QualifierDistance), - CallbackDistance(0), ForceSpecifierReplacement(false), - RequiresImport(false) { + CharDistance(CharDistance), QualifierDistance(QualifierDistance) { if (NameDecl) CorrectionDecls.push_back(NameDecl); } @@ -53,8 +69,7 @@ public: TypoCorrection(NamedDecl *Name, NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0) : CorrectionName(Name->getDeclName()), CorrectionNameSpec(NNS), - CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0), - ForceSpecifierReplacement(false), RequiresImport(false) { + CharDistance(CharDistance) { if (Name) CorrectionDecls.push_back(Name); } @@ -62,24 +77,22 @@ public: TypoCorrection(DeclarationName Name, NestedNameSpecifier *NNS = nullptr, unsigned CharDistance = 0) : CorrectionName(Name), CorrectionNameSpec(NNS), - CharDistance(CharDistance), QualifierDistance(0), CallbackDistance(0), - ForceSpecifierReplacement(false), RequiresImport(false) {} + CharDistance(CharDistance) {} - TypoCorrection() - : CorrectionNameSpec(nullptr), CharDistance(0), QualifierDistance(0), - CallbackDistance(0), ForceSpecifierReplacement(false), - RequiresImport(false) {} + TypoCorrection() = default; - /// \brief Gets the DeclarationName of the typo correction + /// Gets the DeclarationName of the typo correction DeclarationName getCorrection() const { return CorrectionName; } + IdentifierInfo *getCorrectionAsIdentifierInfo() const { return CorrectionName.getAsIdentifierInfo(); } - /// \brief Gets the NestedNameSpecifier needed to use the typo correction + /// Gets the NestedNameSpecifier needed to use the typo correction NestedNameSpecifier *getCorrectionSpecifier() const { return CorrectionNameSpec; } + void setCorrectionSpecifier(NestedNameSpecifier *NNS) { CorrectionNameSpec = NNS; ForceSpecifierReplacement = (NNS != nullptr); @@ -110,7 +123,7 @@ public: return (ED + CharDistanceWeight / 2) / CharDistanceWeight; } - /// \brief Gets the "edit distance" of the typo correction from the typo. + /// Gets the "edit distance" of the typo correction from the typo. /// If Normalized is true, scale the distance down by the CharDistanceWeight /// to return the edit distance in terms of single-character edits. unsigned getEditDistance(bool Normalized = true) const { @@ -129,13 +142,13 @@ public: return Normalized ? NormalizeEditDistance(ED) : ED; } - /// \brief Get the correction declaration found by name lookup (before we + /// Get the correction declaration found by name lookup (before we /// looked through using shadow declarations and the like). NamedDecl *getFoundDecl() const { return hasCorrectionDecl() ? *(CorrectionDecls.begin()) : nullptr; } - /// \brief Gets the pointer to the declaration of the typo correction + /// Gets the pointer to the declaration of the typo correction NamedDecl *getCorrectionDecl() const { auto *D = getFoundDecl(); return D ? D->getUnderlyingDecl() : nullptr; @@ -145,36 +158,37 @@ public: return dyn_cast_or_null<DeclClass>(getCorrectionDecl()); } - /// \brief Clears the list of NamedDecls. + /// Clears the list of NamedDecls. void ClearCorrectionDecls() { CorrectionDecls.clear(); } - /// \brief Clears the list of NamedDecls before adding the new one. + /// Clears the list of NamedDecls before adding the new one. void setCorrectionDecl(NamedDecl *CDecl) { CorrectionDecls.clear(); addCorrectionDecl(CDecl); } - /// \brief Clears the list of NamedDecls and adds the given set. + /// Clears the list of NamedDecls and adds the given set. void setCorrectionDecls(ArrayRef<NamedDecl*> Decls) { CorrectionDecls.clear(); CorrectionDecls.insert(CorrectionDecls.begin(), Decls.begin(), Decls.end()); } - /// \brief Add the given NamedDecl to the list of NamedDecls that are the + /// Add the given NamedDecl to the list of NamedDecls that are the /// declarations associated with the DeclarationName of this TypoCorrection void addCorrectionDecl(NamedDecl *CDecl); std::string getAsString(const LangOptions &LO) const; + std::string getQuoted(const LangOptions &LO) const { return "'" + getAsString(LO) + "'"; } - /// \brief Returns whether this TypoCorrection has a non-empty DeclarationName + /// Returns whether this TypoCorrection has a non-empty DeclarationName explicit operator bool() const { return bool(CorrectionName); } - /// \brief Mark this TypoCorrection as being a keyword. + /// Mark this TypoCorrection as being a keyword. /// Since addCorrectionDeclsand setCorrectionDecl don't allow NULL to be /// added to the list of the correction's NamedDecl pointers, NULL is added /// as the only element in the list to mark this TypoCorrection as a keyword. @@ -214,18 +228,23 @@ public: return CorrectionRange; } - typedef SmallVectorImpl<NamedDecl *>::iterator decl_iterator; + using decl_iterator = SmallVectorImpl<NamedDecl *>::iterator; + decl_iterator begin() { return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); } + decl_iterator end() { return CorrectionDecls.end(); } - typedef SmallVectorImpl<NamedDecl *>::const_iterator const_decl_iterator; + + using const_decl_iterator = SmallVectorImpl<NamedDecl *>::const_iterator; + const_decl_iterator begin() const { return isKeyword() ? CorrectionDecls.end() : CorrectionDecls.begin(); } + const_decl_iterator end() const { return CorrectionDecls.end(); } - /// \brief Returns whether this typo correction is correcting to a + /// Returns whether this typo correction is correcting to a /// declaration that was declared in a module that has not been imported. bool requiresImport() const { return RequiresImport; } void setRequiresImport(bool Req) { RequiresImport = Req; } @@ -246,19 +265,19 @@ private: // Results. DeclarationName CorrectionName; - NestedNameSpecifier *CorrectionNameSpec; + NestedNameSpecifier *CorrectionNameSpec = nullptr; SmallVector<NamedDecl *, 1> CorrectionDecls; - unsigned CharDistance; - unsigned QualifierDistance; - unsigned CallbackDistance; + unsigned CharDistance = 0; + unsigned QualifierDistance = 0; + unsigned CallbackDistance = 0; SourceRange CorrectionRange; - bool ForceSpecifierReplacement; - bool RequiresImport; + bool ForceSpecifierReplacement = false; + bool RequiresImport = false; std::vector<PartialDiagnostic> ExtraDiagnostics; }; -/// @brief Base class for callback objects used by Sema::CorrectTypo to check +/// Base class for callback objects used by Sema::CorrectTypo to check /// the validity of a potential typo correction. class CorrectionCandidateCallback { public: @@ -266,19 +285,15 @@ public: explicit CorrectionCandidateCallback(IdentifierInfo *Typo = nullptr, NestedNameSpecifier *TypoNNS = nullptr) - : WantTypeSpecifiers(true), WantExpressionKeywords(true), - WantCXXNamedCasts(true), WantFunctionLikeCasts(true), - WantRemainingKeywords(true), WantObjCSuper(false), - IsObjCIvarLookup(false), IsAddressOfOperand(false), Typo(Typo), - TypoNNS(TypoNNS) {} + : Typo(Typo), TypoNNS(TypoNNS) {} - virtual ~CorrectionCandidateCallback() {} + virtual ~CorrectionCandidateCallback() = default; - /// \brief Simple predicate used by the default RankCandidate to + /// Simple predicate used by the default RankCandidate to /// determine whether to return an edit distance of 0 or InvalidDistance. - /// This can be overrided by validators that only need to determine if a + /// This can be overridden by validators that only need to determine if a /// candidate is viable, without ranking potentially viable candidates. - /// Only ValidateCandidate or RankCandidate need to be overriden by a + /// Only ValidateCandidate or RankCandidate need to be overridden by a /// callback wishing to check the viability of correction candidates. /// The default predicate always returns true if the candidate is not a type /// name or keyword, true for types if WantTypeSpecifiers is true, and true @@ -286,7 +301,7 @@ public: /// WantCXXNamedCasts, WantRemainingKeywords, or WantObjCSuper is true. virtual bool ValidateCandidate(const TypoCorrection &candidate); - /// \brief Method used by Sema::CorrectTypo to assign an "edit distance" rank + /// Method used by Sema::CorrectTypo to assign an "edit distance" rank /// to a candidate (where a lower value represents a better candidate), or /// returning InvalidDistance if the candidate is not at all viable. For /// validation callbacks that only need to determine if a candidate is viable, @@ -304,16 +319,16 @@ public: // 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; + bool WantTypeSpecifiers = true; + bool WantExpressionKeywords = true; + bool WantCXXNamedCasts = true; + bool WantFunctionLikeCasts = true; + bool WantRemainingKeywords = true; + bool WantObjCSuper = false; // Temporary hack for the one case where a CorrectTypoContext enum is used // when looking up results. - bool IsObjCIvarLookup; - bool IsAddressOfOperand; + bool IsObjCIvarLookup = false; + bool IsAddressOfOperand = false; protected: bool MatchesTypo(const TypoCorrection &candidate) { @@ -328,7 +343,7 @@ protected: NestedNameSpecifier *TypoNNS; }; -/// @brief Simple template class for restricting typo correction candidates +/// Simple template class for restricting typo correction candidates /// to ones having a single Decl* of the given type. template <class C> class DeclFilterCCC : public CorrectionCandidateCallback { @@ -338,7 +353,7 @@ public: } }; -// @brief Callback class to limit the allowed keywords and to only accept typo +// Callback class to limit the allowed keywords and to only accept typo // corrections that are keywords or whose decls refer to functions (or template // functions) that accept the given number of arguments. class FunctionCallFilterCCC : public CorrectionCandidateCallback { @@ -349,14 +364,14 @@ public: bool ValidateCandidate(const TypoCorrection &candidate) override; - private: +private: unsigned NumArgs; bool HasExplicitTemplateArgs; DeclContext *CurContext; MemberExpr *MemberFn; }; -// @brief Callback class that effectively disabled typo correction +// Callback class that effectively disabled typo correction class NoTypoCorrectionCCC : public CorrectionCandidateCallback { public: NoTypoCorrectionCCC() { @@ -372,6 +387,6 @@ public: } }; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_SEMA_TYPOCORRECTION_H diff --git a/include/clang/Sema/Weak.h b/include/clang/Sema/Weak.h index 9c7212e0c8eed..115e97bcd2ce7 100644 --- a/include/clang/Sema/Weak.h +++ b/include/clang/Sema/Weak.h @@ -21,7 +21,7 @@ namespace clang { class IdentifierInfo; -/// \brief Captures information about a \#pragma weak directive. +/// Captures information about a \#pragma weak directive. class WeakInfo { IdentifierInfo *alias; // alias (optional) SourceLocation loc; // for diagnostics diff --git a/include/clang/Serialization/ASTBitCodes.h b/include/clang/Serialization/ASTBitCodes.h index 34a7bb330174b..76bc818557a96 100644 --- a/include/clang/Serialization/ASTBitCodes.h +++ b/include/clang/Serialization/ASTBitCodes.h @@ -31,7 +31,7 @@ namespace clang { namespace serialization { - /// \brief AST file major version number supported by this version of + /// AST file major version number supported by this version of /// Clang. /// /// Whenever the AST file format changes in a way that makes it @@ -42,9 +42,9 @@ namespace serialization { /// 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 = 6; + const unsigned VERSION_MAJOR = 7; - /// \brief AST file minor version number supported by this version of + /// AST file minor version number supported by this version of /// Clang. /// /// Whenever the AST format changes in a way that is still @@ -54,13 +54,13 @@ namespace serialization { /// should be increased. const unsigned VERSION_MINOR = 0; - /// \brief An ID number that refers to an identifier in an AST file. + /// An ID number that refers to an identifier in an AST file. /// /// The ID numbers of identifiers are consecutive (in order of discovery) /// and start at 1. 0 is reserved for NULL. using IdentifierID = uint32_t; - /// \brief An ID number that refers to a declaration in an AST file. + /// An ID number that refers to a declaration in an AST file. /// /// The ID numbers of declarations are consecutive (in order of /// discovery), with values below NUM_PREDEF_DECL_IDS being reserved. @@ -73,7 +73,7 @@ namespace serialization { using LocalDeclID = DeclID; using GlobalDeclID = DeclID; - /// \brief An ID number that refers to a type in an AST file. + /// An ID number that refers to a type in an AST file. /// /// The ID of a type is partitioned into two parts: the lower /// three bits are used to store the const/volatile/restrict @@ -85,7 +85,7 @@ namespace serialization { /// other types that have serialized representations. using TypeID = uint32_t; - /// \brief A type index; the type ID with the qualifier bits removed. + /// A type index; the type ID with the qualifier bits removed. class TypeIdx { uint32_t Idx = 0; @@ -131,58 +131,58 @@ namespace serialization { } }; - /// \brief An ID number that refers to an identifier in an AST file. + /// An ID number that refers to an identifier in an AST file. using IdentID = uint32_t; - /// \brief The number of predefined identifier IDs. + /// The number of predefined identifier IDs. const unsigned int NUM_PREDEF_IDENT_IDS = 1; - /// \brief An ID number that refers to a macro in an AST file. + /// An ID number that refers to a macro in an AST file. using MacroID = uint32_t; - /// \brief A global ID number that refers to a macro in an AST file. + /// A global ID number that refers to a macro in an AST file. using GlobalMacroID = uint32_t; - /// \brief A local to a module ID number that refers to a macro in an + /// A local to a module ID number that refers to a macro in an /// AST file. using LocalMacroID = uint32_t; - /// \brief The number of predefined macro IDs. + /// The number of predefined macro IDs. const unsigned int NUM_PREDEF_MACRO_IDS = 1; - /// \brief An ID number that refers to an ObjC selector in an AST file. + /// An ID number that refers to an ObjC selector in an AST file. using SelectorID = uint32_t; - /// \brief The number of predefined selector IDs. + /// The number of predefined selector IDs. const unsigned int NUM_PREDEF_SELECTOR_IDS = 1; - /// \brief An ID number that refers to a set of CXXBaseSpecifiers in an + /// An ID number that refers to a set of CXXBaseSpecifiers in an /// AST file. using CXXBaseSpecifiersID = uint32_t; - /// \brief An ID number that refers to a list of CXXCtorInitializers in an + /// An ID number that refers to a list of CXXCtorInitializers in an /// AST file. using CXXCtorInitializersID = uint32_t; - /// \brief An ID number that refers to an entity in the detailed + /// An ID number that refers to an entity in the detailed /// preprocessing record. using PreprocessedEntityID = uint32_t; - /// \brief An ID number that refers to a submodule in a module file. + /// An ID number that refers to a submodule in a module file. using SubmoduleID = uint32_t; - /// \brief The number of predefined submodule IDs. + /// The number of predefined submodule IDs. const unsigned int NUM_PREDEF_SUBMODULE_IDS = 1; - /// \brief Source range/offset of a preprocessed entity. + /// Source range/offset of a preprocessed entity. struct PPEntityOffset { - /// \brief Raw source location of beginning of range. + /// Raw source location of beginning of range. unsigned Begin; - /// \brief Raw source location of end of range. + /// Raw source location of end of range. unsigned End; - /// \brief Offset in the AST file. + /// Offset in the AST file. uint32_t BitOffset; PPEntityOffset(SourceRange R, uint32_t BitOffset) @@ -198,12 +198,31 @@ namespace serialization { } }; - /// \brief Source range/offset of a preprocessed entity. + /// Source range of a skipped preprocessor region + struct PPSkippedRange { + /// Raw source location of beginning of range. + unsigned Begin; + /// Raw source location of end of range. + unsigned End; + + PPSkippedRange(SourceRange R) + : Begin(R.getBegin().getRawEncoding()), + End(R.getEnd().getRawEncoding()) { } + + SourceLocation getBegin() const { + return SourceLocation::getFromRawEncoding(Begin); + } + SourceLocation getEnd() const { + return SourceLocation::getFromRawEncoding(End); + } + }; + + /// Source range/offset of a preprocessed entity. struct DeclOffset { - /// \brief Raw source location. + /// Raw source location. unsigned Loc = 0; - /// \brief Offset in the AST file. + /// Offset in the AST file. uint32_t BitOffset = 0; DeclOffset() = default; @@ -219,56 +238,56 @@ namespace serialization { } }; - /// \brief The number of predefined preprocessed entity IDs. + /// The number of predefined preprocessed entity IDs. const unsigned int NUM_PREDEF_PP_ENTITY_IDS = 1; - /// \brief Describes the various kinds of blocks that occur within + /// Describes the various kinds of blocks that occur within /// an AST file. enum BlockIDs { - /// \brief The AST block, which acts as a container around the + /// The AST block, which acts as a container around the /// full AST block. AST_BLOCK_ID = llvm::bitc::FIRST_APPLICATION_BLOCKID, - /// \brief The block containing information about the source + /// The block containing information about the source /// manager. SOURCE_MANAGER_BLOCK_ID, - /// \brief The block containing information about the + /// The block containing information about the /// preprocessor. PREPROCESSOR_BLOCK_ID, - /// \brief The block containing the definitions of all of the + /// The block containing the definitions of all of the /// types and decls used within the AST file. DECLTYPES_BLOCK_ID, - /// \brief The block containing the detailed preprocessing record. + /// The block containing the detailed preprocessing record. PREPROCESSOR_DETAIL_BLOCK_ID, - /// \brief The block containing the submodule structure. + /// The block containing the submodule structure. SUBMODULE_BLOCK_ID, - /// \brief The block containing comments. + /// The block containing comments. COMMENTS_BLOCK_ID, - /// \brief The control block, which contains all of the + /// The control block, which contains all of the /// information that needs to be validated prior to committing /// to loading the AST file. CONTROL_BLOCK_ID, - /// \brief The block of input files, which were used as inputs + /// The block of input files, which were used as inputs /// to create this AST file. /// /// This block is part of the control block. INPUT_FILES_BLOCK_ID, - /// \brief The block of configuration options, used to check that + /// The block of configuration options, used to check that /// a module is being used in a configuration compatible with the /// configuration in which it was built. /// /// This block is part of the control block. OPTIONS_BLOCK_ID, - /// \brief A block containing a module file extension. + /// A block containing a module file extension. EXTENSION_BLOCK_ID, /// A block with unhashed content. @@ -278,47 +297,47 @@ namespace serialization { UNHASHED_CONTROL_BLOCK_ID, }; - /// \brief Record types that occur within the control block. + /// Record types that occur within the control block. enum ControlRecordTypes { - /// \brief AST file metadata, including the AST file version number + /// AST file metadata, including the AST file version number /// and information about the compiler used to build this AST file. METADATA = 1, - /// \brief Record code for the list of other AST files imported by + /// Record code for the list of other AST files imported by /// this AST file. IMPORTS, - /// \brief Record code for the original file that was used to + /// Record code for the original file that was used to /// generate the AST file, including both its file ID and its /// name. ORIGINAL_FILE, - /// \brief The directory that the PCH was originally created in. + /// The directory that the PCH was originally created in. ORIGINAL_PCH_DIR, - /// \brief Record code for file ID of the file or buffer that was used to + /// Record code for file ID of the file or buffer that was used to /// generate the AST file. ORIGINAL_FILE_ID, - /// \brief Offsets into the input-files block where input files + /// Offsets into the input-files block where input files /// reside. INPUT_FILE_OFFSETS, - /// \brief Record code for the module name. + /// Record code for the module name. MODULE_NAME, - /// \brief Record code for the module map file that was used to build this + /// Record code for the module map file that was used to build this /// AST file. MODULE_MAP_FILE, - /// \brief Record code for the module build directory. + /// Record code for the module build directory. MODULE_DIRECTORY, }; - /// \brief Record types that occur within the options block inside + /// Record types that occur within the options block inside /// the control block. enum OptionsRecordTypes { - /// \brief Record code for the language options table. + /// Record code for the language options table. /// /// The record with this code contains the contents of the /// LangOptions structure. We serialize the entire contents of @@ -326,16 +345,16 @@ namespace serialization { /// actually important to check. LANGUAGE_OPTIONS = 1, - /// \brief Record code for the target options table. + /// Record code for the target options table. TARGET_OPTIONS, - /// \brief Record code for the filesystem options table. + /// Record code for the filesystem options table. FILE_SYSTEM_OPTIONS, - /// \brief Record code for the headers search options table. + /// Record code for the headers search options table. HEADER_SEARCH_OPTIONS, - /// \brief Record code for the preprocessor options table. + /// Record code for the preprocessor options table. PREPROCESSOR_OPTIONS, }; @@ -351,7 +370,7 @@ namespace serialization { DIAG_PRAGMA_MAPPINGS, }; - /// \brief Record code for extension blocks. + /// Record code for extension blocks. enum ExtensionBlockRecordTypes { /// Metadata describing this particular extension. EXTENSION_METADATA = 1, @@ -360,16 +379,16 @@ namespace serialization { FIRST_EXTENSION_RECORD_ID = 4 }; - /// \brief Record types that occur within the input-files block + /// Record types that occur within the input-files block /// inside the control block. enum InputFileRecordTypes { - /// \brief An input file. + /// An input file. INPUT_FILE = 1 }; - /// \brief Record types that occur within the AST block itself. + /// Record types that occur within the AST block itself. enum ASTRecordTypes { - /// \brief Record code for the offsets of each type. + /// Record code for the offsets of each type. /// /// The TYPE_OFFSET constant describes the record that occurs /// within the AST block. The record itself is an array of offsets that @@ -383,7 +402,7 @@ namespace serialization { /// corresponding record within the DECLTYPES_BLOCK_ID block. TYPE_OFFSET = 1, - /// \brief Record code for the offsets of each decl. + /// Record code for the offsets of each decl. /// /// The DECL_OFFSET constant describes the record that occurs /// within the block identified by DECL_OFFSETS_BLOCK_ID within @@ -395,7 +414,7 @@ namespace serialization { /// reserved for the translation unit declaration. DECL_OFFSET = 2, - /// \brief Record code for the table of offsets of each + /// Record code for the table of offsets of each /// identifier ID. /// /// The offset table contains offsets into the blob stored in @@ -403,12 +422,12 @@ namespace serialization { /// NULL-terminated string that corresponds to that identifier. IDENTIFIER_OFFSET = 3, - /// \brief This is so that older clang versions, before the introduction + /// This is so that older clang versions, before the introduction /// of the control block, can read and reject the newer PCH format. /// *DON'T CHANGE THIS NUMBER*. METADATA_OLD_FORMAT = 4, - /// \brief Record code for the identifier table. + /// Record code for the identifier table. /// /// The identifier table is a simple blob that contains /// NULL-terminated strings for all of the identifiers @@ -422,7 +441,7 @@ namespace serialization { /// IDs). IDENTIFIER_TABLE = 5, - /// \brief Record code for the array of eagerly deserialized decls. + /// Record code for the array of eagerly deserialized decls. /// /// The AST file contains a list of all of the declarations that should be /// eagerly deserialized present within the parsed headers, stored as an @@ -432,7 +451,7 @@ namespace serialization { /// program (e.g., for code generation). EAGERLY_DESERIALIZED_DECLS = 6, - /// \brief Record code for the set of non-builtin, special + /// Record code for the set of non-builtin, special /// types. /// /// This record contains the type IDs for the various type nodes @@ -441,31 +460,31 @@ namespace serialization { /// offsets into this record. SPECIAL_TYPES = 7, - /// \brief Record code for the extra statistics we gather while + /// Record code for the extra statistics we gather while /// generating an AST file. STATISTICS = 8, - /// \brief Record code for the array of tentative definitions. + /// Record code for the array of tentative definitions. TENTATIVE_DEFINITIONS = 9, // ID 10 used to be for a list of extern "C" declarations. - /// \brief Record code for the table of offsets into the + /// Record code for the table of offsets into the /// Objective-C method pool. SELECTOR_OFFSETS = 11, - /// \brief Record code for the Objective-C method pool, + /// Record code for the Objective-C method pool, METHOD_POOL = 12, - /// \brief The value of the next __COUNTER__ to dispense. + /// The value of the next __COUNTER__ to dispense. /// [PP_COUNTER_VALUE, Val] PP_COUNTER_VALUE = 13, - /// \brief Record code for the table of offsets into the block + /// Record code for the table of offsets into the block /// of source-location information. SOURCE_LOCATION_OFFSETS = 14, - /// \brief Record code for the set of source location entries + /// Record code for the set of source location entries /// that need to be preloaded by the AST reader. /// /// This set contains the source location entry for the @@ -473,47 +492,47 @@ namespace serialization { /// preloaded. SOURCE_LOCATION_PRELOADS = 15, - /// \brief Record code for the set of ext_vector type names. + /// Record code for the set of ext_vector type names. EXT_VECTOR_DECLS = 16, - /// \brief Record code for the array of unused file scoped decls. + /// Record code for the array of unused file scoped decls. UNUSED_FILESCOPED_DECLS = 17, - /// \brief Record code for the table of offsets to entries in the + /// Record code for the table of offsets to entries in the /// preprocessing record. PPD_ENTITIES_OFFSETS = 18, - /// \brief Record code for the array of VTable uses. + /// Record code for the array of VTable uses. VTABLE_USES = 19, // ID 20 used to be for a list of dynamic classes. - /// \brief Record code for referenced selector pool. + /// Record code for referenced selector pool. REFERENCED_SELECTOR_POOL = 21, - /// \brief Record code for an update to the TU's lexically contained + /// Record code for an update to the TU's lexically contained /// declarations. TU_UPDATE_LEXICAL = 22, // ID 23 used to be for a list of local redeclarations. - /// \brief Record code for declarations that Sema keeps references of. + /// Record code for declarations that Sema keeps references of. SEMA_DECL_REFS = 24, - /// \brief Record code for weak undeclared identifiers. + /// Record code for weak undeclared identifiers. WEAK_UNDECLARED_IDENTIFIERS = 25, - /// \brief Record code for pending implicit instantiations. + /// Record code for pending implicit instantiations. PENDING_IMPLICIT_INSTANTIATIONS = 26, // ID 27 used to be for a list of replacement decls. - /// \brief Record code for an update to a decl context's lookup table. + /// Record code for an update to a decl context's lookup table. /// /// In practice, this should only be used for the TU and namespaces. UPDATE_VISIBLE = 28, - /// \brief Record for offsets of DECL_UPDATES records for declarations + /// Record for offsets of DECL_UPDATES records for declarations /// that were modified after being deserialized and need updates. DECL_UPDATE_OFFSETS = 29, @@ -524,242 +543,245 @@ namespace serialization { // ID 32 used to be the code for \#pragma diagnostic mappings. - /// \brief Record code for special CUDA declarations. + /// Record code for special CUDA declarations. CUDA_SPECIAL_DECL_REFS = 33, - /// \brief Record code for header search information. + /// Record code for header search information. HEADER_SEARCH_TABLE = 34, - /// \brief Record code for floating point \#pragma options. + /// Record code for floating point \#pragma options. FP_PRAGMA_OPTIONS = 35, - /// \brief Record code for enabled OpenCL extensions. + /// Record code for enabled OpenCL extensions. OPENCL_EXTENSIONS = 36, - /// \brief The list of delegating constructor declarations. + /// The list of delegating constructor declarations. DELEGATING_CTORS = 37, - /// \brief Record code for the set of known namespaces, which are used + /// Record code for the set of known namespaces, which are used /// for typo correction. KNOWN_NAMESPACES = 38, - /// \brief Record code for the remapping information used to relate + /// Record code for the remapping information used to relate /// loaded modules to the various offsets and IDs(e.g., source location /// offests, declaration and type IDs) that are used in that module to /// refer to other modules. MODULE_OFFSET_MAP = 39, - /// \brief Record code for the source manager line table information, + /// Record code for the source manager line table information, /// which stores information about \#line directives. SOURCE_MANAGER_LINE_TABLE = 40, - /// \brief Record code for map of Objective-C class definition IDs to the + /// Record code for map of Objective-C class definition IDs to the /// ObjC categories in a module that are attached to that class. OBJC_CATEGORIES_MAP = 41, - /// \brief Record code for a file sorted array of DeclIDs in a module. + /// Record code for a file sorted array of DeclIDs in a module. FILE_SORTED_DECLS = 42, - /// \brief Record code for an array of all of the (sub)modules that were + /// Record code for an array of all of the (sub)modules that were /// imported by the AST file. IMPORTED_MODULES = 43, // ID 44 used to be a table of merged canonical declarations. // ID 45 used to be a list of declaration IDs of local redeclarations. - /// \brief Record code for the array of Objective-C categories (including + /// Record code for the array of Objective-C categories (including /// extensions). /// /// This array can only be interpreted properly using the Objective-C /// categories map. OBJC_CATEGORIES = 46, - /// \brief Record code for the table of offsets of each macro ID. + /// Record code for the table of offsets of each macro ID. /// /// The offset table contains offsets into the blob stored in /// the preprocessor block. Each offset points to the corresponding /// macro definition. MACRO_OFFSET = 47, - /// \brief A list of "interesting" identifiers. Only used in C++ (where we + /// A list of "interesting" identifiers. Only used in C++ (where we /// don't normally do lookups into the serialized identifier table). These /// are eagerly deserialized. INTERESTING_IDENTIFIERS = 48, - /// \brief Record code for undefined but used functions and variables that + /// Record code for undefined but used functions and variables that /// need a definition in this TU. UNDEFINED_BUT_USED = 49, - /// \brief Record code for late parsed template functions. + /// Record code for late parsed template functions. LATE_PARSED_TEMPLATE = 50, - /// \brief Record code for \#pragma optimize options. + /// Record code for \#pragma optimize options. OPTIMIZE_PRAGMA_OPTIONS = 51, - /// \brief Record code for potentially unused local typedef names. + /// Record code for potentially unused local typedef names. UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES = 52, // ID 53 used to be a table of constructor initializer records. - /// \brief Delete expressions that will be analyzed later. + /// Delete expressions that will be analyzed later. DELETE_EXPRS_TO_ANALYZE = 54, - /// \brief Record code for \#pragma ms_struct options. + /// Record code for \#pragma ms_struct options. MSSTRUCT_PRAGMA_OPTIONS = 55, - /// \brief Record code for \#pragma ms_struct options. + /// Record code for \#pragma ms_struct options. POINTERS_TO_MEMBERS_PRAGMA_OPTIONS = 56, - /// \brief Number of unmatched #pragma clang cuda_force_host_device begin + /// Number of unmatched #pragma clang cuda_force_host_device begin /// directives we've seen. CUDA_PRAGMA_FORCE_HOST_DEVICE_DEPTH = 57, - /// \brief Record code for types associated with OpenCL extensions. + /// Record code for types associated with OpenCL extensions. OPENCL_EXTENSION_TYPES = 58, - /// \brief Record code for declarations associated with OpenCL extensions. + /// Record code for declarations associated with OpenCL extensions. OPENCL_EXTENSION_DECLS = 59, MODULAR_CODEGEN_DECLS = 60, - /// \brief Record code for \#pragma pack options. + /// Record code for \#pragma pack options. PACK_PRAGMA_OPTIONS = 61, - /// \brief The stack of open #ifs/#ifdefs recorded in a preamble. + /// The stack of open #ifs/#ifdefs recorded in a preamble. PP_CONDITIONAL_STACK = 62, + + /// A table of skipped ranges within the preprocessing record. + PPD_SKIPPED_RANGES = 63 }; - /// \brief Record types used within a source manager block. + /// Record types used within a source manager block. enum SourceManagerRecordTypes { - /// \brief Describes a source location entry (SLocEntry) for a + /// Describes a source location entry (SLocEntry) for a /// file. SM_SLOC_FILE_ENTRY = 1, - /// \brief Describes a source location entry (SLocEntry) for a + /// Describes a source location entry (SLocEntry) for a /// buffer. SM_SLOC_BUFFER_ENTRY = 2, - /// \brief Describes a blob that contains the data for a buffer + /// Describes a blob that contains the data for a buffer /// entry. This kind of record always directly follows a /// SM_SLOC_BUFFER_ENTRY record or a SM_SLOC_FILE_ENTRY with an /// overridden buffer. SM_SLOC_BUFFER_BLOB = 3, - /// \brief Describes a zlib-compressed blob that contains the data for + /// Describes a zlib-compressed blob that contains the data for /// a buffer entry. SM_SLOC_BUFFER_BLOB_COMPRESSED = 4, - /// \brief Describes a source location entry (SLocEntry) for a + /// Describes a source location entry (SLocEntry) for a /// macro expansion. SM_SLOC_EXPANSION_ENTRY = 5 }; - /// \brief Record types used within a preprocessor block. + /// Record types used within a preprocessor block. enum PreprocessorRecordTypes { // The macros in the PP section are a PP_MACRO_* instance followed by a // list of PP_TOKEN instances for each token in the definition. - /// \brief An object-like macro definition. + /// An object-like macro definition. /// [PP_MACRO_OBJECT_LIKE, IdentInfoID, SLoc, IsUsed] PP_MACRO_OBJECT_LIKE = 1, - /// \brief A function-like macro definition. + /// A function-like macro definition. /// [PP_MACRO_FUNCTION_LIKE, \<ObjectLikeStuff>, IsC99Varargs, /// IsGNUVarars, NumArgs, ArgIdentInfoID* ] PP_MACRO_FUNCTION_LIKE = 2, - /// \brief Describes one token. + /// Describes one token. /// [PP_TOKEN, SLoc, Length, IdentInfoID, Kind, Flags] PP_TOKEN = 3, - /// \brief The macro directives history for a particular identifier. + /// The macro directives history for a particular identifier. PP_MACRO_DIRECTIVE_HISTORY = 4, - /// \brief A macro directive exported by a module. + /// A macro directive exported by a module. /// [PP_MODULE_MACRO, SubmoduleID, MacroID, (Overridden SubmoduleID)*] PP_MODULE_MACRO = 5, }; - /// \brief Record types used within a preprocessor detail block. + /// Record types used within a preprocessor detail block. enum PreprocessorDetailRecordTypes { - /// \brief Describes a macro expansion within the preprocessing record. + /// Describes a macro expansion within the preprocessing record. PPD_MACRO_EXPANSION = 0, - /// \brief Describes a macro definition within the preprocessing record. + /// Describes a macro definition within the preprocessing record. PPD_MACRO_DEFINITION = 1, - /// \brief Describes an inclusion directive within the preprocessing + /// Describes an inclusion directive within the preprocessing /// record. PPD_INCLUSION_DIRECTIVE = 2 }; - /// \brief Record types used within a submodule description block. + /// Record types used within a submodule description block. enum SubmoduleRecordTypes { - /// \brief Metadata for submodules as a whole. + /// Metadata for submodules as a whole. SUBMODULE_METADATA = 0, - /// \brief Defines the major attributes of a submodule, including its + /// Defines the major attributes of a submodule, including its /// name and parent. SUBMODULE_DEFINITION = 1, - /// \brief Specifies the umbrella header used to create this module, + /// Specifies the umbrella header used to create this module, /// if any. SUBMODULE_UMBRELLA_HEADER = 2, - /// \brief Specifies a header that falls into this (sub)module. + /// Specifies a header that falls into this (sub)module. SUBMODULE_HEADER = 3, - /// \brief Specifies a top-level header that falls into this (sub)module. + /// Specifies a top-level header that falls into this (sub)module. SUBMODULE_TOPHEADER = 4, - /// \brief Specifies an umbrella directory. + /// Specifies an umbrella directory. SUBMODULE_UMBRELLA_DIR = 5, - /// \brief Specifies the submodules that are imported by this + /// Specifies the submodules that are imported by this /// submodule. SUBMODULE_IMPORTS = 6, - /// \brief Specifies the submodules that are re-exported from this + /// Specifies the submodules that are re-exported from this /// submodule. SUBMODULE_EXPORTS = 7, - /// \brief Specifies a required feature. + /// Specifies a required feature. SUBMODULE_REQUIRES = 8, - /// \brief Specifies a header that has been explicitly excluded + /// Specifies a header that has been explicitly excluded /// from this submodule. SUBMODULE_EXCLUDED_HEADER = 9, - /// \brief Specifies a library or framework to link against. + /// Specifies a library or framework to link against. SUBMODULE_LINK_LIBRARY = 10, - /// \brief Specifies a configuration macro for this module. + /// Specifies a configuration macro for this module. SUBMODULE_CONFIG_MACRO = 11, - /// \brief Specifies a conflict with another module. + /// Specifies a conflict with another module. SUBMODULE_CONFLICT = 12, - /// \brief Specifies a header that is private to this submodule. + /// Specifies a header that is private to this submodule. SUBMODULE_PRIVATE_HEADER = 13, - /// \brief Specifies a header that is part of the module but must be + /// 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 + /// Specifies a header that is private to this submodule but /// must be textually included. SUBMODULE_PRIVATE_TEXTUAL_HEADER = 15, - /// \brief Specifies some declarations with initializers that must be + /// Specifies some declarations with initializers that must be /// emitted to initialize the module. SUBMODULE_INITIALIZERS = 16, - /// \brief Specifies the name of the module that will eventually + /// Specifies the name of the module that will eventually /// re-export the entities in this module. SUBMODULE_EXPORT_AS = 17, }; - /// \brief Record types used within a comments block. + /// Record types used within a comments block. enum CommentRecordTypes { COMMENTS_RAW_COMMENT = 0 }; @@ -771,7 +793,7 @@ namespace serialization { /// /// @{ - /// \brief Predefined type IDs. + /// Predefined type IDs. /// /// These type IDs correspond to predefined types in the AST /// context, such as built-in types (int) and special place-holder @@ -779,496 +801,574 @@ namespace serialization { /// types are never actually serialized, since they will be built /// by the AST context when it is created. enum PredefinedTypeIDs { - /// \brief The NULL type. + /// The NULL type. PREDEF_TYPE_NULL_ID = 0, - /// \brief The void type. + /// The void type. PREDEF_TYPE_VOID_ID = 1, - /// \brief The 'bool' or '_Bool' type. + /// The 'bool' or '_Bool' type. PREDEF_TYPE_BOOL_ID = 2, - /// \brief The 'char' type, when it is unsigned. + /// The 'char' type, when it is unsigned. PREDEF_TYPE_CHAR_U_ID = 3, - /// \brief The 'unsigned char' type. + /// The 'unsigned char' type. PREDEF_TYPE_UCHAR_ID = 4, - /// \brief The 'unsigned short' type. + /// The 'unsigned short' type. PREDEF_TYPE_USHORT_ID = 5, - /// \brief The 'unsigned int' type. + /// The 'unsigned int' type. PREDEF_TYPE_UINT_ID = 6, - /// \brief The 'unsigned long' type. + /// The 'unsigned long' type. PREDEF_TYPE_ULONG_ID = 7, - /// \brief The 'unsigned long long' type. + /// The 'unsigned long long' type. PREDEF_TYPE_ULONGLONG_ID = 8, - /// \brief The 'char' type, when it is signed. + /// The 'char' type, when it is signed. PREDEF_TYPE_CHAR_S_ID = 9, - /// \brief The 'signed char' type. + /// The 'signed char' type. PREDEF_TYPE_SCHAR_ID = 10, - /// \brief The C++ 'wchar_t' type. + /// The C++ 'wchar_t' type. PREDEF_TYPE_WCHAR_ID = 11, - /// \brief The (signed) 'short' type. + /// The (signed) 'short' type. PREDEF_TYPE_SHORT_ID = 12, - /// \brief The (signed) 'int' type. + /// The (signed) 'int' type. PREDEF_TYPE_INT_ID = 13, - /// \brief The (signed) 'long' type. + /// The (signed) 'long' type. PREDEF_TYPE_LONG_ID = 14, - /// \brief The (signed) 'long long' type. + /// The (signed) 'long long' type. PREDEF_TYPE_LONGLONG_ID = 15, - /// \brief The 'float' type. + /// The 'float' type. PREDEF_TYPE_FLOAT_ID = 16, - /// \brief The 'double' type. + /// The 'double' type. PREDEF_TYPE_DOUBLE_ID = 17, - /// \brief The 'long double' type. + /// The 'long double' type. PREDEF_TYPE_LONGDOUBLE_ID = 18, - /// \brief The placeholder type for overloaded function sets. + /// The placeholder type for overloaded function sets. PREDEF_TYPE_OVERLOAD_ID = 19, - /// \brief The placeholder type for dependent types. + /// The placeholder type for dependent types. PREDEF_TYPE_DEPENDENT_ID = 20, - /// \brief The '__uint128_t' type. + /// The '__uint128_t' type. PREDEF_TYPE_UINT128_ID = 21, - /// \brief The '__int128_t' type. + /// The '__int128_t' type. PREDEF_TYPE_INT128_ID = 22, - /// \brief The type of 'nullptr'. + /// The type of 'nullptr'. PREDEF_TYPE_NULLPTR_ID = 23, - /// \brief The C++ 'char16_t' type. + /// The C++ 'char16_t' type. PREDEF_TYPE_CHAR16_ID = 24, - /// \brief The C++ 'char32_t' type. + /// The C++ 'char32_t' type. PREDEF_TYPE_CHAR32_ID = 25, - /// \brief The ObjC 'id' type. + /// The ObjC 'id' type. PREDEF_TYPE_OBJC_ID = 26, - /// \brief The ObjC 'Class' type. + /// The ObjC 'Class' type. PREDEF_TYPE_OBJC_CLASS = 27, - /// \brief The ObjC 'SEL' type. + /// The ObjC 'SEL' type. PREDEF_TYPE_OBJC_SEL = 28, - /// \brief The 'unknown any' placeholder type. + /// The 'unknown any' placeholder type. PREDEF_TYPE_UNKNOWN_ANY = 29, - /// \brief The placeholder type for bound member functions. + /// The placeholder type for bound member functions. PREDEF_TYPE_BOUND_MEMBER = 30, - /// \brief The "auto" deduction type. + /// The "auto" deduction type. PREDEF_TYPE_AUTO_DEDUCT = 31, - /// \brief The "auto &&" deduction type. + /// The "auto &&" deduction type. PREDEF_TYPE_AUTO_RREF_DEDUCT = 32, - /// \brief The OpenCL 'half' / ARM NEON __fp16 type. + /// The OpenCL 'half' / ARM NEON __fp16 type. PREDEF_TYPE_HALF_ID = 33, - /// \brief ARC's unbridged-cast placeholder type. + /// ARC's unbridged-cast placeholder type. PREDEF_TYPE_ARC_UNBRIDGED_CAST = 34, - /// \brief The pseudo-object placeholder type. + /// The pseudo-object placeholder type. PREDEF_TYPE_PSEUDO_OBJECT = 35, - /// \brief The placeholder type for builtin functions. + /// The placeholder type for builtin functions. PREDEF_TYPE_BUILTIN_FN = 36, - /// \brief OpenCL event type. + /// OpenCL event type. PREDEF_TYPE_EVENT_ID = 37, - /// \brief OpenCL clk event type. + /// OpenCL clk event type. PREDEF_TYPE_CLK_EVENT_ID = 38, - /// \brief OpenCL sampler type. + /// OpenCL sampler type. PREDEF_TYPE_SAMPLER_ID = 39, - /// \brief OpenCL queue type. + /// OpenCL queue type. PREDEF_TYPE_QUEUE_ID = 40, - /// \brief OpenCL reserve_id type. + /// OpenCL reserve_id type. PREDEF_TYPE_RESERVE_ID_ID = 41, - /// \brief The placeholder type for OpenMP array section. + /// The placeholder type for OpenMP array section. PREDEF_TYPE_OMP_ARRAY_SECTION = 42, - /// \brief The '__float128' type + /// The '__float128' type PREDEF_TYPE_FLOAT128_ID = 43, - /// \brief The '_Float16' type + /// The '_Float16' type PREDEF_TYPE_FLOAT16_ID = 44, - /// \brief OpenCL image types with auto numeration + /// The C++ 'char8_t' type. + PREDEF_TYPE_CHAR8_ID = 45, + + /// \brief The 'short _Accum' type + PREDEF_TYPE_SHORT_ACCUM_ID = 46, + + /// \brief The '_Accum' type + PREDEF_TYPE_ACCUM_ID = 47, + + /// \brief The 'long _Accum' type + PREDEF_TYPE_LONG_ACCUM_ID = 48, + + /// \brief The 'unsigned short _Accum' type + PREDEF_TYPE_USHORT_ACCUM_ID = 49, + + /// \brief The 'unsigned _Accum' type + PREDEF_TYPE_UACCUM_ID = 50, + + /// \brief The 'unsigned long _Accum' type + PREDEF_TYPE_ULONG_ACCUM_ID = 51, + + /// \brief The 'short _Fract' type + PREDEF_TYPE_SHORT_FRACT_ID = 52, + + /// \brief The '_Fract' type + PREDEF_TYPE_FRACT_ID = 53, + + /// \brief The 'long _Fract' type + PREDEF_TYPE_LONG_FRACT_ID = 54, + + /// \brief The 'unsigned short _Fract' type + PREDEF_TYPE_USHORT_FRACT_ID = 55, + + /// \brief The 'unsigned _Fract' type + PREDEF_TYPE_UFRACT_ID = 56, + + /// \brief The 'unsigned long _Fract' type + PREDEF_TYPE_ULONG_FRACT_ID = 57, + + /// \brief The '_Sat short _Accum' type + PREDEF_TYPE_SAT_SHORT_ACCUM_ID = 58, + + /// \brief The '_Sat _Accum' type + PREDEF_TYPE_SAT_ACCUM_ID = 59, + + /// \brief The '_Sat long _Accum' type + PREDEF_TYPE_SAT_LONG_ACCUM_ID = 60, + + /// \brief The '_Sat unsigned short _Accum' type + PREDEF_TYPE_SAT_USHORT_ACCUM_ID = 61, + + /// \brief The '_Sat unsigned _Accum' type + PREDEF_TYPE_SAT_UACCUM_ID = 62, + + /// \brief The '_Sat unsigned long _Accum' type + PREDEF_TYPE_SAT_ULONG_ACCUM_ID = 63, + + /// \brief The '_Sat short _Fract' type + PREDEF_TYPE_SAT_SHORT_FRACT_ID = 64, + + /// \brief The '_Sat _Fract' type + PREDEF_TYPE_SAT_FRACT_ID = 65, + + /// \brief The '_Sat long _Fract' type + PREDEF_TYPE_SAT_LONG_FRACT_ID = 66, + + /// \brief The '_Sat unsigned short _Fract' type + PREDEF_TYPE_SAT_USHORT_FRACT_ID = 67, + + /// \brief The '_Sat unsigned _Fract' type + PREDEF_TYPE_SAT_UFRACT_ID = 68, + + /// \brief The '_Sat unsigned long _Fract' type + PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69, + + /// OpenCL image types with auto numeration #define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \ PREDEF_TYPE_##Id##_ID, #include "clang/Basic/OpenCLImageTypes.def" }; - /// \brief The number of predefined type IDs that are reserved for + /// The number of predefined type IDs that are reserved for /// the PREDEF_TYPE_* constants. /// /// Type IDs for non-predefined types will start at /// NUM_PREDEF_TYPE_IDs. - const unsigned NUM_PREDEF_TYPE_IDS = 100; + const unsigned NUM_PREDEF_TYPE_IDS = 200; - /// \brief Record codes for each kind of type. + /// Record codes for each kind of type. /// /// These constants describe the type records that can occur within a /// block identified by DECLTYPES_BLOCK_ID in the AST file. Each /// constant describes a record for a specific type class in the /// AST. Note that DeclCode values share this code space. enum TypeCode { - /// \brief An ExtQualType record. - TYPE_EXT_QUAL = 1, + /// An ExtQualType record. + TYPE_EXT_QUAL = 1, - /// \brief A ComplexType record. - TYPE_COMPLEX = 3, + /// A ComplexType record. + TYPE_COMPLEX = 3, - /// \brief A PointerType record. - TYPE_POINTER = 4, + /// A PointerType record. + TYPE_POINTER = 4, - /// \brief A BlockPointerType record. - TYPE_BLOCK_POINTER = 5, + /// A BlockPointerType record. + TYPE_BLOCK_POINTER = 5, - /// \brief An LValueReferenceType record. - TYPE_LVALUE_REFERENCE = 6, + /// An LValueReferenceType record. + TYPE_LVALUE_REFERENCE = 6, - /// \brief An RValueReferenceType record. - TYPE_RVALUE_REFERENCE = 7, + /// An RValueReferenceType record. + TYPE_RVALUE_REFERENCE = 7, - /// \brief A MemberPointerType record. - TYPE_MEMBER_POINTER = 8, + /// A MemberPointerType record. + TYPE_MEMBER_POINTER = 8, - /// \brief A ConstantArrayType record. - TYPE_CONSTANT_ARRAY = 9, + /// A ConstantArrayType record. + TYPE_CONSTANT_ARRAY = 9, - /// \brief An IncompleteArrayType record. - TYPE_INCOMPLETE_ARRAY = 10, + /// An IncompleteArrayType record. + TYPE_INCOMPLETE_ARRAY = 10, - /// \brief A VariableArrayType record. - TYPE_VARIABLE_ARRAY = 11, + /// A VariableArrayType record. + TYPE_VARIABLE_ARRAY = 11, - /// \brief A VectorType record. - TYPE_VECTOR = 12, + /// A VectorType record. + TYPE_VECTOR = 12, - /// \brief An ExtVectorType record. - TYPE_EXT_VECTOR = 13, + /// An ExtVectorType record. + TYPE_EXT_VECTOR = 13, - /// \brief A FunctionNoProtoType record. - TYPE_FUNCTION_NO_PROTO = 14, + /// A FunctionNoProtoType record. + TYPE_FUNCTION_NO_PROTO = 14, - /// \brief A FunctionProtoType record. - TYPE_FUNCTION_PROTO = 15, + /// A FunctionProtoType record. + TYPE_FUNCTION_PROTO = 15, - /// \brief A TypedefType record. - TYPE_TYPEDEF = 16, + /// A TypedefType record. + TYPE_TYPEDEF = 16, - /// \brief A TypeOfExprType record. - TYPE_TYPEOF_EXPR = 17, + /// A TypeOfExprType record. + TYPE_TYPEOF_EXPR = 17, - /// \brief A TypeOfType record. - TYPE_TYPEOF = 18, + /// A TypeOfType record. + TYPE_TYPEOF = 18, - /// \brief A RecordType record. - TYPE_RECORD = 19, + /// A RecordType record. + TYPE_RECORD = 19, - /// \brief An EnumType record. - TYPE_ENUM = 20, + /// An EnumType record. + TYPE_ENUM = 20, - /// \brief An ObjCInterfaceType record. - TYPE_OBJC_INTERFACE = 21, + /// An ObjCInterfaceType record. + TYPE_OBJC_INTERFACE = 21, - /// \brief An ObjCObjectPointerType record. - TYPE_OBJC_OBJECT_POINTER = 22, + /// An ObjCObjectPointerType record. + TYPE_OBJC_OBJECT_POINTER = 22, - /// \brief a DecltypeType record. - TYPE_DECLTYPE = 23, + /// a DecltypeType record. + TYPE_DECLTYPE = 23, - /// \brief An ElaboratedType record. - TYPE_ELABORATED = 24, + /// An ElaboratedType record. + TYPE_ELABORATED = 24, - /// \brief A SubstTemplateTypeParmType record. + /// A SubstTemplateTypeParmType record. TYPE_SUBST_TEMPLATE_TYPE_PARM = 25, - /// \brief An UnresolvedUsingType record. - TYPE_UNRESOLVED_USING = 26, + /// An UnresolvedUsingType record. + TYPE_UNRESOLVED_USING = 26, - /// \brief An InjectedClassNameType record. - TYPE_INJECTED_CLASS_NAME = 27, + /// An InjectedClassNameType record. + TYPE_INJECTED_CLASS_NAME = 27, - /// \brief An ObjCObjectType record. - TYPE_OBJC_OBJECT = 28, + /// An ObjCObjectType record. + TYPE_OBJC_OBJECT = 28, - /// \brief An TemplateTypeParmType record. - TYPE_TEMPLATE_TYPE_PARM = 29, + /// An TemplateTypeParmType record. + TYPE_TEMPLATE_TYPE_PARM = 29, - /// \brief An TemplateSpecializationType record. - TYPE_TEMPLATE_SPECIALIZATION = 30, + /// An TemplateSpecializationType record. + TYPE_TEMPLATE_SPECIALIZATION = 30, - /// \brief A DependentNameType record. - TYPE_DEPENDENT_NAME = 31, + /// A DependentNameType record. + TYPE_DEPENDENT_NAME = 31, - /// \brief A DependentTemplateSpecializationType record. + /// A DependentTemplateSpecializationType record. TYPE_DEPENDENT_TEMPLATE_SPECIALIZATION = 32, - /// \brief A DependentSizedArrayType record. - TYPE_DEPENDENT_SIZED_ARRAY = 33, + /// A DependentSizedArrayType record. + TYPE_DEPENDENT_SIZED_ARRAY = 33, - /// \brief A ParenType record. - TYPE_PAREN = 34, + /// A ParenType record. + TYPE_PAREN = 34, - /// \brief A PackExpansionType record. - TYPE_PACK_EXPANSION = 35, + /// A PackExpansionType record. + TYPE_PACK_EXPANSION = 35, - /// \brief An AttributedType record. - TYPE_ATTRIBUTED = 36, + /// An AttributedType record. + TYPE_ATTRIBUTED = 36, - /// \brief A SubstTemplateTypeParmPackType record. + /// A SubstTemplateTypeParmPackType record. TYPE_SUBST_TEMPLATE_TYPE_PARM_PACK = 37, - /// \brief A AutoType record. - TYPE_AUTO = 38, + /// A AutoType record. + TYPE_AUTO = 38, - /// \brief A UnaryTransformType record. - TYPE_UNARY_TRANSFORM = 39, + /// A UnaryTransformType record. + TYPE_UNARY_TRANSFORM = 39, - /// \brief An AtomicType record. - TYPE_ATOMIC = 40, + /// An AtomicType record. + TYPE_ATOMIC = 40, - /// \brief A DecayedType record. - TYPE_DECAYED = 41, + /// A DecayedType record. + TYPE_DECAYED = 41, - /// \brief An AdjustedType record. - TYPE_ADJUSTED = 42, + /// An AdjustedType record. + TYPE_ADJUSTED = 42, - /// \brief A PipeType record. - TYPE_PIPE = 43, + /// A PipeType record. + TYPE_PIPE = 43, - /// \brief An ObjCTypeParamType record. - TYPE_OBJC_TYPE_PARAM = 44, + /// An ObjCTypeParamType record. + TYPE_OBJC_TYPE_PARAM = 44, - /// \brief A DeducedTemplateSpecializationType record. + /// A DeducedTemplateSpecializationType record. TYPE_DEDUCED_TEMPLATE_SPECIALIZATION = 45, - /// \brief A DependentSizedExtVectorType record. + /// A DependentSizedExtVectorType record. TYPE_DEPENDENT_SIZED_EXT_VECTOR = 46, - /// \brief A DependentAddressSpaceType record. - TYPE_DEPENDENT_ADDRESS_SPACE = 47 + /// A DependentAddressSpaceType record. + TYPE_DEPENDENT_ADDRESS_SPACE = 47, + + /// A dependentSizedVectorType record. + TYPE_DEPENDENT_SIZED_VECTOR = 48 }; - /// \brief The type IDs for special types constructed by semantic + /// The type IDs for special types constructed by semantic /// analysis. /// /// The constants in this enumeration are indices into the /// SPECIAL_TYPES record. enum SpecialTypeIDs { - /// \brief CFConstantString type + /// CFConstantString type SPECIAL_TYPE_CF_CONSTANT_STRING = 0, - /// \brief C FILE typedef type + /// C FILE typedef type SPECIAL_TYPE_FILE = 1, - /// \brief C jmp_buf typedef type + /// C jmp_buf typedef type SPECIAL_TYPE_JMP_BUF = 2, - /// \brief C sigjmp_buf typedef type + /// C sigjmp_buf typedef type SPECIAL_TYPE_SIGJMP_BUF = 3, - /// \brief Objective-C "id" redefinition type + /// Objective-C "id" redefinition type SPECIAL_TYPE_OBJC_ID_REDEFINITION = 4, - /// \brief Objective-C "Class" redefinition type + /// Objective-C "Class" redefinition type SPECIAL_TYPE_OBJC_CLASS_REDEFINITION = 5, - /// \brief Objective-C "SEL" redefinition type + /// Objective-C "SEL" redefinition type SPECIAL_TYPE_OBJC_SEL_REDEFINITION = 6, - /// \brief C ucontext_t typedef type + /// C ucontext_t typedef type SPECIAL_TYPE_UCONTEXT_T = 7 }; - /// \brief The number of special type IDs. + /// The number of special type IDs. const unsigned NumSpecialTypeIDs = 8; - /// \brief Predefined declaration IDs. + /// Predefined declaration IDs. /// /// These declaration IDs correspond to predefined declarations in the AST /// context, such as the NULL declaration ID. Such declarations are never /// actually serialized, since they will be built by the AST context when /// it is created. enum PredefinedDeclIDs { - /// \brief The NULL declaration. + /// The NULL declaration. PREDEF_DECL_NULL_ID = 0, - /// \brief The translation unit. + /// The translation unit. PREDEF_DECL_TRANSLATION_UNIT_ID = 1, - /// \brief The Objective-C 'id' type. + /// The Objective-C 'id' type. PREDEF_DECL_OBJC_ID_ID = 2, - /// \brief The Objective-C 'SEL' type. + /// The Objective-C 'SEL' type. PREDEF_DECL_OBJC_SEL_ID = 3, - /// \brief The Objective-C 'Class' type. + /// The Objective-C 'Class' type. PREDEF_DECL_OBJC_CLASS_ID = 4, - /// \brief The Objective-C 'Protocol' type. + /// The Objective-C 'Protocol' type. PREDEF_DECL_OBJC_PROTOCOL_ID = 5, - /// \brief The signed 128-bit integer type. + /// The signed 128-bit integer type. PREDEF_DECL_INT_128_ID = 6, - /// \brief The unsigned 128-bit integer type. + /// The unsigned 128-bit integer type. PREDEF_DECL_UNSIGNED_INT_128_ID = 7, - /// \brief The internal 'instancetype' typedef. + /// The internal 'instancetype' typedef. PREDEF_DECL_OBJC_INSTANCETYPE_ID = 8, - /// \brief The internal '__builtin_va_list' typedef. + /// The internal '__builtin_va_list' typedef. PREDEF_DECL_BUILTIN_VA_LIST_ID = 9, - /// \brief The internal '__va_list_tag' struct, if any. + /// The internal '__va_list_tag' struct, if any. PREDEF_DECL_VA_LIST_TAG = 10, - /// \brief The internal '__builtin_ms_va_list' typedef. + /// The internal '__builtin_ms_va_list' typedef. PREDEF_DECL_BUILTIN_MS_VA_LIST_ID = 11, - /// \brief The extern "C" context. + /// The extern "C" context. PREDEF_DECL_EXTERN_C_CONTEXT_ID = 12, - /// \brief The internal '__make_integer_seq' template. + /// The internal '__make_integer_seq' template. PREDEF_DECL_MAKE_INTEGER_SEQ_ID = 13, - /// \brief The internal '__NSConstantString' typedef. + /// The internal '__NSConstantString' typedef. PREDEF_DECL_CF_CONSTANT_STRING_ID = 14, - /// \brief The internal '__NSConstantString' tag type. + /// The internal '__NSConstantString' tag type. PREDEF_DECL_CF_CONSTANT_STRING_TAG_ID = 15, - /// \brief The internal '__type_pack_element' template. + /// The internal '__type_pack_element' template. PREDEF_DECL_TYPE_PACK_ELEMENT_ID = 16, }; - /// \brief The number of declaration IDs that are predefined. + /// The number of declaration IDs that are predefined. /// /// For more information about predefined declarations, see the /// \c PredefinedDeclIDs type and the PREDEF_DECL_*_ID constants. const unsigned int NUM_PREDEF_DECL_IDS = 17; - /// \brief Record of updates for a declaration that was modified after + /// Record of updates for a declaration that was modified after /// being deserialized. This can occur within DECLTYPES_BLOCK_ID. const unsigned int DECL_UPDATES = 49; - /// \brief Record code for a list of local redeclarations of a declaration. + /// Record code for a list of local redeclarations of a declaration. /// This can occur within DECLTYPES_BLOCK_ID. const unsigned int LOCAL_REDECLARATIONS = 50; - /// \brief Record codes for each kind of declaration. + /// Record codes for each kind of declaration. /// /// These constants describe the declaration records that can occur within /// a declarations block (identified by DECLTYPES_BLOCK_ID). Each /// constant describes a record for a specific declaration class /// in the AST. Note that TypeCode values share this code space. enum DeclCode { - /// \brief A TypedefDecl record. + /// A TypedefDecl record. DECL_TYPEDEF = 51, - /// \brief A TypeAliasDecl record. + /// A TypeAliasDecl record. DECL_TYPEALIAS, - /// \brief An EnumDecl record. + /// An EnumDecl record. DECL_ENUM, - /// \brief A RecordDecl record. + /// A RecordDecl record. DECL_RECORD, - /// \brief An EnumConstantDecl record. + /// An EnumConstantDecl record. DECL_ENUM_CONSTANT, - /// \brief A FunctionDecl record. + /// A FunctionDecl record. DECL_FUNCTION, - /// \brief A ObjCMethodDecl record. + /// A ObjCMethodDecl record. DECL_OBJC_METHOD, - /// \brief A ObjCInterfaceDecl record. + /// A ObjCInterfaceDecl record. DECL_OBJC_INTERFACE, - /// \brief A ObjCProtocolDecl record. + /// A ObjCProtocolDecl record. DECL_OBJC_PROTOCOL, - /// \brief A ObjCIvarDecl record. + /// A ObjCIvarDecl record. DECL_OBJC_IVAR, - /// \brief A ObjCAtDefsFieldDecl record. + /// A ObjCAtDefsFieldDecl record. DECL_OBJC_AT_DEFS_FIELD, - /// \brief A ObjCCategoryDecl record. + /// A ObjCCategoryDecl record. DECL_OBJC_CATEGORY, - /// \brief A ObjCCategoryImplDecl record. + /// A ObjCCategoryImplDecl record. DECL_OBJC_CATEGORY_IMPL, - /// \brief A ObjCImplementationDecl record. + /// A ObjCImplementationDecl record. DECL_OBJC_IMPLEMENTATION, - /// \brief A ObjCCompatibleAliasDecl record. + /// A ObjCCompatibleAliasDecl record. DECL_OBJC_COMPATIBLE_ALIAS, - /// \brief A ObjCPropertyDecl record. + /// A ObjCPropertyDecl record. DECL_OBJC_PROPERTY, - /// \brief A ObjCPropertyImplDecl record. + /// A ObjCPropertyImplDecl record. DECL_OBJC_PROPERTY_IMPL, - /// \brief A FieldDecl record. + /// A FieldDecl record. DECL_FIELD, - /// \brief A MSPropertyDecl record. + /// A MSPropertyDecl record. DECL_MS_PROPERTY, - /// \brief A VarDecl record. + /// A VarDecl record. DECL_VAR, - /// \brief An ImplicitParamDecl record. + /// An ImplicitParamDecl record. DECL_IMPLICIT_PARAM, - /// \brief A ParmVarDecl record. + /// A ParmVarDecl record. DECL_PARM_VAR, - /// \brief A DecompositionDecl record. + /// A DecompositionDecl record. DECL_DECOMPOSITION, - /// \brief A BindingDecl record. + /// A BindingDecl record. DECL_BINDING, - /// \brief A FileScopeAsmDecl record. + /// A FileScopeAsmDecl record. DECL_FILE_SCOPE_ASM, - /// \brief A BlockDecl record. + /// A BlockDecl record. DECL_BLOCK, - /// \brief A CapturedDecl record. + /// A CapturedDecl record. DECL_CAPTURED, - /// \brief A record that stores the set of declarations that are + /// A record that stores the set of declarations that are /// lexically stored within a given DeclContext. /// /// The record itself is a blob that is an array of declaration IDs, @@ -1278,7 +1378,7 @@ namespace serialization { /// DeclContext::decls_begin() and DeclContext::decls_end(). DECL_CONTEXT_LEXICAL, - /// \brief A record that stores the set of declarations that are + /// A record that stores the set of declarations that are /// visible from a given DeclContext. /// /// The record itself stores a set of mappings, each of which @@ -1287,155 +1387,155 @@ namespace serialization { /// into a DeclContext via DeclContext::lookup. DECL_CONTEXT_VISIBLE, - /// \brief A LabelDecl record. + /// A LabelDecl record. DECL_LABEL, - /// \brief A NamespaceDecl record. + /// A NamespaceDecl record. DECL_NAMESPACE, - /// \brief A NamespaceAliasDecl record. + /// A NamespaceAliasDecl record. DECL_NAMESPACE_ALIAS, - /// \brief A UsingDecl record. + /// A UsingDecl record. DECL_USING, - /// \brief A UsingPackDecl record. + /// A UsingPackDecl record. DECL_USING_PACK, - /// \brief A UsingShadowDecl record. + /// A UsingShadowDecl record. DECL_USING_SHADOW, - /// \brief A ConstructorUsingShadowDecl record. + /// A ConstructorUsingShadowDecl record. DECL_CONSTRUCTOR_USING_SHADOW, - /// \brief A UsingDirecitveDecl record. + /// A UsingDirecitveDecl record. DECL_USING_DIRECTIVE, - /// \brief An UnresolvedUsingValueDecl record. + /// An UnresolvedUsingValueDecl record. DECL_UNRESOLVED_USING_VALUE, - /// \brief An UnresolvedUsingTypenameDecl record. + /// An UnresolvedUsingTypenameDecl record. DECL_UNRESOLVED_USING_TYPENAME, - /// \brief A LinkageSpecDecl record. + /// A LinkageSpecDecl record. DECL_LINKAGE_SPEC, - /// \brief An ExportDecl record. + /// An ExportDecl record. DECL_EXPORT, - /// \brief A CXXRecordDecl record. + /// A CXXRecordDecl record. DECL_CXX_RECORD, - /// \brief A CXXDeductionGuideDecl record. + /// A CXXDeductionGuideDecl record. DECL_CXX_DEDUCTION_GUIDE, - /// \brief A CXXMethodDecl record. + /// A CXXMethodDecl record. DECL_CXX_METHOD, - /// \brief A CXXConstructorDecl record. + /// A CXXConstructorDecl record. DECL_CXX_CONSTRUCTOR, - /// \brief A CXXConstructorDecl record for an inherited constructor. + /// A CXXConstructorDecl record for an inherited constructor. DECL_CXX_INHERITED_CONSTRUCTOR, - /// \brief A CXXDestructorDecl record. + /// A CXXDestructorDecl record. DECL_CXX_DESTRUCTOR, - /// \brief A CXXConversionDecl record. + /// A CXXConversionDecl record. DECL_CXX_CONVERSION, - /// \brief An AccessSpecDecl record. + /// An AccessSpecDecl record. DECL_ACCESS_SPEC, - /// \brief A FriendDecl record. + /// A FriendDecl record. DECL_FRIEND, - /// \brief A FriendTemplateDecl record. + /// A FriendTemplateDecl record. DECL_FRIEND_TEMPLATE, - /// \brief A ClassTemplateDecl record. + /// A ClassTemplateDecl record. DECL_CLASS_TEMPLATE, - /// \brief A ClassTemplateSpecializationDecl record. + /// A ClassTemplateSpecializationDecl record. DECL_CLASS_TEMPLATE_SPECIALIZATION, - /// \brief A ClassTemplatePartialSpecializationDecl record. + /// A ClassTemplatePartialSpecializationDecl record. DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION, - /// \brief A VarTemplateDecl record. + /// A VarTemplateDecl record. DECL_VAR_TEMPLATE, - /// \brief A VarTemplateSpecializationDecl record. + /// A VarTemplateSpecializationDecl record. DECL_VAR_TEMPLATE_SPECIALIZATION, - /// \brief A VarTemplatePartialSpecializationDecl record. + /// A VarTemplatePartialSpecializationDecl record. DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION, - /// \brief A FunctionTemplateDecl record. + /// A FunctionTemplateDecl record. DECL_FUNCTION_TEMPLATE, - /// \brief A TemplateTypeParmDecl record. + /// A TemplateTypeParmDecl record. DECL_TEMPLATE_TYPE_PARM, - /// \brief A NonTypeTemplateParmDecl record. + /// A NonTypeTemplateParmDecl record. DECL_NON_TYPE_TEMPLATE_PARM, - /// \brief A TemplateTemplateParmDecl record. + /// A TemplateTemplateParmDecl record. DECL_TEMPLATE_TEMPLATE_PARM, - /// \brief A TypeAliasTemplateDecl record. + /// A TypeAliasTemplateDecl record. DECL_TYPE_ALIAS_TEMPLATE, - /// \brief A StaticAssertDecl record. + /// A StaticAssertDecl record. DECL_STATIC_ASSERT, - /// \brief A record containing CXXBaseSpecifiers. + /// A record containing CXXBaseSpecifiers. DECL_CXX_BASE_SPECIFIERS, - /// \brief A record containing CXXCtorInitializers. + /// A record containing CXXCtorInitializers. DECL_CXX_CTOR_INITIALIZERS, - /// \brief A IndirectFieldDecl record. + /// A IndirectFieldDecl record. DECL_INDIRECTFIELD, - /// \brief A NonTypeTemplateParmDecl record that stores an expanded + /// A NonTypeTemplateParmDecl record that stores an expanded /// non-type template parameter pack. DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK, - /// \brief A TemplateTemplateParmDecl record that stores an expanded + /// A TemplateTemplateParmDecl record that stores an expanded /// template template parameter pack. DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK, - /// \brief A ClassScopeFunctionSpecializationDecl record a class scope + /// A ClassScopeFunctionSpecializationDecl record a class scope /// function specialization. (Microsoft extension). DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION, - /// \brief An ImportDecl recording a module import. + /// An ImportDecl recording a module import. DECL_IMPORT, - /// \brief An OMPThreadPrivateDecl record. + /// An OMPThreadPrivateDecl record. DECL_OMP_THREADPRIVATE, - /// \brief An EmptyDecl record. + /// An EmptyDecl record. DECL_EMPTY, - /// \brief An ObjCTypeParamDecl record. + /// An ObjCTypeParamDecl record. DECL_OBJC_TYPE_PARAM, - /// \brief An OMPCapturedExprDecl record. + /// An OMPCapturedExprDecl record. DECL_OMP_CAPTUREDEXPR, - /// \brief A PragmaCommentDecl record. + /// A PragmaCommentDecl record. DECL_PRAGMA_COMMENT, - /// \brief A PragmaDetectMismatchDecl record. + /// A PragmaDetectMismatchDecl record. DECL_PRAGMA_DETECT_MISMATCH, - /// \brief An OMPDeclareReductionDecl record. + /// An OMPDeclareReductionDecl record. DECL_OMP_DECLARE_REDUCTION, }; - /// \brief Record codes for each kind of statement or expression. + /// Record codes for each kind of statement or expression. /// /// These constants describe the records that describe statements /// or expressions. These records occur within type and declarations @@ -1443,310 +1543,310 @@ namespace serialization { /// describes a record for a specific statement or expression class in the /// AST. enum StmtCode { - /// \brief A marker record that indicates that we are at the end + /// A marker record that indicates that we are at the end /// of an expression. STMT_STOP = 128, - /// \brief A NULL expression. + /// A NULL expression. STMT_NULL_PTR, - /// \brief A reference to a previously [de]serialized Stmt record. + /// A reference to a previously [de]serialized Stmt record. STMT_REF_PTR, - /// \brief A NullStmt record. + /// A NullStmt record. STMT_NULL, - /// \brief A CompoundStmt record. + /// A CompoundStmt record. STMT_COMPOUND, - /// \brief A CaseStmt record. + /// A CaseStmt record. STMT_CASE, - /// \brief A DefaultStmt record. + /// A DefaultStmt record. STMT_DEFAULT, - /// \brief A LabelStmt record. + /// A LabelStmt record. STMT_LABEL, - /// \brief An AttributedStmt record. + /// An AttributedStmt record. STMT_ATTRIBUTED, - /// \brief An IfStmt record. + /// An IfStmt record. STMT_IF, - /// \brief A SwitchStmt record. + /// A SwitchStmt record. STMT_SWITCH, - /// \brief A WhileStmt record. + /// A WhileStmt record. STMT_WHILE, - /// \brief A DoStmt record. + /// A DoStmt record. STMT_DO, - /// \brief A ForStmt record. + /// A ForStmt record. STMT_FOR, - /// \brief A GotoStmt record. + /// A GotoStmt record. STMT_GOTO, - /// \brief An IndirectGotoStmt record. + /// An IndirectGotoStmt record. STMT_INDIRECT_GOTO, - /// \brief A ContinueStmt record. + /// A ContinueStmt record. STMT_CONTINUE, - /// \brief A BreakStmt record. + /// A BreakStmt record. STMT_BREAK, - /// \brief A ReturnStmt record. + /// A ReturnStmt record. STMT_RETURN, - /// \brief A DeclStmt record. + /// A DeclStmt record. STMT_DECL, - /// \brief A CapturedStmt record. + /// A CapturedStmt record. STMT_CAPTURED, - /// \brief A GCC-style AsmStmt record. + /// A GCC-style AsmStmt record. STMT_GCCASM, - /// \brief A MS-style AsmStmt record. + /// A MS-style AsmStmt record. STMT_MSASM, - /// \brief A PredefinedExpr record. + /// A PredefinedExpr record. EXPR_PREDEFINED, - /// \brief A DeclRefExpr record. + /// A DeclRefExpr record. EXPR_DECL_REF, - /// \brief An IntegerLiteral record. + /// An IntegerLiteral record. EXPR_INTEGER_LITERAL, - /// \brief A FloatingLiteral record. + /// A FloatingLiteral record. EXPR_FLOATING_LITERAL, - /// \brief An ImaginaryLiteral record. + /// An ImaginaryLiteral record. EXPR_IMAGINARY_LITERAL, - /// \brief A StringLiteral record. + /// A StringLiteral record. EXPR_STRING_LITERAL, - /// \brief A CharacterLiteral record. + /// A CharacterLiteral record. EXPR_CHARACTER_LITERAL, - /// \brief A ParenExpr record. + /// A ParenExpr record. EXPR_PAREN, - /// \brief A ParenListExpr record. + /// A ParenListExpr record. EXPR_PAREN_LIST, - /// \brief A UnaryOperator record. + /// A UnaryOperator record. EXPR_UNARY_OPERATOR, - /// \brief An OffsetOfExpr record. + /// An OffsetOfExpr record. EXPR_OFFSETOF, - /// \brief A SizefAlignOfExpr record. + /// A SizefAlignOfExpr record. EXPR_SIZEOF_ALIGN_OF, - /// \brief An ArraySubscriptExpr record. + /// An ArraySubscriptExpr record. EXPR_ARRAY_SUBSCRIPT, - /// \brief A CallExpr record. + /// A CallExpr record. EXPR_CALL, - /// \brief A MemberExpr record. + /// A MemberExpr record. EXPR_MEMBER, - /// \brief A BinaryOperator record. + /// A BinaryOperator record. EXPR_BINARY_OPERATOR, - /// \brief A CompoundAssignOperator record. + /// A CompoundAssignOperator record. EXPR_COMPOUND_ASSIGN_OPERATOR, - /// \brief A ConditionOperator record. + /// A ConditionOperator record. EXPR_CONDITIONAL_OPERATOR, - /// \brief An ImplicitCastExpr record. + /// An ImplicitCastExpr record. EXPR_IMPLICIT_CAST, - /// \brief A CStyleCastExpr record. + /// A CStyleCastExpr record. EXPR_CSTYLE_CAST, - /// \brief A CompoundLiteralExpr record. + /// A CompoundLiteralExpr record. EXPR_COMPOUND_LITERAL, - /// \brief An ExtVectorElementExpr record. + /// An ExtVectorElementExpr record. EXPR_EXT_VECTOR_ELEMENT, - /// \brief An InitListExpr record. + /// An InitListExpr record. EXPR_INIT_LIST, - /// \brief A DesignatedInitExpr record. + /// A DesignatedInitExpr record. EXPR_DESIGNATED_INIT, - /// \brief A DesignatedInitUpdateExpr record. + /// A DesignatedInitUpdateExpr record. EXPR_DESIGNATED_INIT_UPDATE, - /// \brief An NoInitExpr record. + /// An NoInitExpr record. EXPR_NO_INIT, - /// \brief An ArrayInitLoopExpr record. + /// An ArrayInitLoopExpr record. EXPR_ARRAY_INIT_LOOP, - /// \brief An ArrayInitIndexExpr record. + /// An ArrayInitIndexExpr record. EXPR_ARRAY_INIT_INDEX, - /// \brief An ImplicitValueInitExpr record. + /// An ImplicitValueInitExpr record. EXPR_IMPLICIT_VALUE_INIT, - /// \brief A VAArgExpr record. + /// A VAArgExpr record. EXPR_VA_ARG, - /// \brief An AddrLabelExpr record. + /// An AddrLabelExpr record. EXPR_ADDR_LABEL, - /// \brief A StmtExpr record. + /// A StmtExpr record. EXPR_STMT, - /// \brief A ChooseExpr record. + /// A ChooseExpr record. EXPR_CHOOSE, - /// \brief A GNUNullExpr record. + /// A GNUNullExpr record. EXPR_GNU_NULL, - /// \brief A ShuffleVectorExpr record. + /// A ShuffleVectorExpr record. EXPR_SHUFFLE_VECTOR, - /// \brief A ConvertVectorExpr record. + /// A ConvertVectorExpr record. EXPR_CONVERT_VECTOR, - /// \brief BlockExpr + /// BlockExpr EXPR_BLOCK, - /// \brief A GenericSelectionExpr record. + /// A GenericSelectionExpr record. EXPR_GENERIC_SELECTION, - /// \brief A PseudoObjectExpr record. + /// A PseudoObjectExpr record. EXPR_PSEUDO_OBJECT, - /// \brief An AtomicExpr record. + /// An AtomicExpr record. EXPR_ATOMIC, // Objective-C - /// \brief An ObjCStringLiteral record. + /// An ObjCStringLiteral record. EXPR_OBJC_STRING_LITERAL, EXPR_OBJC_BOXED_EXPRESSION, EXPR_OBJC_ARRAY_LITERAL, EXPR_OBJC_DICTIONARY_LITERAL, - /// \brief An ObjCEncodeExpr record. + /// An ObjCEncodeExpr record. EXPR_OBJC_ENCODE, - /// \brief An ObjCSelectorExpr record. + /// An ObjCSelectorExpr record. EXPR_OBJC_SELECTOR_EXPR, - /// \brief An ObjCProtocolExpr record. + /// An ObjCProtocolExpr record. EXPR_OBJC_PROTOCOL_EXPR, - /// \brief An ObjCIvarRefExpr record. + /// An ObjCIvarRefExpr record. EXPR_OBJC_IVAR_REF_EXPR, - /// \brief An ObjCPropertyRefExpr record. + /// An ObjCPropertyRefExpr record. EXPR_OBJC_PROPERTY_REF_EXPR, - /// \brief An ObjCSubscriptRefExpr record. + /// An ObjCSubscriptRefExpr record. EXPR_OBJC_SUBSCRIPT_REF_EXPR, - /// \brief UNUSED + /// UNUSED EXPR_OBJC_KVC_REF_EXPR, - /// \brief An ObjCMessageExpr record. + /// An ObjCMessageExpr record. EXPR_OBJC_MESSAGE_EXPR, - /// \brief An ObjCIsa Expr record. + /// An ObjCIsa Expr record. EXPR_OBJC_ISA, - /// \brief An ObjCIndirectCopyRestoreExpr record. + /// An ObjCIndirectCopyRestoreExpr record. EXPR_OBJC_INDIRECT_COPY_RESTORE, - /// \brief An ObjCForCollectionStmt record. + /// An ObjCForCollectionStmt record. STMT_OBJC_FOR_COLLECTION, - /// \brief An ObjCAtCatchStmt record. + /// An ObjCAtCatchStmt record. STMT_OBJC_CATCH, - /// \brief An ObjCAtFinallyStmt record. + /// An ObjCAtFinallyStmt record. STMT_OBJC_FINALLY, - /// \brief An ObjCAtTryStmt record. + /// An ObjCAtTryStmt record. STMT_OBJC_AT_TRY, - /// \brief An ObjCAtSynchronizedStmt record. + /// An ObjCAtSynchronizedStmt record. STMT_OBJC_AT_SYNCHRONIZED, - /// \brief An ObjCAtThrowStmt record. + /// An ObjCAtThrowStmt record. STMT_OBJC_AT_THROW, - /// \brief An ObjCAutoreleasePoolStmt record. + /// An ObjCAutoreleasePoolStmt record. STMT_OBJC_AUTORELEASE_POOL, - /// \brief An ObjCBoolLiteralExpr record. + /// An ObjCBoolLiteralExpr record. EXPR_OBJC_BOOL_LITERAL, - /// \brief An ObjCAvailabilityCheckExpr record. + /// An ObjCAvailabilityCheckExpr record. EXPR_OBJC_AVAILABILITY_CHECK, // C++ - /// \brief A CXXCatchStmt record. + /// A CXXCatchStmt record. STMT_CXX_CATCH, - /// \brief A CXXTryStmt record. + /// A CXXTryStmt record. STMT_CXX_TRY, - /// \brief A CXXForRangeStmt record. + /// A CXXForRangeStmt record. STMT_CXX_FOR_RANGE, - /// \brief A CXXOperatorCallExpr record. + /// A CXXOperatorCallExpr record. EXPR_CXX_OPERATOR_CALL, - /// \brief A CXXMemberCallExpr record. + /// A CXXMemberCallExpr record. EXPR_CXX_MEMBER_CALL, - /// \brief A CXXConstructExpr record. + /// A CXXConstructExpr record. EXPR_CXX_CONSTRUCT, - /// \brief A CXXInheritedCtorInitExpr record. + /// A CXXInheritedCtorInitExpr record. EXPR_CXX_INHERITED_CTOR_INIT, - /// \brief A CXXTemporaryObjectExpr record. + /// A CXXTemporaryObjectExpr record. EXPR_CXX_TEMPORARY_OBJECT, - /// \brief A CXXStaticCastExpr record. + /// A CXXStaticCastExpr record. EXPR_CXX_STATIC_CAST, - /// \brief A CXXDynamicCastExpr record. + /// A CXXDynamicCastExpr record. EXPR_CXX_DYNAMIC_CAST, - /// \brief A CXXReinterpretCastExpr record. + /// A CXXReinterpretCastExpr record. EXPR_CXX_REINTERPRET_CAST, - /// \brief A CXXConstCastExpr record. + /// A CXXConstCastExpr record. EXPR_CXX_CONST_CAST, - /// \brief A CXXFunctionalCastExpr record. + /// A CXXFunctionalCastExpr record. EXPR_CXX_FUNCTIONAL_CAST, - /// \brief A UserDefinedLiteral record. + /// A UserDefinedLiteral record. EXPR_USER_DEFINED_LITERAL, - /// \brief A CXXStdInitializerListExpr record. + /// A CXXStdInitializerListExpr record. EXPR_CXX_STD_INITIALIZER_LIST, - /// \brief A CXXBoolLiteralExpr record. + /// A CXXBoolLiteralExpr record. EXPR_CXX_BOOL_LITERAL, EXPR_CXX_NULL_PTR_LITERAL, // CXXNullPtrLiteralExpr @@ -1865,24 +1965,24 @@ namespace serialization { EXPR_DEPENDENT_COAWAIT, }; - /// \brief The kinds of designators that can occur in a + /// The kinds of designators that can occur in a /// DesignatedInitExpr. enum DesignatorTypes { - /// \brief Field designator where only the field name is known. + /// Field designator where only the field name is known. DESIG_FIELD_NAME = 0, - /// \brief Field designator where the field has been resolved to + /// Field designator where the field has been resolved to /// a declaration. DESIG_FIELD_DECL = 1, - /// \brief Array designator. + /// Array designator. DESIG_ARRAY = 2, - /// \brief GNU array range designator. + /// GNU array range designator. DESIG_ARRAY_RANGE = 3 }; - /// \brief The different kinds of data that can occur in a + /// The different kinds of data that can occur in a /// CtorInitializer. enum CtorInitializerType { CTOR_INITIALIZER_BASE, @@ -1891,7 +1991,7 @@ namespace serialization { CTOR_INITIALIZER_INDIRECT_MEMBER }; - /// \brief Describes the redeclarations of a declaration. + /// Describes the redeclarations of a declaration. struct LocalRedeclarationsInfo { // The ID of the first declaration DeclID FirstID; @@ -1920,7 +2020,7 @@ namespace serialization { } }; - /// \brief Describes the categories of an Objective-C class. + /// Describes the categories of an Objective-C class. struct ObjCCategoriesInfo { // The ID of the definition DeclID DefinitionID; @@ -1949,7 +2049,7 @@ namespace serialization { } }; - /// \brief A key used when looking up entities by \ref DeclarationName. + /// A key used when looking up entities by \ref DeclarationName. /// /// Different \ref DeclarationNames are mapped to different keys, but the /// same key can occasionally represent multiple names (for names that diff --git a/include/clang/Serialization/ASTDeserializationListener.h b/include/clang/Serialization/ASTDeserializationListener.h index c26f3e0b425e4..c462a90dde549 100644 --- a/include/clang/Serialization/ASTDeserializationListener.h +++ b/include/clang/Serialization/ASTDeserializationListener.h @@ -32,28 +32,28 @@ class ASTDeserializationListener { public: virtual ~ASTDeserializationListener(); - /// \brief The ASTReader was initialized. + /// The ASTReader was initialized. virtual void ReaderInitialized(ASTReader *Reader) { } - /// \brief An identifier was deserialized from the AST file. + /// An identifier was deserialized from the AST file. virtual void IdentifierRead(serialization::IdentID ID, IdentifierInfo *II) { } - /// \brief A macro was read from the AST file. + /// A macro was read from the AST file. virtual void MacroRead(serialization::MacroID ID, MacroInfo *MI) { } - /// \brief A type was deserialized from the AST file. The ID here has the + /// A type was deserialized from the AST file. The ID here has the /// qualifier bits already removed, and T is guaranteed to be locally /// unqualified. virtual void TypeRead(serialization::TypeIdx Idx, QualType T) { } - /// \brief A decl was deserialized from the AST file. + /// A decl was deserialized from the AST file. virtual void DeclRead(serialization::DeclID ID, const Decl *D) { } - /// \brief A selector was read from the AST file. + /// A selector was read from the AST file. virtual void SelectorRead(serialization::SelectorID iD, Selector Sel) {} - /// \brief A macro definition was read from the AST file. + /// A macro definition was read from the AST file. virtual void MacroDefinitionRead(serialization::PreprocessedEntityID, MacroDefinitionRecord *MD) {} - /// \brief A module definition was read from the AST file. + /// A module definition was read from the AST file. virtual void ModuleRead(serialization::SubmoduleID ID, Module *Mod) {} - /// \brief A module import was read from the AST file. + /// A module import was read from the AST file. virtual void ModuleImportRead(serialization::SubmoduleID ID, SourceLocation ImportLoc) {} }; diff --git a/include/clang/Serialization/ASTReader.h b/include/clang/Serialization/ASTReader.h index 37920fc143ea7..82a74a64443d6 100644 --- a/include/clang/Serialization/ASTReader.h +++ b/include/clang/Serialization/ASTReader.h @@ -14,20 +14,20 @@ #ifndef LLVM_CLANG_SERIALIZATION_ASTREADER_H #define LLVM_CLANG_SERIALIZATION_ASTREADER_H +#include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclarationName.h" +#include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/TemplateBase.h" #include "clang/AST/TemplateName.h" #include "clang/AST/Type.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/DiagnosticOptions.h" -#include "clang/Basic/FileSystemOptions.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/Module.h" #include "clang/Basic/OpenCLOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Version.h" -#include "clang/Basic/VersionTuple.h" #include "clang/Lex/ExternalPreprocessorSource.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/PreprocessingRecord.h" @@ -61,6 +61,7 @@ #include "llvm/Support/Endian.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Timer.h" +#include "llvm/Support/VersionTuple.h" #include <cassert> #include <cstddef> #include <cstdint> @@ -79,9 +80,6 @@ class ASTContext; class ASTDeserializationListener; class ASTReader; class ASTRecordReader; -class CXXBaseSpecifier; -class CXXConstructorDecl; -class CXXCtorInitializer; class CXXTemporary; class Decl; class DeclaratorDecl; @@ -102,7 +100,6 @@ class MacroInfo; class MemoryBufferCache; class NamedDecl; class NamespaceDecl; -class NestedNameSpecifier; class ObjCCategoryDecl; class ObjCInterfaceDecl; class PCHContainerReader; @@ -120,7 +117,7 @@ class TypeSourceInfo; class ValueDecl; class VarDecl; -/// \brief Abstract interface for callback invocations by the ASTReader. +/// Abstract interface for callback invocations by the ASTReader. /// /// While reading an AST file, the ASTReader will call the methods of the /// listener to pass on specific information. Some of the listener methods can @@ -130,7 +127,7 @@ class ASTReaderListener { public: virtual ~ASTReaderListener(); - /// \brief Receives the full Clang version information. + /// Receives the full Clang version information. /// /// \returns true to indicate that the version is invalid. Subclasses should /// generally defer to this implementation. @@ -141,7 +138,7 @@ public: virtual void ReadModuleName(StringRef ModuleName) {} virtual void ReadModuleMapFile(StringRef ModuleMapPath) {} - /// \brief Receives the language options. + /// Receives the language options. /// /// \returns true to indicate the options are invalid or false otherwise. virtual bool ReadLanguageOptions(const LangOptions &LangOpts, @@ -150,7 +147,7 @@ public: return false; } - /// \brief Receives the target options. + /// Receives the target options. /// /// \returns true to indicate the target options are invalid, or false /// otherwise. @@ -159,7 +156,7 @@ public: return false; } - /// \brief Receives the diagnostic options. + /// Receives the diagnostic options. /// /// \returns true to indicate the diagnostic options are invalid, or false /// otherwise. @@ -169,7 +166,7 @@ public: return false; } - /// \brief Receives the file system options. + /// Receives the file system options. /// /// \returns true to indicate the file system options are invalid, or false /// otherwise. @@ -178,7 +175,7 @@ public: return false; } - /// \brief Receives the header search options. + /// Receives the header search options. /// /// \returns true to indicate the header search options are invalid, or false /// otherwise. @@ -188,7 +185,7 @@ public: return false; } - /// \brief Receives the preprocessor options. + /// Receives the preprocessor options. /// /// \param SuggestedPredefines Can be filled in with the set of predefines /// that are suggested by the preprocessor options. Typically only used when @@ -202,7 +199,7 @@ public: return false; } - /// \brief Receives __COUNTER__ value. + /// Receives __COUNTER__ value. virtual void ReadCounter(const serialization::ModuleFile &M, unsigned Value) {} @@ -210,15 +207,15 @@ public: virtual void visitModuleFile(StringRef Filename, serialization::ModuleKind Kind) {} - /// \brief Returns true if this \c ASTReaderListener wants to receive the + /// Returns true if this \c ASTReaderListener wants to receive the /// input files of the AST file via \c visitInputFile, false otherwise. virtual bool needsInputFileVisitation() { return false; } - /// \brief Returns true if this \c ASTReaderListener wants to receive the + /// Returns true if this \c ASTReaderListener wants to receive the /// system input files of the AST file via \c visitInputFile, false otherwise. virtual bool needsSystemInputFileVisitation() { return false; } - /// \brief if \c needsInputFileVisitation returns true, this is called for + /// if \c needsInputFileVisitation returns true, this is called for /// each non-system input file of the AST File. If /// \c needsSystemInputFileVisitation is true, then it is called for all /// system input files as well. @@ -229,11 +226,11 @@ public: return true; } - /// \brief Returns true if this \c ASTReaderListener wants to receive the + /// 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 + /// If needsImportVisitation returns \c true, this is called for each /// AST file imported by this AST file. virtual void visitImport(StringRef Filename) {} @@ -242,7 +239,7 @@ public: const ModuleFileExtensionMetadata &Metadata) {} }; -/// \brief Simple wrapper class for chaining listeners. +/// Simple wrapper class for chaining listeners. class ChainedASTReaderListener : public ASTReaderListener { std::unique_ptr<ASTReaderListener> First; std::unique_ptr<ASTReaderListener> Second; @@ -286,7 +283,7 @@ public: const ModuleFileExtensionMetadata &Metadata) override; }; -/// \brief ASTReaderListener implementation to validate the information of +/// ASTReaderListener implementation to validate the information of /// the PCH file against an initialized Preprocessor. class PCHValidator : public ASTReaderListener { Preprocessor &PP; @@ -294,7 +291,7 @@ class PCHValidator : public ASTReaderListener { public: PCHValidator(Preprocessor &PP, ASTReader &Reader) - : PP(PP), Reader(Reader) {} + : PP(PP), Reader(Reader) {} bool ReadLanguageOptions(const LangOptions &LangOpts, bool Complain, bool AllowCompatibleDifferences) override; @@ -313,7 +310,7 @@ private: void Error(const char *Msg); }; -/// \brief ASTReaderListenter implementation to set SuggestedPredefines of +/// ASTReaderListenter implementation to set SuggestedPredefines of /// ASTReader which is required to use a pch file. This is the replacement /// of PCHValidator or SimplePCHValidator when using a pch file without /// validating it. @@ -321,8 +318,7 @@ class SimpleASTReaderListener : public ASTReaderListener { Preprocessor &PP; public: - SimpleASTReaderListener(Preprocessor &PP) - : PP(PP) {} + SimpleASTReaderListener(Preprocessor &PP) : PP(PP) {} bool ReadPreprocessorOptions(const PreprocessorOptions &PPOpts, bool Complain, std::string &SuggestedPredefines) override; @@ -336,14 +332,14 @@ namespace reader { class ASTIdentifierLookupTrait; -/// \brief The on-disk hash table(s) used for DeclContext name lookup. +/// The on-disk hash table(s) used for DeclContext name lookup. struct DeclContextLookupTable; } // namespace reader } // namespace serialization -/// \brief Reads an AST files chain containing the contents of a translation +/// Reads an AST files chain containing the contents of a translation /// unit. /// /// The ASTReader class reads bitstreams (produced by the ASTWriter @@ -364,7 +360,7 @@ class ASTReader public ExternalSLocEntrySource { public: - /// \brief Types of AST files. + /// Types of AST files. friend class ASTDeclReader; friend class ASTIdentifierIterator; friend class ASTRecordReader; @@ -379,31 +375,31 @@ public: using RecordData = SmallVector<uint64_t, 64>; using RecordDataImpl = SmallVectorImpl<uint64_t>; - /// \brief The result of reading the control block of an AST file, which + /// The result of reading the control block of an AST file, which /// can fail for various reasons. enum ASTReadResult { - /// \brief The control block was read successfully. Aside from failures, + /// The control block was read successfully. Aside from failures, /// the AST file is safe to read into the current context. Success, - /// \brief The AST file itself appears corrupted. + /// The AST file itself appears corrupted. Failure, - /// \brief The AST file was missing. + /// The AST file was missing. Missing, - /// \brief The AST file is out-of-date relative to its input files, + /// The AST file is out-of-date relative to its input files, /// and needs to be regenerated. OutOfDate, - /// \brief The AST file was written by a different version of Clang. + /// The AST file was written by a different version of Clang. VersionMismatch, - /// \brief The AST file was writtten with a different language/target + /// The AST file was writtten with a different language/target /// configuration. ConfigurationMismatch, - /// \brief The AST file has errors. + /// The AST file has errors. HadErrors }; @@ -415,10 +411,10 @@ public: using ModuleReverseIterator = ModuleManager::ModuleReverseIterator; private: - /// \brief The receiver of some callbacks invoked by ASTReader. + /// The receiver of some callbacks invoked by ASTReader. std::unique_ptr<ASTReaderListener> Listener; - /// \brief The receiver of deserialization events. + /// The receiver of deserialization events. ASTDeserializationListener *DeserializationListener = nullptr; bool OwnsDeserializationListener = false; @@ -428,26 +424,26 @@ private: const PCHContainerReader &PCHContainerRdr; DiagnosticsEngine &Diags; - /// \brief The semantic analysis object that will be processing the + /// The semantic analysis object that will be processing the /// AST files and the translation unit that uses it. Sema *SemaObj = nullptr; - /// \brief The preprocessor that will be loading the source file. + /// The preprocessor that will be loading the source file. Preprocessor &PP; - /// \brief The AST context into which we'll read the AST files. + /// The AST context into which we'll read the AST files. ASTContext *ContextObj = nullptr; - /// \brief The AST consumer. + /// The AST consumer. ASTConsumer *Consumer = nullptr; - /// \brief The module manager which manages modules and their dependencies + /// The module manager which manages modules and their dependencies ModuleManager ModuleMgr; /// The cache that manages memory buffers for PCM files. MemoryBufferCache &PCMCache; - /// \brief A dummy identifier resolver used to merge TU-scope declarations in + /// A dummy identifier resolver used to merge TU-scope declarations in /// C, for the cases where we don't have a Sema object to provide a real /// identifier resolver. IdentifierResolver DummyIdResolver; @@ -455,31 +451,31 @@ private: /// A mapping from extension block names to module file extensions. llvm::StringMap<std::shared_ptr<ModuleFileExtension>> ModuleFileExtensions; - /// \brief A timer used to track the time spent deserializing. + /// A timer used to track the time spent deserializing. std::unique_ptr<llvm::Timer> ReadTimer; - /// \brief The location where the module file will be considered as + /// The location where the module file will be considered as /// imported from. For non-module AST types it should be invalid. SourceLocation CurrentImportLoc; - /// \brief The global module index, if loaded. + /// The global module index, if loaded. std::unique_ptr<GlobalModuleIndex> GlobalIndex; - /// \brief A map of global bit offsets to the module that stores entities + /// A map of global bit offsets to the module that stores entities /// at those bit offsets. ContinuousRangeMap<uint64_t, ModuleFile*, 4> GlobalBitOffsetsMap; - /// \brief A map of negated SLocEntryIDs to the modules containing them. + /// A map of negated SLocEntryIDs to the modules containing them. ContinuousRangeMap<unsigned, ModuleFile*, 64> GlobalSLocEntryMap; using GlobalSLocOffsetMapType = ContinuousRangeMap<unsigned, ModuleFile *, 64>; - /// \brief A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset) + /// A map of reversed (SourceManager::MaxLoadedOffset - SLocOffset) /// SourceLocation offsets to the modules containing them. GlobalSLocOffsetMapType GlobalSLocOffsetMap; - /// \brief Types that have already been loaded from the chain. + /// Types that have already been loaded from the chain. /// /// When the pointer at index I is non-NULL, the type with /// ID = (I + 1) << FastQual::Width has already been loaded @@ -488,12 +484,12 @@ private: using GlobalTypeMapType = ContinuousRangeMap<serialization::TypeID, ModuleFile *, 4>; - /// \brief Mapping from global type IDs to the module in which the + /// Mapping from global type IDs to the module in which the /// type resides along with the offset that should be added to the /// global type ID to produce a local ID. GlobalTypeMapType GlobalTypeMap; - /// \brief Declarations that have already been loaded from the chain. + /// Declarations that have already been loaded from the chain. /// /// When the pointer at index I is non-NULL, the declaration with ID /// = I + 1 has already been loaded. @@ -502,7 +498,7 @@ private: using GlobalDeclMapType = ContinuousRangeMap<serialization::DeclID, ModuleFile *, 4>; - /// \brief Mapping from global declaration IDs to the module in which the + /// Mapping from global declaration IDs to the module in which the /// declaration resides. GlobalDeclMapType GlobalDeclMap; @@ -511,7 +507,7 @@ private: using DeclUpdateOffsetsMap = llvm::DenseMap<serialization::DeclID, FileOffsetsTy>; - /// \brief Declarations that have modifications residing in a later file + /// Declarations that have modifications residing in a later file /// in the chain. DeclUpdateOffsetsMap DeclUpdateOffsets; @@ -527,30 +523,30 @@ private: : D(D), ID(ID), JustLoaded(JustLoaded) {} }; - /// \brief Declaration updates for already-loaded declarations that we need + /// Declaration updates for already-loaded declarations that we need /// to apply once we finish processing an import. llvm::SmallVector<PendingUpdateRecord, 16> PendingUpdateRecords; enum class PendingFakeDefinitionKind { NotFake, Fake, FakeLoaded }; - /// \brief The DefinitionData pointers that we faked up for class definitions + /// The DefinitionData pointers that we faked up for class definitions /// that we needed but hadn't loaded yet. llvm::DenseMap<void *, PendingFakeDefinitionKind> PendingFakeDefinitionData; - /// \brief Exception specification updates that have been loaded but not yet + /// Exception specification updates that have been loaded but not yet /// propagated across the relevant redeclaration chain. The map key is the /// canonical declaration (used only for deduplication) and the value is a /// declaration that has an exception specification. llvm::SmallMapVector<Decl *, FunctionDecl *, 4> PendingExceptionSpecUpdates; - /// \brief Declarations that have been imported and have typedef names for + /// 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 + /// Mergeable declaration contexts that have anonymous declarations /// within them, and those anonymous declarations. - llvm::DenseMap<DeclContext*, llvm::SmallVector<NamedDecl*, 2>> + llvm::DenseMap<Decl*, llvm::SmallVector<NamedDecl*, 2>> AnonymousDeclarationsForMerging; struct FileDeclsInfo { @@ -559,24 +555,24 @@ private: FileDeclsInfo() = default; FileDeclsInfo(ModuleFile *Mod, ArrayRef<serialization::LocalDeclID> Decls) - : Mod(Mod), Decls(Decls) {} + : Mod(Mod), Decls(Decls) {} }; - /// \brief Map from a FileID to the file-level declarations that it contains. + /// Map from a FileID to the file-level declarations that it contains. llvm::DenseMap<FileID, FileDeclsInfo> FileDeclIDs; - /// \brief An array of lexical contents of a declaration context, as a sequence of + /// An array of lexical contents of a declaration context, as a sequence of /// Decl::Kind, DeclID pairs. using LexicalContents = ArrayRef<llvm::support::unaligned_uint32_t>; - /// \brief Map from a DeclContext to its lexical contents. + /// Map from a DeclContext to its lexical contents. llvm::DenseMap<const DeclContext*, std::pair<ModuleFile*, LexicalContents>> LexicalDecls; - /// \brief Map from the TU to its lexical contents from each module file. + /// Map from the TU to its lexical contents from each module file. std::vector<std::pair<ModuleFile*, LexicalContents>> TULexicalDecls; - /// \brief Map from a DeclContext to its lookup tables. + /// Map from a DeclContext to its lookup tables. llvm::DenseMap<const DeclContext *, serialization::reader::DeclContextLookupTable> Lookups; @@ -590,12 +586,12 @@ private: }; using DeclContextVisibleUpdates = SmallVector<PendingVisibleUpdate, 1>; - /// \brief Updates to the visible declarations of declaration contexts that + /// Updates to the visible declarations of declaration contexts that /// haven't been loaded yet. llvm::DenseMap<serialization::DeclID, DeclContextVisibleUpdates> PendingVisibleUpdates; - /// \brief The set of C++ or Objective-C classes that have forward + /// The set of C++ or Objective-C classes that have forward /// declarations that have not yet been linked to their definitions. llvm::SmallPtrSet<Decl *, 4> PendingDefinitions; @@ -604,24 +600,24 @@ private: llvm::SmallDenseMap<Decl *, unsigned, 4>, SmallVector<std::pair<Decl *, uint64_t>, 4>>; - /// \brief Functions or methods that have bodies that will be attached. + /// Functions or methods that have bodies that will be attached. PendingBodiesMap PendingBodies; - /// \brief Definitions for which we have added merged definitions but not yet + /// Definitions for which we have added merged definitions but not yet /// performed deduplication. llvm::SetVector<NamedDecl *> PendingMergedDefinitionsToDeduplicate; - /// \brief Read the record that describes the lexical contents of a DC. + /// Read the record that describes the lexical contents of a DC. bool ReadLexicalDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, uint64_t Offset, DeclContext *DC); - /// \brief Read the record that describes the visible contents of a DC. + /// Read the record that describes the visible contents of a DC. bool ReadVisibleDeclContextStorage(ModuleFile &M, llvm::BitstreamCursor &Cursor, uint64_t Offset, serialization::DeclID ID); - /// \brief A vector containing identifiers that have already been + /// A vector containing identifiers that have already been /// loaded. /// /// If the pointer at index I is non-NULL, then it refers to the @@ -632,12 +628,12 @@ private: using GlobalIdentifierMapType = ContinuousRangeMap<serialization::IdentID, ModuleFile *, 4>; - /// \brief Mapping from global identifier IDs to the module in which the + /// Mapping from global identifier IDs to the module in which the /// identifier resides along with the offset that should be added to the /// global identifier ID to produce a local ID. GlobalIdentifierMapType GlobalIdentifierMap; - /// \brief A vector containing macros that have already been + /// A vector containing macros that have already been /// loaded. /// /// If the pointer at index I is non-NULL, then it refers to the @@ -648,7 +644,7 @@ private: using LoadedMacroInfo = std::pair<IdentifierInfo *, serialization::SubmoduleID>; - /// \brief A set of #undef directives that we have loaded; used to + /// A set of #undef directives that we have loaded; used to /// deduplicate the same #undef information coming from multiple module /// files. llvm::DenseSet<LoadedMacroInfo> LoadedUndefs; @@ -656,12 +652,12 @@ private: using GlobalMacroMapType = ContinuousRangeMap<serialization::MacroID, ModuleFile *, 4>; - /// \brief Mapping from global macro IDs to the module in which the + /// Mapping from global macro IDs to the module in which the /// macro resides along with the offset that should be added to the /// global macro ID to produce a local ID. GlobalMacroMapType GlobalMacroMap; - /// \brief A vector containing submodules that have already been loaded. + /// A vector containing submodules that have already been loaded. /// /// This vector is indexed by the Submodule ID (-1). NULL submodule entries /// indicate that the particular submodule ID has not yet been loaded. @@ -670,45 +666,45 @@ private: using GlobalSubmoduleMapType = ContinuousRangeMap<serialization::SubmoduleID, ModuleFile *, 4>; - /// \brief Mapping from global submodule IDs to the module file in which the + /// Mapping from global submodule IDs to the module file in which the /// submodule resides along with the offset that should be added to the /// global submodule ID to produce a local ID. GlobalSubmoduleMapType GlobalSubmoduleMap; - /// \brief A set of hidden declarations. + /// A set of hidden declarations. using HiddenNames = SmallVector<Decl *, 2>; using HiddenNamesMapType = llvm::DenseMap<Module *, HiddenNames>; - /// \brief A mapping from each of the hidden submodules to the deserialized + /// A mapping from each of the hidden submodules to the deserialized /// declarations in that submodule that could be made visible. HiddenNamesMapType HiddenNamesMap; - /// \brief A module import, export, or conflict that hasn't yet been resolved. + /// A module import, export, or conflict that hasn't yet been resolved. struct UnresolvedModuleRef { - /// \brief The file in which this module resides. + /// The file in which this module resides. ModuleFile *File; - /// \brief The module that is importing or exporting. + /// The module that is importing or exporting. Module *Mod; - /// \brief The kind of module reference. + /// The kind of module reference. enum { Import, Export, Conflict } Kind; - /// \brief The local ID of the module that is being exported. + /// The local ID of the module that is being exported. unsigned ID; - /// \brief Whether this is a wildcard export. + /// Whether this is a wildcard export. unsigned IsWildcard : 1; - /// \brief String data. + /// String data. StringRef String; }; - /// \brief The set of module imports and exports that still need to be + /// The set of module imports and exports that still need to be /// resolved. SmallVector<UnresolvedModuleRef, 2> UnresolvedModuleRefs; - /// \brief A vector containing selectors that have already been loaded. + /// A vector containing selectors that have already been loaded. /// /// This vector is indexed by the Selector ID (-1). NULL selector /// entries indicate that the particular selector ID has not yet @@ -718,11 +714,11 @@ private: using GlobalSelectorMapType = ContinuousRangeMap<serialization::SelectorID, ModuleFile *, 4>; - /// \brief Mapping from global selector IDs to the module in which the + /// Mapping from global selector IDs to the module in which the /// global selector ID to produce a local ID. GlobalSelectorMapType GlobalSelectorMap; - /// \brief The generation number of the last time we loaded data from the + /// The generation number of the last time we loaded data from the /// global method pool for this selector. llvm::DenseMap<Selector, unsigned> SelectorGeneration; @@ -741,23 +737,30 @@ private: using PendingMacroIDsMap = llvm::MapVector<IdentifierInfo *, SmallVector<PendingMacroInfo, 2>>; - /// \brief Mapping from identifiers that have a macro history to the global + /// Mapping from identifiers that have a macro history to the global /// IDs have not yet been deserialized to the global IDs of those macros. PendingMacroIDsMap PendingMacroIDs; using GlobalPreprocessedEntityMapType = ContinuousRangeMap<unsigned, ModuleFile *, 4>; - /// \brief Mapping from global preprocessing entity IDs to the module in + /// Mapping from global preprocessing entity IDs to the module in /// which the preprocessed entity resides along with the offset that should be /// added to the global preprocessing entity ID to produce a local ID. GlobalPreprocessedEntityMapType GlobalPreprocessedEntityMap; + using GlobalSkippedRangeMapType = + ContinuousRangeMap<unsigned, ModuleFile *, 4>; + + /// Mapping from global skipped range base IDs to the module in which + /// the skipped ranges reside. + GlobalSkippedRangeMapType GlobalSkippedRangeMap; + /// \name CodeGen-relevant special data - /// \brief Fields containing data that is relevant to CodeGen. + /// Fields containing data that is relevant to CodeGen. //@{ - /// \brief The IDs of all declarations that fulfill the criteria of + /// The IDs of all declarations that fulfill the criteria of /// "interesting" decls. /// /// This contains the data loaded from all EAGERLY_DESERIALIZED_DECLS blocks @@ -765,21 +768,21 @@ private: /// the consumer eagerly. SmallVector<uint64_t, 16> EagerlyDeserializedDecls; - /// \brief The IDs of all tentative definitions stored in the chain. + /// The IDs of all tentative definitions stored in the chain. /// /// Sema keeps track of all tentative definitions in a TU because it has to /// complete them and pass them on to CodeGen. Thus, tentative definitions in /// the PCH chain must be eagerly deserialized. SmallVector<uint64_t, 16> TentativeDefinitions; - /// \brief The IDs of all CXXRecordDecls stored in the chain whose VTables are + /// The IDs of all CXXRecordDecls stored in the chain whose VTables are /// used. /// /// CodeGen has to emit VTables for these records, so they have to be eagerly /// deserialized. SmallVector<uint64_t, 64> VTableUses; - /// \brief A snapshot of the pending instantiations in the chain. + /// A snapshot of the pending instantiations in the chain. /// /// This record tracks the instantiations that Sema has to perform at the /// end of the TU. It consists of a pair of values for every pending @@ -790,26 +793,26 @@ private: //@} /// \name DiagnosticsEngine-relevant special data - /// \brief Fields containing data that is used for generating diagnostics + /// Fields containing data that is used for generating diagnostics //@{ - /// \brief A snapshot of Sema's unused file-scoped variable tracking, for + /// A snapshot of Sema's unused file-scoped variable tracking, for /// generating warnings. SmallVector<uint64_t, 16> UnusedFileScopedDecls; - /// \brief A list of all the delegating constructors we've seen, to diagnose + /// A list of all the delegating constructors we've seen, to diagnose /// cycles. SmallVector<uint64_t, 4> DelegatingCtorDecls; - /// \brief Method selectors used in a @selector expression. Used for + /// Method selectors used in a @selector expression. Used for /// implementation of -Wselector. SmallVector<uint64_t, 64> ReferencedSelectorsData; - /// \brief A snapshot of Sema's weak undeclared identifier tracking, for + /// A snapshot of Sema's weak undeclared identifier tracking, for /// generating warnings. SmallVector<uint64_t, 64> WeakUndeclaredIdentifiers; - /// \brief The IDs of type aliases for ext_vectors that exist in the chain. + /// The IDs of type aliases for ext_vectors that exist in the chain. /// /// Used by Sema for finding sugared names for ext_vectors in diagnostics. SmallVector<uint64_t, 4> ExtVectorDecls; @@ -817,48 +820,48 @@ private: //@} /// \name Sema-relevant special data - /// \brief Fields containing data that is used for semantic analysis + /// Fields containing data that is used for semantic analysis //@{ - /// \brief The IDs of all potentially unused typedef names in the chain. + /// The IDs of all potentially unused typedef names in the chain. /// /// Sema tracks these to emit warnings. SmallVector<uint64_t, 16> UnusedLocalTypedefNameCandidates; - /// \brief Our current depth in #pragma cuda force_host_device begin/end + /// Our current depth in #pragma cuda force_host_device begin/end /// macros. unsigned ForceCUDAHostDeviceDepth = 0; - /// \brief The IDs of the declarations Sema stores directly. + /// The IDs of the declarations Sema stores directly. /// /// Sema tracks a few important decls, such as namespace std, directly. SmallVector<uint64_t, 4> SemaDeclRefs; - /// \brief The IDs of the types ASTContext stores directly. + /// The IDs of the types ASTContext stores directly. /// /// The AST context tracks a few important types, such as va_list, directly. SmallVector<uint64_t, 16> SpecialTypes; - /// \brief The IDs of CUDA-specific declarations ASTContext stores directly. + /// The IDs of CUDA-specific declarations ASTContext stores directly. /// /// The AST context tracks a few important decls, currently cudaConfigureCall, /// directly. SmallVector<uint64_t, 2> CUDASpecialDeclRefs; - /// \brief The floating point pragma option settings. + /// The floating point pragma option settings. SmallVector<uint64_t, 1> FPPragmaOptions; - /// \brief The pragma clang optimize location (if the pragma state is "off"). + /// The pragma clang optimize location (if the pragma state is "off"). SourceLocation OptimizeOffPragmaLocation; - /// \brief The PragmaMSStructKind pragma ms_struct state if set, or -1. + /// The PragmaMSStructKind pragma ms_struct state if set, or -1. int PragmaMSStructState = -1; - /// \brief The PragmaMSPointersToMembersKind pragma pointers_to_members state. + /// The PragmaMSPointersToMembersKind pragma pointers_to_members state. int PragmaMSPointersToMembersState = -1; SourceLocation PointersToMembersPragmaLocation; - /// \brief The pragma pack state. + /// The pragma pack state. Optional<unsigned> PragmaPackCurrentValue; SourceLocation PragmaPackCurrentLocation; struct PragmaPackStackEntry { @@ -870,26 +873,26 @@ private: llvm::SmallVector<PragmaPackStackEntry, 2> PragmaPackStack; llvm::SmallVector<std::string, 2> PragmaPackStrings; - /// \brief The OpenCL extension settings. + /// The OpenCL extension settings. OpenCLOptions OpenCLExtensions; - /// \brief Extensions required by an OpenCL type. + /// Extensions required by an OpenCL type. llvm::DenseMap<const Type *, std::set<std::string>> OpenCLTypeExtMap; - /// \brief Extensions required by an OpenCL declaration. + /// Extensions required by an OpenCL declaration. llvm::DenseMap<const Decl *, std::set<std::string>> OpenCLDeclExtMap; - /// \brief A list of the namespaces we've seen. + /// A list of the namespaces we've seen. SmallVector<uint64_t, 4> KnownNamespaces; - /// \brief A list of undefined decls with internal linkage followed by the + /// A list of undefined decls with internal linkage followed by the /// SourceLocation of a matching ODR-use. SmallVector<uint64_t, 8> UndefinedButUsed; - /// \brief Delete expressions to analyze at the end of translation unit. + /// Delete expressions to analyze at the end of translation unit. SmallVector<uint64_t, 8> DelayedDeleteExprs; - // \brief A list of late parsed template function data. + // A list of late parsed template function data. SmallVector<uint64_t, 1> LateParsedTemplates; public: @@ -898,45 +901,45 @@ public: SourceLocation ImportLoc; ImportedSubmodule(serialization::SubmoduleID ID, SourceLocation ImportLoc) - : ID(ID), ImportLoc(ImportLoc) {} + : ID(ID), ImportLoc(ImportLoc) {} }; private: - /// \brief A list of modules that were imported by precompiled headers or + /// A list of modules that were imported by precompiled headers or /// any other non-module AST file. SmallVector<ImportedSubmodule, 2> ImportedModules; //@} - /// \brief The system include root to be used when loading the + /// The system include root to be used when loading the /// precompiled header. std::string isysroot; - /// \brief Whether to disable the normal validation performed on precompiled + /// Whether to disable the normal validation performed on precompiled /// headers when they are loaded. bool DisableValidation; - /// \brief Whether to accept an AST file with compiler errors. + /// Whether to accept an AST file with compiler errors. bool AllowASTWithCompilerErrors; - /// \brief Whether to accept an AST file that has a different configuration + /// Whether to accept an AST file that has a different configuration /// from the current compiler instance. bool AllowConfigurationMismatch; - /// \brief Whether validate system input files. + /// Whether validate system input files. bool ValidateSystemInputs; - /// \brief Whether we are allowed to use the global module index. + /// Whether we are allowed to use the global module index. bool UseGlobalIndex; - /// \brief Whether we have tried loading the global module index yet. + /// Whether we have tried loading the global module index yet. bool TriedLoadingGlobalIndex = false; - ///\brief Whether we are currently processing update records. + ///Whether we are currently processing update records. bool ProcessingUpdateRecords = false; using SwitchCaseMapTy = llvm::DenseMap<unsigned, SwitchCase *>; - /// \brief Mapping from switch-case IDs in the chain to switch-case statements + /// Mapping from switch-case IDs in the chain to switch-case statements /// /// Statements usually don't have IDs, but switch cases need them, so that the /// switch statement can refer to them. @@ -944,56 +947,56 @@ private: SwitchCaseMapTy *CurrSwitchCaseStmts; - /// \brief The number of source location entries de-serialized from + /// The number of source location entries de-serialized from /// the PCH file. unsigned NumSLocEntriesRead = 0; - /// \brief The number of source location entries in the chain. + /// The number of source location entries in the chain. unsigned TotalNumSLocEntries = 0; - /// \brief The number of statements (and expressions) de-serialized + /// The number of statements (and expressions) de-serialized /// from the chain. unsigned NumStatementsRead = 0; - /// \brief The total number of statements (and expressions) stored + /// The total number of statements (and expressions) stored /// in the chain. unsigned TotalNumStatements = 0; - /// \brief The number of macros de-serialized from the chain. + /// The number of macros de-serialized from the chain. unsigned NumMacrosRead = 0; - /// \brief The total number of macros stored in the chain. + /// The total number of macros stored in the chain. unsigned TotalNumMacros = 0; - /// \brief The number of lookups into identifier tables. + /// The number of lookups into identifier tables. unsigned NumIdentifierLookups = 0; - /// \brief The number of lookups into identifier tables that succeed. + /// The number of lookups into identifier tables that succeed. unsigned NumIdentifierLookupHits = 0; - /// \brief The number of selectors that have been read. + /// The number of selectors that have been read. unsigned NumSelectorsRead = 0; - /// \brief The number of method pool entries that have been read. + /// The number of method pool entries that have been read. unsigned NumMethodPoolEntriesRead = 0; - /// \brief The number of times we have looked up a selector in the method + /// The number of times we have looked up a selector in the method /// pool. unsigned NumMethodPoolLookups = 0; - /// \brief The number of times we have looked up a selector in the method + /// The number of times we have looked up a selector in the method /// pool and found something. unsigned NumMethodPoolHits = 0; - /// \brief The number of times we have looked up a selector in the method + /// The number of times we have looked up a selector in the method /// pool within a specific module. unsigned NumMethodPoolTableLookups = 0; - /// \brief The number of times we have looked up a selector in the method + /// The number of times we have looked up a selector in the method /// pool within a specific module and found something. unsigned NumMethodPoolTableHits = 0; - /// \brief The total number of method pool entries in the selector table. + /// The total number of method pool entries in the selector table. unsigned TotalNumMethodPoolEntries = 0; /// Number of lexical decl contexts read/total. @@ -1005,16 +1008,16 @@ private: /// Total size of modules, in bits, currently loaded uint64_t TotalModulesSizeInBits = 0; - /// \brief Number of Decl/types that are currently deserializing. + /// Number of Decl/types that are currently deserializing. unsigned NumCurrentElementsDeserializing = 0; - /// \brief Set true while we are in the process of passing deserialized + /// Set true while we are in the process of passing deserialized /// "interesting" decls to consumer inside FinishedDeserializing(). /// This is used as a guard to avoid recursively repeating the process of /// passing decls to consumer. bool PassingDeclsToConsumer = false; - /// \brief The set of identifiers that were read while the AST reader was + /// The set of identifiers that were read while the AST reader was /// (recursively) loading declarations. /// /// The declarations on the identifier chain for these identifiers will be @@ -1022,12 +1025,12 @@ private: llvm::MapVector<IdentifierInfo *, SmallVector<uint32_t, 4>> PendingIdentifierInfos; - /// \brief The set of lookup results that we have faked in order to support + /// The set of lookup results that we have faked in order to support /// merging of partially deserialized decls but that we have not yet removed. llvm::SmallMapVector<IdentifierInfo *, SmallVector<NamedDecl*, 2>, 16> PendingFakeLookupResults; - /// \brief The generation number of each identifier, which keeps track of + /// The generation number of each identifier, which keeps track of /// the last time we loaded information about this identifier. llvm::DenseMap<IdentifierInfo *, unsigned> IdentifierGeneration; @@ -1045,7 +1048,7 @@ private: bool hasPendingBody() { return DeclHasPendingBody; } }; - /// \brief Contains declarations and definitions that could be + /// Contains declarations and definitions that could be /// "interesting" to the ASTConsumer, when we get that AST consumer. /// /// "Interesting" declarations are those that have data that may @@ -1053,16 +1056,16 @@ private: /// Objective-C protocols. std::deque<InterestingDecl> PotentiallyInterestingDecls; - /// \brief The list of redeclaration chains that still need to be + /// The list of redeclaration chains that still need to be /// reconstructed, and the local offset to the corresponding list /// of redeclarations. SmallVector<std::pair<Decl *, uint64_t>, 16> PendingDeclChains; - /// \brief The list of canonical declarations whose redeclaration chains + /// The list of canonical declarations whose redeclaration chains /// need to be marked as incomplete once we're done deserializing things. SmallVector<Decl *, 16> PendingIncompleteDeclChains; - /// \brief The Decl IDs for the Sema/Lexical DeclContext of a Decl that has + /// The Decl IDs for the Sema/Lexical DeclContext of a Decl that has /// been loaded but its DeclContext was not set yet. struct PendingDeclContextInfo { Decl *D; @@ -1070,14 +1073,14 @@ private: serialization::GlobalDeclID LexicalDC; }; - /// \brief The set of Decls that have been loaded but their DeclContexts are + /// The set of Decls that have been loaded but their DeclContexts are /// not set yet. /// /// The DeclContexts for these Decls will be set once recursive loading has /// been completed. std::deque<PendingDeclContextInfo> PendingDeclContextInfos; - /// \brief The set of NamedDecls that have been loaded, but are members of a + /// The set of NamedDecls that have been loaded, but are members of a /// context that has been merged into another context where the corresponding /// declaration is either missing or has not yet been loaded. /// @@ -1088,22 +1091,26 @@ private: using DataPointers = std::pair<CXXRecordDecl *, struct CXXRecordDecl::DefinitionData *>; - /// \brief Record definitions in which we found an ODR violation. + /// Record definitions in which we found an ODR violation. llvm::SmallDenseMap<CXXRecordDecl *, llvm::SmallVector<DataPointers, 2>, 2> PendingOdrMergeFailures; - /// \brief Function definitions in which we found an ODR violation. + /// Function definitions in which we found an ODR violation. llvm::SmallDenseMap<FunctionDecl *, llvm::SmallVector<FunctionDecl *, 2>, 2> PendingFunctionOdrMergeFailures; - /// \brief DeclContexts in which we have diagnosed an ODR violation. + /// Enum definitions in which we found an ODR violation. + llvm::SmallDenseMap<EnumDecl *, llvm::SmallVector<EnumDecl *, 2>, 2> + PendingEnumOdrMergeFailures; + + /// DeclContexts in which we have diagnosed an ODR violation. llvm::SmallPtrSet<DeclContext*, 2> DiagnosedOdrMergeFailures; - /// \brief The set of Objective-C categories that have been deserialized + /// The set of Objective-C categories that have been deserialized /// since the last time the declaration chains were linked. llvm::SmallPtrSet<ObjCCategoryDecl *, 16> CategoriesDeserialized; - /// \brief The set of Objective-C class definitions that have already been + /// The set of Objective-C class definitions that have already been /// loaded, for which we will need to check for categories whenever a new /// module is loaded. SmallVector<ObjCInterfaceDecl *, 16> ObjCClassesLoaded; @@ -1111,41 +1118,41 @@ private: using KeyDeclsMap = llvm::DenseMap<Decl *, SmallVector<serialization::DeclID, 2>>; - /// \brief A mapping from canonical declarations to the set of global + /// A mapping from canonical declarations to the set of global /// declaration IDs for key declaration that have been merged with that /// canonical declaration. A key declaration is a formerly-canonical /// declaration whose module did not import any other key declaration for that /// entity. These are the IDs that we use as keys when finding redecl chains. KeyDeclsMap KeyDecls; - /// \brief A mapping from DeclContexts to the semantic DeclContext that we + /// A mapping from DeclContexts to the semantic DeclContext that we /// are treating as the definition of the entity. This is used, for instance, /// when merging implicit instantiations of class templates across modules. llvm::DenseMap<DeclContext *, DeclContext *> MergedDeclContexts; - /// \brief A mapping from canonical declarations of enums to their canonical + /// A mapping from canonical declarations of enums to their canonical /// definitions. Only populated when using modules in C++. llvm::DenseMap<EnumDecl *, EnumDecl *> EnumDefinitions; - /// \brief When reading a Stmt tree, Stmt operands are placed in this stack. + /// When reading a Stmt tree, Stmt operands are placed in this stack. SmallVector<Stmt *, 16> StmtStack; - /// \brief What kind of records we are reading. + /// What kind of records we are reading. enum ReadingKind { Read_None, Read_Decl, Read_Type, Read_Stmt }; - /// \brief What kind of records we are reading. + /// What kind of records we are reading. ReadingKind ReadingKind = Read_None; - /// \brief RAII object to change the reading kind. + /// RAII object to change the reading kind. class ReadingKindTracker { ASTReader &Reader; enum ReadingKind PrevKind; public: ReadingKindTracker(enum ReadingKind newKind, ASTReader &reader) - : Reader(reader), PrevKind(Reader.ReadingKind) { + : Reader(reader), PrevKind(Reader.ReadingKind) { Reader.ReadingKind = newKind; } @@ -1154,14 +1161,14 @@ private: ~ReadingKindTracker() { Reader.ReadingKind = PrevKind; } }; - /// \brief RAII object to mark the start of processing updates. + /// RAII object to mark the start of processing updates. class ProcessingUpdatesRAIIObj { ASTReader &Reader; bool PrevState; public: ProcessingUpdatesRAIIObj(ASTReader &reader) - : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) { + : Reader(reader), PrevState(Reader.ProcessingUpdateRecords) { Reader.ProcessingUpdateRecords = true; } @@ -1171,7 +1178,7 @@ private: ~ProcessingUpdatesRAIIObj() { Reader.ProcessingUpdateRecords = PrevState; } }; - /// \brief Suggested contents of the predefines buffer, after this + /// Suggested contents of the predefines buffer, after this /// PCH file has been processed. /// /// In most cases, this string will be empty, because the predefines @@ -1183,7 +1190,7 @@ private: llvm::DenseMap<const Decl *, bool> DefinitionSource; - /// \brief Reads a statement from the specified cursor. + /// Reads a statement from the specified cursor. Stmt *ReadStmtFromStream(ModuleFile &F); struct InputFileInfo { @@ -1195,10 +1202,10 @@ private: bool TopLevelModuleMap; }; - /// \brief Reads the stored information about an input file. + /// Reads the stored information about an input file. InputFileInfo readInputFileInfo(ModuleFile &F, unsigned ID); - /// \brief Retrieve the file entry and 'overridden' bit for an input + /// Retrieve the file entry and 'overridden' bit for an input /// file in the given module file. serialization::InputFile getInputFile(ModuleFile &F, unsigned ID, bool Complain = true); @@ -1207,7 +1214,7 @@ public: void ResolveImportedPath(ModuleFile &M, std::string &Filename); static void ResolveImportedPath(std::string &Filename, StringRef Prefix); - /// \brief Returns the first key declaration for the given declaration. This + /// Returns the first key declaration for the given declaration. This /// is one that is formerly-canonical (or still canonical) and whose module /// did not import any other key declaration of the entity. Decl *getKeyDeclaration(Decl *D) { @@ -1224,7 +1231,7 @@ public: return getKeyDeclaration(const_cast<Decl*>(D)); } - /// \brief Run a callback on each imported key declaration of \p D. + /// Run a callback on each imported key declaration of \p D. template <typename Fn> void forEachImportedKeyDecl(const Decl *D, Fn Visit) { D = D->getCanonicalDecl(); @@ -1237,7 +1244,7 @@ public: Visit(GetExistingDecl(ID)); } - /// \brief Get the loaded lookup tables for \p Primary, if any. + /// Get the loaded lookup tables for \p Primary, if any. const serialization::reader::DeclContextLookupTable * getLoadedLookupTables(DeclContext *Primary) const; @@ -1250,7 +1257,7 @@ private: ImportedModule(ModuleFile *Mod, ModuleFile *ImportedBy, SourceLocation ImportLoc) - : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) {} + : Mod(Mod), ImportedBy(ImportedBy), ImportLoc(ImportLoc) {} }; ASTReadResult ReadASTCore(StringRef FileName, ModuleKind Type, @@ -1314,8 +1321,7 @@ private: ModuleFile *F; uint64_t Offset; - RecordLocation(ModuleFile *M, uint64_t O) - : F(M), Offset(O) {} + RecordLocation(ModuleFile *M, uint64_t O) : F(M), Offset(O) {} }; QualType readTypeRecord(unsigned Index); @@ -1328,7 +1334,7 @@ private: Decl *ReadDeclRecord(serialization::DeclID ID); void markIncompleteDeclChain(Decl *Canon); - /// \brief Returns the most recent declaration of a declaration (which must be + /// Returns the most recent declaration of a declaration (which must be /// of a redeclarable kind) that is either local or has already been loaded /// merged into its redecl chain. Decl *getMostRecentExistingDecl(Decl *D); @@ -1343,12 +1349,12 @@ private: RecordLocation getLocalBitOffset(uint64_t GlobalOffset); uint64_t getGlobalBitOffset(ModuleFile &M, uint32_t LocalOffset); - /// \brief Returns the first preprocessed entity ID that begins or ends after + /// Returns the first preprocessed entity ID that begins or ends after /// \arg Loc. serialization::PreprocessedEntityID findPreprocessedEntity(SourceLocation Loc, bool EndsAfter) const; - /// \brief Find the next module that contains entities and return the ID + /// Find the next module that contains entities and return the ID /// of the first entry. /// /// \param SLocMapI points at a chunk of a module that contains no @@ -1358,12 +1364,12 @@ private: findNextPreprocessedEntity( GlobalSLocOffsetMapType::const_iterator SLocMapI) const; - /// \brief Returns (ModuleFile, Local index) pair for \p GlobalIndex of a + /// Returns (ModuleFile, Local index) pair for \p GlobalIndex of a /// preprocessed entity. std::pair<ModuleFile *, unsigned> getModulePreprocessedEntity(unsigned GlobalIndex); - /// \brief Returns (begin, end) pair for the preprocessed entities of a + /// Returns (begin, end) pair for the preprocessed entities of a /// particular module. llvm::iterator_range<PreprocessingRecord::iterator> getModulePreprocessedEntities(ModuleFile &Mod) const; @@ -1416,7 +1422,7 @@ private: PendingDeclContextInfos.push_back(Info); } - /// \brief Produce an error diagnostic and return true. + /// Produce an error diagnostic and return true. /// /// This routine should only be used for fatal errors that have to /// do with non-routine failures (e.g., corrupted AST file). @@ -1425,7 +1431,7 @@ private: StringRef Arg2 = StringRef()) const; public: - /// \brief Load the AST file and validate its contents against the given + /// Load the AST file and validate its contents against the given /// Preprocessor. /// /// \param PP the preprocessor associated with the context in which this @@ -1480,34 +1486,34 @@ public: FileManager &getFileManager() const { return FileMgr; } DiagnosticsEngine &getDiags() const { return Diags; } - /// \brief Flags that indicate what kind of AST loading failures the client + /// Flags that indicate what kind of AST loading failures the client /// of the AST reader can directly handle. /// /// When a client states that it can handle a particular kind of failure, /// the AST reader will not emit errors when producing that kind of failure. enum LoadFailureCapabilities { - /// \brief The client can't handle any AST loading failures. + /// The client can't handle any AST loading failures. ARR_None = 0, - /// \brief The client can handle an AST file that cannot load because it + /// The client can handle an AST file that cannot load because it /// is missing. ARR_Missing = 0x1, - /// \brief The client can handle an AST file that cannot load because it + /// The client can handle an AST file that cannot load because it /// is out-of-date relative to its input files. ARR_OutOfDate = 0x2, - /// \brief The client can handle an AST file that cannot load because it + /// The client can handle an AST file that cannot load because it /// was built with a different version of Clang. ARR_VersionMismatch = 0x4, - /// \brief The client can handle an AST file that cannot load because it's + /// The client can handle an AST file that cannot load because it's /// compiled configuration doesn't match that of the context it was /// loaded into. ARR_ConfigurationMismatch = 0x8 }; - /// \brief Load the AST file designated by the given file name. + /// Load the AST file designated by the given file name. /// /// \param FileName The name of the AST file to load. /// @@ -1528,7 +1534,7 @@ public: unsigned ClientLoadCapabilities, SmallVectorImpl<ImportedSubmodule> *Imported = nullptr); - /// \brief Make the entities in the given module and any of its (non-explicit) + /// Make the entities in the given module and any of its (non-explicit) /// submodules visible to name lookup. /// /// \param Mod The module whose names should be made visible. @@ -1541,24 +1547,24 @@ public: Module::NameVisibilityKind NameVisibility, SourceLocation ImportLoc); - /// \brief Make the names within this set of hidden names visible. + /// Make the names within this set of hidden names visible. void makeNamesVisible(const HiddenNames &Names, Module *Owner); - /// \brief Note that MergedDef is a redefinition of the canonical definition + /// Note that MergedDef is a redefinition of the canonical definition /// Def, so Def should be visible whenever MergedDef is. void mergeDefinitionVisibility(NamedDecl *Def, NamedDecl *MergedDef); - /// \brief Take the AST callbacks listener. + /// Take the AST callbacks listener. std::unique_ptr<ASTReaderListener> takeListener() { return std::move(Listener); } - /// \brief Set the AST callbacks listener. + /// Set the AST callbacks listener. void setListener(std::unique_ptr<ASTReaderListener> Listener) { this->Listener = std::move(Listener); } - /// \brief Add an AST callback listener. + /// Add an AST callback listener. /// /// Takes ownership of \p L. void addListener(std::unique_ptr<ASTReaderListener> L) { @@ -1593,67 +1599,72 @@ public: } }; - /// \brief Set the AST deserialization listener. + /// Set the AST deserialization listener. void setDeserializationListener(ASTDeserializationListener *Listener, bool TakeOwnership = false); - /// \brief Determine whether this AST reader has a global index. + /// Get the AST deserialization listener. + ASTDeserializationListener *getDeserializationListener() { + return DeserializationListener; + } + + /// Determine whether this AST reader has a global index. bool hasGlobalIndex() const { return (bool)GlobalIndex; } - /// \brief Return global module index. + /// Return global module index. GlobalModuleIndex *getGlobalIndex() { return GlobalIndex.get(); } - /// \brief Reset reader for a reload try. + /// Reset reader for a reload try. void resetForReload() { TriedLoadingGlobalIndex = false; } - /// \brief Attempts to load the global index. + /// Attempts to load the global index. /// /// \returns true if loading the global index has failed for any reason. bool loadGlobalIndex(); - /// \brief Determine whether we tried to load the global index, but failed, + /// Determine whether we tried to load the global index, but failed, /// e.g., because it is out-of-date or does not exist. bool isGlobalIndexUnavailable() const; - /// \brief Initializes the ASTContext + /// Initializes the ASTContext void InitializeContext(); - /// \brief Update the state of Sema after loading some additional modules. + /// Update the state of Sema after loading some additional modules. void UpdateSema(); - /// \brief Add in-memory (virtual file) buffer. + /// Add in-memory (virtual file) 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 + /// Finalizes the AST reader's state before writing an AST file to /// disk. /// /// This operation may undo temporary state in the AST that should not be /// emitted. void finalizeForWriting(); - /// \brief Retrieve the module manager. + /// Retrieve the module manager. ModuleManager &getModuleManager() { return ModuleMgr; } - /// \brief Retrieve the preprocessor. + /// Retrieve the preprocessor. Preprocessor &getPreprocessor() const { return PP; } - /// \brief Retrieve the name of the original source file name for the primary + /// Retrieve the name of the original source file name for the primary /// module file. StringRef getOriginalSourceFile() { return ModuleMgr.getPrimaryModule().OriginalSourceFileName; } - /// \brief Retrieve the name of the original source file name directly from + /// Retrieve the name of the original source file name directly from /// the AST file, without actually loading the AST file. static std::string getOriginalSourceFile(const std::string &ASTFileName, FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, DiagnosticsEngine &Diags); - /// \brief Read the control block for the named AST file. + /// Read the control block for the named AST file. /// /// \returns true if an error occurred, false otherwise. static bool @@ -1663,7 +1674,7 @@ public: ASTReaderListener &Listener, bool ValidateDiagnosticOptions); - /// \brief Determine whether the given AST file is acceptable to load into a + /// Determine whether the given AST file is acceptable to load into a /// translation unit with the given language and target options. static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, const PCHContainerReader &PCHContainerRdr, @@ -1672,68 +1683,71 @@ public: const PreprocessorOptions &PPOpts, StringRef ExistingModuleCachePath); - /// \brief Returns the suggested contents of the predefines buffer, + /// Returns the suggested contents of the predefines buffer, /// which contains a (typically-empty) subset of the predefines /// build prior to including the precompiled header. const std::string &getSuggestedPredefines() { return SuggestedPredefines; } - /// \brief Read a preallocated preprocessed entity from the external source. + /// Read a preallocated preprocessed entity from the external source. /// /// \returns null if an error occurred that prevented the preprocessed /// entity from being loaded. PreprocessedEntity *ReadPreprocessedEntity(unsigned Index) override; - /// \brief Returns a pair of [Begin, End) indices of preallocated + /// Returns a pair of [Begin, End) indices of preallocated /// preprocessed entities that \p Range encompasses. std::pair<unsigned, unsigned> findPreprocessedEntitiesInRange(SourceRange Range) override; - /// \brief Optionally returns true or false if the preallocated preprocessed + /// Optionally returns true or false if the preallocated preprocessed /// entity with index \p Index came from file \p FID. Optional<bool> isPreprocessedEntityInFileID(unsigned Index, FileID FID) override; - /// \brief Read the header file information for the given file entry. + /// Read a preallocated skipped range from the external source. + SourceRange ReadSkippedRange(unsigned Index) override; + + /// Read the header file information for the given file entry. HeaderFileInfo GetHeaderFileInfo(const FileEntry *FE) override; void ReadPragmaDiagnosticMappings(DiagnosticsEngine &Diag); - /// \brief Returns the number of source locations found in the chain. + /// Returns the number of source locations found in the chain. unsigned getTotalNumSLocs() const { return TotalNumSLocEntries; } - /// \brief Returns the number of identifiers found in the chain. + /// Returns the number of identifiers found in the chain. unsigned getTotalNumIdentifiers() const { return static_cast<unsigned>(IdentifiersLoaded.size()); } - /// \brief Returns the number of macros found in the chain. + /// Returns the number of macros found in the chain. unsigned getTotalNumMacros() const { return static_cast<unsigned>(MacrosLoaded.size()); } - /// \brief Returns the number of types found in the chain. + /// Returns the number of types found in the chain. unsigned getTotalNumTypes() const { return static_cast<unsigned>(TypesLoaded.size()); } - /// \brief Returns the number of declarations found in the chain. + /// Returns the number of declarations found in the chain. unsigned getTotalNumDecls() const { return static_cast<unsigned>(DeclsLoaded.size()); } - /// \brief Returns the number of submodules known. + /// Returns the number of submodules known. unsigned getTotalNumSubmodules() const { return static_cast<unsigned>(SubmodulesLoaded.size()); } - /// \brief Returns the number of selectors found in the chain. + /// Returns the number of selectors found in the chain. unsigned getTotalNumSelectors() const { return static_cast<unsigned>(SelectorsLoaded.size()); } - /// \brief Returns the number of preprocessed entities known to the AST + /// Returns the number of preprocessed entities known to the AST /// reader. unsigned getTotalNumPreprocessedEntities() const { unsigned Result = 0; @@ -1742,13 +1756,13 @@ public: return Result; } - /// \brief Reads a TemplateArgumentLocInfo appropriate for the + /// Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind. TemplateArgumentLocInfo GetTemplateArgumentLocInfo(ModuleFile &F, TemplateArgument::ArgKind Kind, const RecordData &Record, unsigned &Idx); - /// \brief Reads a TemplateArgumentLoc. + /// Reads a TemplateArgumentLoc. TemplateArgumentLoc ReadTemplateArgumentLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx); @@ -1757,63 +1771,67 @@ public: ReadASTTemplateArgumentListInfo(ModuleFile &F, const RecordData &Record, unsigned &Index); - /// \brief Reads a declarator info from the given record. + /// Reads a declarator info from the given record. TypeSourceInfo *GetTypeSourceInfo(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Resolve a type ID into a type, potentially building a new + /// Raad the type locations for the given TInfo. + void ReadTypeLoc(ModuleFile &F, const RecordData &Record, unsigned &Idx, + TypeLoc TL); + + /// Resolve a type ID into a type, potentially building a new /// type. QualType GetType(serialization::TypeID ID); - /// \brief Resolve a local type ID within a given AST file into a type. + /// Resolve a local type ID within a given AST file into a type. QualType getLocalType(ModuleFile &F, unsigned LocalID); - /// \brief Map a local type ID within a given AST file into a global type ID. + /// Map a local type ID within a given AST file into a global type ID. serialization::TypeID getGlobalTypeID(ModuleFile &F, unsigned LocalID) const; - /// \brief Read a type from the current position in the given record, which + /// Read a type from the current position in the given record, which /// was read from the given AST file. QualType readType(ModuleFile &F, const RecordData &Record, unsigned &Idx) { if (Idx >= Record.size()) - return QualType(); + return {}; return getLocalType(F, Record[Idx++]); } - /// \brief Map from a local declaration ID within a given module to a + /// Map from a local declaration ID within a given module to a /// global declaration ID. serialization::DeclID getGlobalDeclID(ModuleFile &F, serialization::LocalDeclID LocalID) const; - /// \brief Returns true if global DeclID \p ID originated from module \p M. + /// Returns true if global DeclID \p ID originated from module \p M. bool isDeclIDFromModule(serialization::GlobalDeclID ID, ModuleFile &M) const; - /// \brief Retrieve the module file that owns the given declaration, or NULL + /// Retrieve the module file that owns the given declaration, or NULL /// if the declaration is not from a module file. ModuleFile *getOwningModuleFile(const Decl *D); - /// \brief Get the best name we know for the module that owns the given + /// Get the best name we know for the module that owns the given /// declaration, or an empty string if the declaration is not from a module. std::string getOwningModuleNameForDiagnostic(const Decl *D); - /// \brief Returns the source location for the decl \p ID. + /// Returns the source location for the decl \p ID. SourceLocation getSourceLocationForDeclID(serialization::GlobalDeclID ID); - /// \brief Resolve a declaration ID into a declaration, potentially + /// Resolve a declaration ID into a declaration, potentially /// building a new declaration. Decl *GetDecl(serialization::DeclID ID); Decl *GetExternalDecl(uint32_t ID) override; - /// \brief Resolve a declaration ID into a declaration. Return 0 if it's not + /// Resolve a declaration ID into a declaration. Return 0 if it's not /// been loaded yet. Decl *GetExistingDecl(serialization::DeclID ID); - /// \brief Reads a declaration with the given local ID in the given module. + /// Reads a declaration with the given local ID in the given module. Decl *GetLocalDecl(ModuleFile &F, uint32_t LocalID) { return GetDecl(getGlobalDeclID(F, LocalID)); } - /// \brief Reads a declaration with the given local ID in the given module. + /// Reads a declaration with the given local ID in the given module. /// /// \returns The requested declaration, casted to the given return type. template<typename T> @@ -1821,7 +1839,7 @@ public: return cast_or_null<T>(GetLocalDecl(F, LocalID)); } - /// \brief Map a global declaration ID into the declaration ID used to + /// Map a global declaration ID into the declaration ID used to /// refer to this declaration within the given module fule. /// /// \returns the global ID of the given declaration as known in the given @@ -1830,20 +1848,20 @@ public: mapGlobalIDToModuleFileGlobalID(ModuleFile &M, serialization::DeclID GlobalID); - /// \brief Reads a declaration ID from the given position in a record in the + /// Reads a declaration ID from the given position in a record in the /// given module. /// /// \returns The declaration ID read from the record, adjusted to a global ID. serialization::DeclID ReadDeclID(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Reads a declaration from the given position in a record in the + /// Reads a declaration from the given position in a record in the /// given module. Decl *ReadDecl(ModuleFile &F, const RecordData &R, unsigned &I) { return GetDecl(ReadDeclID(F, R, I)); } - /// \brief Reads a declaration from the given position in a record in the + /// Reads a declaration from the given position in a record in the /// given module. /// /// \returns The declaration read from this location, casted to the given @@ -1853,14 +1871,14 @@ public: return cast_or_null<T>(GetDecl(ReadDeclID(F, R, I))); } - /// \brief If any redeclarations of \p D have been imported since it was + /// If any redeclarations of \p D have been imported since it was /// last checked, this digs out those redeclarations and adds them to the /// redeclaration chain for \p D. void CompleteRedeclChain(const Decl *D) override; CXXBaseSpecifier *GetExternalCXXBaseSpecifiers(uint64_t Offset) override; - /// \brief Resolve the offset of a statement into a statement. + /// Resolve the offset of a statement into a statement. /// /// This operation will read a new statement from the external /// source each time it is called, and is meant to be used via a @@ -1872,13 +1890,13 @@ public: /// and then leave the cursor pointing into the block. static bool ReadBlockAbbrevs(llvm::BitstreamCursor &Cursor, unsigned BlockID); - /// \brief Finds all the visible declarations with a given name. + /// Finds all the visible declarations with a given name. /// The current implementation of this method just loads the entire /// lookup table as unmaterialized references. bool FindExternalVisibleDeclsByName(const DeclContext *DC, DeclarationName Name) override; - /// \brief Read all of the declarations lexically stored in a + /// Read all of the declarations lexically stored in a /// declaration context. /// /// \param DC The declaration context whose declarations will be @@ -1896,47 +1914,47 @@ public: llvm::function_ref<bool(Decl::Kind)> IsKindWeWant, SmallVectorImpl<Decl *> &Decls) override; - /// \brief Get the decls that are contained in a file in the Offset/Length + /// Get the decls that are contained in a file in the Offset/Length /// range. \p Length can be 0 to indicate a point at \p Offset instead of /// a range. void FindFileRegionDecls(FileID File, unsigned Offset, unsigned Length, SmallVectorImpl<Decl *> &Decls) override; - /// \brief Notify ASTReader that we started deserialization of + /// Notify ASTReader that we started deserialization of /// a decl or type so until FinishedDeserializing is called there may be /// decls that are initializing. Must be paired with FinishedDeserializing. void StartedDeserializing() override; - /// \brief Notify ASTReader that we finished the deserialization of + /// Notify ASTReader that we finished the deserialization of /// a decl or type. Must be paired with StartedDeserializing. void FinishedDeserializing() override; - /// \brief Function that will be invoked when we begin parsing a new + /// Function that will be invoked when we begin parsing a new /// translation unit involving this external AST source. /// /// This function will provide all of the external definitions to /// the ASTConsumer. void StartTranslationUnit(ASTConsumer *Consumer) override; - /// \brief Print some statistics about AST usage. + /// Print some statistics about AST usage. void PrintStats() override; - /// \brief Dump information about the AST reader to standard error. + /// Dump information about the AST reader to standard error. void dump(); /// Return the amount of memory used by memory buffers, breaking down /// by heap-backed versus mmap'ed memory. void getMemoryBufferSizes(MemoryBufferSizes &sizes) const override; - /// \brief Initialize the semantic source with the Sema instance + /// Initialize the semantic source with the Sema instance /// being used to perform semantic analysis on the abstract syntax /// tree. void InitializeSema(Sema &S) override; - /// \brief Inform the semantic consumer that Sema is no longer available. + /// Inform the semantic consumer that Sema is no longer available. void ForgetSema() override { SemaObj = nullptr; } - /// \brief Retrieve the IdentifierInfo for the named identifier. + /// Retrieve the IdentifierInfo for the named identifier. /// /// This routine builds a new IdentifierInfo for the given identifier. If any /// declarations with this name are visible from translation unit scope, their @@ -1944,11 +1962,11 @@ public: /// chain of the identifier. IdentifierInfo *get(StringRef Name) override; - /// \brief Retrieve an iterator into the set of all identifiers + /// Retrieve an iterator into the set of all identifiers /// in all loaded AST files. IdentifierIterator *getIdentifiers() override; - /// \brief Load the contents of the global method pool for a given + /// Load the contents of the global method pool for a given /// selector. void ReadMethodPool(Selector Sel) override; @@ -1956,7 +1974,7 @@ public: /// selector if necessary. void updateOutOfDateSelector(Selector Sel) override; - /// \brief Load the set of namespaces that are known to the external source, + /// Load the set of namespaces that are known to the external source, /// which will be used during typo correction. void ReadKnownNamespaces( SmallVectorImpl<NamespaceDecl *> &Namespaces) override; @@ -1998,7 +2016,7 @@ public: llvm::MapVector<const FunctionDecl *, std::unique_ptr<LateParsedTemplate>> &LPTMap) override; - /// \brief Load a selector from disk, registering its ID if it exists. + /// Load a selector from disk, registering its ID if it exists. void LoadSelector(Selector Sel); void SetIdentifierInfo(unsigned ID, IdentifierInfo *II); @@ -2006,10 +2024,10 @@ public: const SmallVectorImpl<uint32_t> &DeclIDs, SmallVectorImpl<Decl *> *Decls = nullptr); - /// \brief Report a diagnostic. + /// Report a diagnostic. DiagnosticBuilder Diag(unsigned DiagID) const; - /// \brief Report a diagnostic. + /// Report a diagnostic. DiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID) const; IdentifierInfo *DecodeIdentifierInfo(serialization::IdentifierID ID); @@ -2033,47 +2051,49 @@ public: void resolvePendingMacro(IdentifierInfo *II, const PendingMacroInfo &PMInfo); - /// \brief Retrieve the macro with the given ID. + /// Retrieve the macro with the given ID. MacroInfo *getMacro(serialization::MacroID ID); - /// \brief Retrieve the global macro ID corresponding to the given local + /// Retrieve the global macro ID corresponding to the given local /// ID within the given module file. serialization::MacroID getGlobalMacroID(ModuleFile &M, unsigned LocalID); - /// \brief Read the source location entry with index ID. + /// Read the source location entry with index ID. bool ReadSLocEntry(int ID) override; - /// \brief Retrieve the module import location and module name for the + /// Retrieve the module import location and module name for the /// given source manager entry ID. std::pair<SourceLocation, StringRef> getModuleImportLoc(int ID) override; - /// \brief Retrieve the global submodule ID given a module and its local ID + /// Retrieve the global submodule ID given a module and its local ID /// number. serialization::SubmoduleID getGlobalSubmoduleID(ModuleFile &M, unsigned LocalID); - /// \brief Retrieve the submodule that corresponds to a global submodule ID. + /// Retrieve the submodule that corresponds to a global submodule ID. /// Module *getSubmodule(serialization::SubmoduleID GlobalID); - /// \brief Retrieve the module that corresponds to the given module ID. + /// Retrieve the module that corresponds to the given module ID. /// /// Note: overrides method in ExternalASTSource Module *getModule(unsigned ID) override; - /// \brief Retrieve the module file with a given local ID within the specified + bool DeclIsFromPCHWithObjectFile(const Decl *D) override; + + /// Retrieve the module file with a given local ID within the specified /// ModuleFile. ModuleFile *getLocalModuleFile(ModuleFile &M, unsigned ID); - /// \brief Get an ID for the given module file. + /// Get an ID for the given module file. unsigned getModuleFileID(ModuleFile *M); - /// \brief Return a descriptor for the corresponding module. + /// Return a descriptor for the corresponding module. llvm::Optional<ASTSourceDescriptor> getSourceDescriptor(unsigned ID) override; ExtKind hasExternalDefinitions(const Decl *D) override; - /// \brief Retrieve a selector from the given module with its local ID + /// Retrieve a selector from the given module with its local ID /// number. Selector getLocalSelector(ModuleFile &M, unsigned LocalID); @@ -2086,12 +2106,12 @@ public: return getLocalSelector(M, Record[Idx++]); } - /// \brief Retrieve the global selector ID that corresponds to this + /// Retrieve the global selector ID that corresponds to this /// the local selector ID in a given module. serialization::SelectorID getGlobalSelectorID(ModuleFile &F, unsigned LocalID) const; - /// \brief Read a declaration name. + /// Read a declaration name. DeclarationName ReadDeclarationName(ModuleFile &F, const RecordData &Record, unsigned &Idx); void ReadDeclarationNameLoc(ModuleFile &F, @@ -2111,54 +2131,54 @@ public: const RecordData &Record, unsigned &Idx); - /// \brief Read a template name. + /// Read a template name. TemplateName ReadTemplateName(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Read a template argument. + /// Read a template argument. TemplateArgument ReadTemplateArgument(ModuleFile &F, const RecordData &Record, unsigned &Idx, bool Canonicalize = false); - /// \brief Read a template parameter list. + /// Read a template parameter list. TemplateParameterList *ReadTemplateParameterList(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Read a template argument array. + /// Read a template argument array. void ReadTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, ModuleFile &F, const RecordData &Record, unsigned &Idx, bool Canonicalize = false); - /// \brief Read a UnresolvedSet structure. + /// Read a UnresolvedSet structure. void ReadUnresolvedSet(ModuleFile &F, LazyASTUnresolvedSet &Set, const RecordData &Record, unsigned &Idx); - /// \brief Read a C++ base specifier. + /// Read a C++ base specifier. CXXBaseSpecifier ReadCXXBaseSpecifier(ModuleFile &F, const RecordData &Record,unsigned &Idx); - /// \brief Read a CXXCtorInitializer array. + /// Read a CXXCtorInitializer array. CXXCtorInitializer ** ReadCXXCtorInitializers(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Read the contents of a CXXCtorInitializer array. + /// Read the contents of a CXXCtorInitializer array. CXXCtorInitializer **GetExternalCXXCtorInitializers(uint64_t Offset) override; - /// \brief Read a source location from raw form and return it in its + /// Read a source location from raw form and return it in its /// originating module file's source location space. SourceLocation ReadUntranslatedSourceLocation(uint32_t Raw) const { return SourceLocation::getFromRawEncoding((Raw >> 1) | (Raw << 31)); } - /// \brief Read a source location from raw form. + /// Read a source location from raw form. SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, uint32_t Raw) const { SourceLocation Loc = ReadUntranslatedSourceLocation(Raw); return TranslateSourceLocation(ModuleFile, Loc); } - /// \brief Translate a source location from another module file's source + /// Translate a source location from another module file's source /// location space into ours. SourceLocation TranslateSourceLocation(ModuleFile &ModuleFile, SourceLocation Loc) const { @@ -2171,59 +2191,59 @@ public: return Loc.getLocWithOffset(Remap); } - /// \brief Read a source location. + /// Read a source location. SourceLocation ReadSourceLocation(ModuleFile &ModuleFile, const RecordDataImpl &Record, unsigned &Idx) { return ReadSourceLocation(ModuleFile, Record[Idx++]); } - /// \brief Read a source range. + /// Read a source range. SourceRange ReadSourceRange(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Read an integral value + /// Read an integral value llvm::APInt ReadAPInt(const RecordData &Record, unsigned &Idx); - /// \brief Read a signed integral value + /// Read a signed integral value llvm::APSInt ReadAPSInt(const RecordData &Record, unsigned &Idx); - /// \brief Read a floating-point value + /// Read a floating-point value llvm::APFloat ReadAPFloat(const RecordData &Record, const llvm::fltSemantics &Sem, unsigned &Idx); - // \brief Read a string + // Read a string static std::string ReadString(const RecordData &Record, unsigned &Idx); - // \brief Skip a string + // Skip a string static void SkipString(const RecordData &Record, unsigned &Idx) { Idx += Record[Idx] + 1; } - // \brief Read a path + // Read a path std::string ReadPath(ModuleFile &F, const RecordData &Record, unsigned &Idx); - // \brief Skip a path + // Skip a path static void SkipPath(const RecordData &Record, unsigned &Idx) { SkipString(Record, Idx); } - /// \brief Read a version tuple. + /// Read a version tuple. static VersionTuple ReadVersionTuple(const RecordData &Record, unsigned &Idx); CXXTemporary *ReadCXXTemporary(ModuleFile &F, const RecordData &Record, unsigned &Idx); - /// \brief Reads attributes from the current stream position. + /// Reads attributes from the current stream position. void ReadAttributes(ASTRecordReader &Record, AttrVec &Attrs); - /// \brief Reads a statement. + /// Reads a statement. Stmt *ReadStmt(ModuleFile &F); - /// \brief Reads an expression. + /// Reads an expression. Expr *ReadExpr(ModuleFile &F); - /// \brief Reads a sub-statement operand during statement reading. + /// Reads a sub-statement operand during statement reading. Stmt *ReadSubStmt() { assert(ReadingKind == Read_Stmt && "Should be called only during statement reading!"); @@ -2233,21 +2253,21 @@ public: return StmtStack.pop_back_val(); } - /// \brief Reads a sub-expression operand during statement reading. + /// Reads a sub-expression operand during statement reading. Expr *ReadSubExpr(); - /// \brief Reads a token out of a record. + /// Reads a token out of a record. Token ReadToken(ModuleFile &M, const RecordDataImpl &Record, unsigned &Idx); - /// \brief Reads the macro record located at the given offset. + /// Reads the macro record located at the given offset. MacroInfo *ReadMacroRecord(ModuleFile &F, uint64_t Offset); - /// \brief Determine the global preprocessed entity ID that corresponds to + /// Determine the global preprocessed entity ID that corresponds to /// the given local ID within the given module. serialization::PreprocessedEntityID getGlobalPreprocessedEntityID(ModuleFile &M, unsigned LocalID) const; - /// \brief Add a macro to deserialize its macro directive history. + /// Add a macro to deserialize its macro directive history. /// /// \param II The name of the macro. /// \param M The module file. @@ -2256,56 +2276,56 @@ public: void addPendingMacro(IdentifierInfo *II, ModuleFile *M, uint64_t MacroDirectivesOffset); - /// \brief Read the set of macros defined by this external macro source. + /// Read the set of macros defined by this external macro source. void ReadDefinedMacros() override; - /// \brief Update an out-of-date identifier. + /// Update an out-of-date identifier. void updateOutOfDateIdentifier(IdentifierInfo &II) override; - /// \brief Note that this identifier is up-to-date. + /// Note that this identifier is up-to-date. void markIdentifierUpToDate(IdentifierInfo *II); - /// \brief Load all external visible decls in the given DeclContext. + /// Load all external visible decls in the given DeclContext. void completeVisibleDeclsMap(const DeclContext *DC) override; - /// \brief Retrieve the AST context that this AST reader supplements. + /// Retrieve the AST context that this AST reader supplements. ASTContext &getContext() { assert(ContextObj && "requested AST context when not loading AST"); return *ContextObj; } - // \brief Contains the IDs for declarations that were requested before we have + // Contains the IDs for declarations that were requested before we have // access to a Sema object. SmallVector<uint64_t, 16> PreloadedDeclIDs; - /// \brief Retrieve the semantic analysis object used to analyze the + /// Retrieve the semantic analysis object used to analyze the /// translation unit in which the precompiled header is being /// imported. Sema *getSema() { return SemaObj; } - /// \brief Get the identifier resolver used for name lookup / updates + /// Get the identifier resolver used for name lookup / updates /// in the translation unit scope. We have one of these even if we don't /// have a Sema object. IdentifierResolver &getIdResolver(); - /// \brief Retrieve the identifier table associated with the + /// Retrieve the identifier table associated with the /// preprocessor. IdentifierTable &getIdentifierTable(); - /// \brief Record that the given ID maps to the given switch-case + /// Record that the given ID maps to the given switch-case /// statement. void RecordSwitchCaseID(SwitchCase *SC, unsigned ID); - /// \brief Retrieve the switch-case statement with the given ID. + /// Retrieve the switch-case statement with the given ID. SwitchCase *getSwitchCaseWithID(unsigned ID); void ClearSwitchCaseIDs(); - /// \brief Cursors for comments blocks. + /// Cursors for comments blocks. SmallVector<std::pair<llvm::BitstreamCursor, serialization::ModuleFile *>, 8> CommentsCursors; - /// \brief Loads comments ranges. + /// Loads comments ranges. void ReadComments() override; /// Visit all the input files of the given module file. @@ -2323,7 +2343,7 @@ public: bool isProcessingUpdateRecords() { return ProcessingUpdateRecords; } }; -/// \brief An object for streaming information from a record. +/// An object for streaming information from a record. class ASTRecordReader { using ModuleFile = serialization::ModuleFile; @@ -2339,56 +2359,56 @@ public: /// Construct an ASTRecordReader that uses the default encoding scheme. ASTRecordReader(ASTReader &Reader, ModuleFile &F) : Reader(&Reader), F(&F) {} - /// \brief Reads a record with id AbbrevID from Cursor, resetting the + /// Reads a record with id AbbrevID from Cursor, resetting the /// internal state. unsigned readRecord(llvm::BitstreamCursor &Cursor, unsigned AbbrevID); - /// \brief Is this a module file for a module (rather than a PCH or similar). + /// Is this a module file for a module (rather than a PCH or similar). bool isModule() const { return F->isModule(); } - /// \brief Retrieve the AST context that this AST reader supplements. + /// Retrieve the AST context that this AST reader supplements. ASTContext &getContext() { return Reader->getContext(); } - /// \brief The current position in this record. + /// The current position in this record. unsigned getIdx() const { return Idx; } - /// \brief The length of this record. + /// The length of this record. size_t size() const { return Record.size(); } - /// \brief An arbitrary index in this record. + /// An arbitrary index in this record. const uint64_t &operator[](size_t N) { return Record[N]; } - /// \brief The last element in this record. + /// The last element in this record. const uint64_t &back() const { return Record.back(); } - /// \brief Returns the current value in this record, and advances to the + /// Returns the current value in this record, and advances to the /// next value. const uint64_t &readInt() { return Record[Idx++]; } - /// \brief Returns the current value in this record, without advancing. + /// Returns the current value in this record, without advancing. const uint64_t &peekInt() { return Record[Idx]; } - /// \brief Skips the specified number of values. + /// Skips the specified number of values. void skipInts(unsigned N) { Idx += N; } - /// \brief Retrieve the global submodule ID its local ID number. + /// Retrieve the global submodule ID its local ID number. serialization::SubmoduleID getGlobalSubmoduleID(unsigned LocalID) { return Reader->getGlobalSubmoduleID(*F, LocalID); } - /// \brief Retrieve the submodule that corresponds to a global submodule ID. + /// Retrieve the submodule that corresponds to a global submodule ID. Module *getSubmodule(serialization::SubmoduleID GlobalID) { return Reader->getSubmodule(GlobalID); } - /// \brief Read the record that describes the lexical contents of a DC. + /// Read the record that describes the lexical contents of a DC. bool readLexicalDeclContextStorage(uint64_t Offset, DeclContext *DC) { return Reader->ReadLexicalDeclContextStorage(*F, F->DeclsCursor, Offset, DC); } - /// \brief Read the record that describes the visible contents of a DC. + /// Read the record that describes the visible contents of a DC. bool readVisibleDeclContextStorage(uint64_t Offset, serialization::DeclID ID) { return Reader->ReadVisibleDeclContextStorage(*F, F->DeclsCursor, Offset, @@ -2400,24 +2420,24 @@ public: return Reader->readExceptionSpec(*F, ExceptionStorage, ESI, Record, Idx); } - /// \brief Get the global offset corresponding to a local offset. + /// Get the global offset corresponding to a local offset. uint64_t getGlobalBitOffset(uint32_t LocalOffset) { return Reader->getGlobalBitOffset(*F, LocalOffset); } - /// \brief Reads a statement. + /// Reads a statement. Stmt *readStmt() { return Reader->ReadStmt(*F); } - /// \brief Reads an expression. + /// Reads an expression. Expr *readExpr() { return Reader->ReadExpr(*F); } - /// \brief Reads a sub-statement operand during statement reading. + /// Reads a sub-statement operand during statement reading. Stmt *readSubStmt() { return Reader->ReadSubStmt(); } - /// \brief Reads a sub-expression operand during statement reading. + /// Reads a sub-expression operand during statement reading. Expr *readSubExpr() { return Reader->ReadSubExpr(); } - /// \brief Reads a declaration with the given local ID in the given module. + /// Reads a declaration with the given local ID in the given module. /// /// \returns The requested declaration, casted to the given return type. template<typename T> @@ -2425,14 +2445,14 @@ public: return cast_or_null<T>(Reader->GetLocalDecl(*F, LocalID)); } - /// \brief Reads a TemplateArgumentLocInfo appropriate for the + /// Reads a TemplateArgumentLocInfo appropriate for the /// given TemplateArgument kind, advancing Idx. TemplateArgumentLocInfo getTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind) { return Reader->GetTemplateArgumentLocInfo(*F, Kind, Record, Idx); } - /// \brief Reads a TemplateArgumentLoc, advancing Idx. + /// Reads a TemplateArgumentLoc, advancing Idx. TemplateArgumentLoc readTemplateArgumentLoc() { return Reader->ReadTemplateArgumentLoc(*F, Record, Idx); @@ -2443,35 +2463,40 @@ public: return Reader->ReadASTTemplateArgumentListInfo(*F, Record, Idx); } - /// \brief Reads a declarator info from the given record, advancing Idx. + /// Reads a declarator info from the given record, advancing Idx. TypeSourceInfo *getTypeSourceInfo() { return Reader->GetTypeSourceInfo(*F, Record, Idx); } - /// \brief Map a local type ID within a given AST file to a global type ID. + /// Reads the location information for a type. + void readTypeLoc(TypeLoc TL) { + return Reader->ReadTypeLoc(*F, Record, Idx, TL); + } + + /// Map a local type ID within a given AST file to a global type ID. serialization::TypeID getGlobalTypeID(unsigned LocalID) const { return Reader->getGlobalTypeID(*F, LocalID); } - /// \brief Read a type from the current position in the record. + /// Read a type from the current position in the record. QualType readType() { return Reader->readType(*F, Record, Idx); } - /// \brief Reads a declaration ID from the given position in this record. + /// Reads a declaration ID from the given position in this record. /// /// \returns The declaration ID read from the record, adjusted to a global ID. serialization::DeclID readDeclID() { return Reader->ReadDeclID(*F, Record, Idx); } - /// \brief Reads a declaration from the given position in a record in the + /// Reads a declaration from the given position in a record in the /// given module, advancing Idx. Decl *readDecl() { return Reader->ReadDecl(*F, Record, Idx); } - /// \brief Reads a declaration from the given position in the record, + /// Reads a declaration from the given position in the record, /// advancing Idx. /// /// \returns The declaration read from this location, casted to the given @@ -2485,12 +2510,12 @@ public: return Reader->GetIdentifierInfo(*F, Record, Idx); } - /// \brief Read a selector from the Record, advancing Idx. + /// Read a selector from the Record, advancing Idx. Selector readSelector() { return Reader->ReadSelector(*F, Record, Idx); } - /// \brief Read a declaration name, advancing Idx. + /// Read a declaration name, advancing Idx. DeclarationName readDeclarationName() { return Reader->ReadDeclarationName(*F, Record, Idx); } @@ -2513,39 +2538,39 @@ public: return Reader->ReadNestedNameSpecifierLoc(*F, Record, Idx); } - /// \brief Read a template name, advancing Idx. + /// Read a template name, advancing Idx. TemplateName readTemplateName() { return Reader->ReadTemplateName(*F, Record, Idx); } - /// \brief Read a template argument, advancing Idx. + /// Read a template argument, advancing Idx. TemplateArgument readTemplateArgument(bool Canonicalize = false) { return Reader->ReadTemplateArgument(*F, Record, Idx, Canonicalize); } - /// \brief Read a template parameter list, advancing Idx. + /// Read a template parameter list, advancing Idx. TemplateParameterList *readTemplateParameterList() { return Reader->ReadTemplateParameterList(*F, Record, Idx); } - /// \brief Read a template argument array, advancing Idx. + /// Read a template argument array, advancing Idx. void readTemplateArgumentList(SmallVectorImpl<TemplateArgument> &TemplArgs, bool Canonicalize = false) { return Reader->ReadTemplateArgumentList(TemplArgs, *F, Record, Idx, Canonicalize); } - /// \brief Read a UnresolvedSet structure, advancing Idx. + /// Read a UnresolvedSet structure, advancing Idx. void readUnresolvedSet(LazyASTUnresolvedSet &Set) { return Reader->ReadUnresolvedSet(*F, Set, Record, Idx); } - /// \brief Read a C++ base specifier, advancing Idx. + /// Read a C++ base specifier, advancing Idx. CXXBaseSpecifier readCXXBaseSpecifier() { return Reader->ReadCXXBaseSpecifier(*F, Record, Idx); } - /// \brief Read a CXXCtorInitializer array, advancing Idx. + /// Read a CXXCtorInitializer array, advancing Idx. CXXCtorInitializer **readCXXCtorInitializers() { return Reader->ReadCXXCtorInitializers(*F, Record, Idx); } @@ -2554,52 +2579,52 @@ public: return Reader->ReadCXXTemporary(*F, Record, Idx); } - /// \brief Read a source location, advancing Idx. + /// Read a source location, advancing Idx. SourceLocation readSourceLocation() { return Reader->ReadSourceLocation(*F, Record, Idx); } - /// \brief Read a source range, advancing Idx. + /// Read a source range, advancing Idx. SourceRange readSourceRange() { return Reader->ReadSourceRange(*F, Record, Idx); } - /// \brief Read an integral value, advancing Idx. + /// Read an integral value, advancing Idx. llvm::APInt readAPInt() { return Reader->ReadAPInt(Record, Idx); } - /// \brief Read a signed integral value, advancing Idx. + /// Read a signed integral value, advancing Idx. llvm::APSInt readAPSInt() { return Reader->ReadAPSInt(Record, Idx); } - /// \brief Read a floating-point value, advancing Idx. + /// Read a floating-point value, advancing Idx. llvm::APFloat readAPFloat(const llvm::fltSemantics &Sem) { return Reader->ReadAPFloat(Record, Sem,Idx); } - /// \brief Read a string, advancing Idx. + /// Read a string, advancing Idx. std::string readString() { return Reader->ReadString(Record, Idx); } - /// \brief Read a path, advancing Idx. + /// Read a path, advancing Idx. std::string readPath() { return Reader->ReadPath(*F, Record, Idx); } - /// \brief Read a version tuple, advancing Idx. + /// Read a version tuple, advancing Idx. VersionTuple readVersionTuple() { return ASTReader::ReadVersionTuple(Record, Idx); } - /// \brief Reads attributes from the current stream position, advancing Idx. + /// Reads attributes from the current stream position, advancing Idx. void readAttributes(AttrVec &Attrs) { return Reader->ReadAttributes(*this, Attrs); } - /// \brief Reads a token out of a record, advancing Idx. + /// Reads a token out of a record, advancing Idx. Token readToken() { return Reader->ReadToken(*F, Record, Idx); } @@ -2608,17 +2633,17 @@ public: Reader->RecordSwitchCaseID(SC, ID); } - /// \brief Retrieve the switch-case statement with the given ID. + /// Retrieve the switch-case statement with the given ID. SwitchCase *getSwitchCaseWithID(unsigned ID) { return Reader->getSwitchCaseWithID(ID); } }; -/// \brief Helper class that saves the current stream position and +/// Helper class that saves the current stream position and /// then restores it when destroyed. struct SavedStreamPosition { explicit SavedStreamPosition(llvm::BitstreamCursor &Cursor) - : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {} + : Cursor(Cursor), Offset(Cursor.GetCurrentBitNo()) {} ~SavedStreamPosition() { Cursor.JumpToBit(Offset); diff --git a/include/clang/Serialization/ASTWriter.h b/include/clang/Serialization/ASTWriter.h index 9437bf7f2c9f1..a93579930ff52 100644 --- a/include/clang/Serialization/ASTWriter.h +++ b/include/clang/Serialization/ASTWriter.h @@ -93,9 +93,8 @@ class SwitchCase; class TemplateParameterList; class Token; class TypeSourceInfo; -class VersionTuple; -/// \brief Writes an AST file containing the contents of a translation unit. +/// Writes an AST file containing the contents of a translation unit. /// /// The ASTWriter class produces a bitstream containing the serialized /// representation of a given abstract syntax tree and its supporting @@ -114,7 +113,7 @@ public: using RecordDataRef = ArrayRef<uint64_t>; private: - /// \brief Map that provides the ID numbers of each type within the + /// Map that provides the ID numbers of each type within the /// output stream, plus those deserialized from a chained PCH. /// /// The ID numbers of types are consecutive (in order of discovery) @@ -126,52 +125,52 @@ private: using TypeIdxMap = llvm::DenseMap<QualType, serialization::TypeIdx, serialization::UnsafeQualTypeDenseMapInfo>; - /// \brief The bitstream writer used to emit this precompiled header. + /// The bitstream writer used to emit this precompiled header. llvm::BitstreamWriter &Stream; /// The buffer associated with the bitstream. const SmallVectorImpl<char> &Buffer; - /// \brief The PCM manager which manages memory buffers for pcm files. + /// The PCM manager which manages memory buffers for pcm files. MemoryBufferCache &PCMCache; - /// \brief The ASTContext we're writing. + /// The ASTContext we're writing. ASTContext *Context = nullptr; - /// \brief The preprocessor we're writing. + /// The preprocessor we're writing. Preprocessor *PP = nullptr; - /// \brief The reader of existing AST files, if we're chaining. + /// The reader of existing AST files, if we're chaining. ASTReader *Chain = nullptr; - /// \brief The module we're currently writing, if any. + /// The module we're currently writing, if any. Module *WritingModule = nullptr; - /// \brief The base directory for any relative paths we emit. + /// The base directory for any relative paths we emit. std::string BaseDirectory; - /// \brief Indicates whether timestamps should be written to the produced + /// Indicates whether timestamps should be written to the produced /// module file. This is the case for files implicitly written to the /// module cache, where we need the timestamps to determine if the module /// file is up to date, but not otherwise. bool IncludeTimestamps; - /// \brief Indicates when the AST writing is actively performing + /// Indicates when the AST writing is actively performing /// serialization, rather than just queueing updates. bool WritingAST = false; - /// \brief Indicates that we are done serializing the collection of decls + /// Indicates that we are done serializing the collection of decls /// and types to emit. bool DoneWritingDeclsAndTypes = false; - /// \brief Indicates that the AST contained compiler errors. + /// Indicates that the AST contained compiler errors. bool ASTHasCompilerErrors = false; - /// \brief Mapping from input file entries to the index into the + /// Mapping from input file entries to the index into the /// offset table where information about that input file is stored. llvm::DenseMap<const FileEntry *, uint32_t> InputFileIDs; - /// \brief Stores a declaration or a type to be written to the AST file. + /// Stores a declaration or a type to be written to the AST file. class DeclOrType { public: DeclOrType(Decl *D) : Stored(D), IsType(false) {} @@ -195,16 +194,16 @@ private: bool IsType; }; - /// \brief The declarations and types to emit. + /// The declarations and types to emit. std::queue<DeclOrType> DeclTypesToEmit; - /// \brief The first ID number we can use for our own declarations. + /// The first ID number we can use for our own declarations. serialization::DeclID FirstDeclID = serialization::NUM_PREDEF_DECL_IDS; - /// \brief The decl ID that will be assigned to the next new decl. + /// The decl ID that will be assigned to the next new decl. serialization::DeclID NextDeclID = FirstDeclID; - /// \brief Map that provides the ID numbers of each declaration within + /// Map that provides the ID numbers of each declaration within /// the output stream, as well as those deserialized from a chained PCH. /// /// The ID numbers of declarations are consecutive (in order of @@ -212,35 +211,35 @@ private: /// unit, while 0 is reserved for NULL. llvm::DenseMap<const Decl *, serialization::DeclID> DeclIDs; - /// \brief Offset of each declaration in the bitstream, indexed by + /// Offset of each declaration in the bitstream, indexed by /// the declaration's ID. std::vector<serialization::DeclOffset> DeclOffsets; - /// \brief Sorted (by file offset) vector of pairs of file offset/DeclID. + /// Sorted (by file offset) vector of pairs of file offset/DeclID. using LocDeclIDsTy = SmallVector<std::pair<unsigned, serialization::DeclID>, 64>; struct DeclIDInFileInfo { LocDeclIDsTy DeclIDs; - /// \brief Set when the DeclIDs vectors from all files are joined, this + /// Set when the DeclIDs vectors from all files are joined, this /// indicates the index that this particular vector has in the global one. unsigned FirstDeclIndex; }; using FileDeclIDsTy = llvm::DenseMap<FileID, DeclIDInFileInfo *>; - /// \brief Map from file SLocEntries to info about the file-level declarations + /// Map from file SLocEntries to info about the file-level declarations /// that it contains. FileDeclIDsTy FileDeclIDs; void associateDeclWithFile(const Decl *D, serialization::DeclID); - /// \brief The first ID number we can use for our own types. + /// The first ID number we can use for our own types. serialization::TypeID FirstTypeID = serialization::NUM_PREDEF_TYPE_IDS; - /// \brief The type ID that will be assigned to the next new type. + /// The type ID that will be assigned to the next new type. serialization::TypeID NextTypeID = FirstTypeID; - /// \brief Map that provides the ID numbers of each type within the + /// Map that provides the ID numbers of each type within the /// output stream, plus those deserialized from a chained PCH. /// /// The ID numbers of types are consecutive (in order of discovery) @@ -251,17 +250,17 @@ private: /// Keys in the map never have const/volatile qualifiers. TypeIdxMap TypeIdxs; - /// \brief Offset of each type in the bitstream, indexed by + /// Offset of each type in the bitstream, indexed by /// the type's ID. std::vector<uint32_t> TypeOffsets; - /// \brief The first ID number we can use for our own identifiers. + /// The first ID number we can use for our own identifiers. serialization::IdentID FirstIdentID = serialization::NUM_PREDEF_IDENT_IDS; - /// \brief The identifier ID that will be assigned to the next new identifier. + /// The identifier ID that will be assigned to the next new identifier. serialization::IdentID NextIdentID = FirstIdentID; - /// \brief Map that provides the ID numbers of each identifier in + /// Map that provides the ID numbers of each identifier in /// the output stream. /// /// The ID numbers for identifiers are consecutive (in order of @@ -269,13 +268,13 @@ private: /// IdentifierInfo. llvm::MapVector<const IdentifierInfo *, serialization::IdentID> IdentifierIDs; - /// \brief The first ID number we can use for our own macros. + /// The first ID number we can use for our own macros. serialization::MacroID FirstMacroID = serialization::NUM_PREDEF_MACRO_IDS; - /// \brief The identifier ID that will be assigned to the next new identifier. + /// The identifier ID that will be assigned to the next new identifier. serialization::MacroID NextMacroID = FirstMacroID; - /// \brief Map that provides the ID numbers of each macro. + /// Map that provides the ID numbers of each macro. llvm::DenseMap<MacroInfo *, serialization::MacroID> MacroIDs; struct MacroInfoToEmitData { @@ -284,7 +283,7 @@ private: serialization::MacroID ID; }; - /// \brief The macro infos to emit. + /// The macro infos to emit. std::vector<MacroInfoToEmitData> MacroInfosToEmit; llvm::DenseMap<const IdentifierInfo *, uint64_t> IdentMacroDirectivesOffsetMap; @@ -292,46 +291,46 @@ private: /// @name FlushStmt Caches /// @{ - /// \brief Set of parent Stmts for the currently serializing sub-stmt. + /// Set of parent Stmts for the currently serializing sub-stmt. llvm::DenseSet<Stmt *> ParentStmts; - /// \brief Offsets of sub-stmts already serialized. The offset points + /// Offsets of sub-stmts already serialized. The offset points /// just after the stmt record. llvm::DenseMap<Stmt *, uint64_t> SubStmtEntries; /// @} - /// \brief Offsets of each of the identifier IDs into the identifier + /// Offsets of each of the identifier IDs into the identifier /// table. std::vector<uint32_t> IdentifierOffsets; - /// \brief The first ID number we can use for our own submodules. + /// The first ID number we can use for our own submodules. serialization::SubmoduleID FirstSubmoduleID = serialization::NUM_PREDEF_SUBMODULE_IDS; - /// \brief The submodule ID that will be assigned to the next new submodule. + /// The submodule ID that will be assigned to the next new submodule. serialization::SubmoduleID NextSubmoduleID = FirstSubmoduleID; - /// \brief The first ID number we can use for our own selectors. + /// The first ID number we can use for our own selectors. serialization::SelectorID FirstSelectorID = serialization::NUM_PREDEF_SELECTOR_IDS; - /// \brief The selector ID that will be assigned to the next new selector. + /// The selector ID that will be assigned to the next new selector. serialization::SelectorID NextSelectorID = FirstSelectorID; - /// \brief Map that provides the ID numbers of each Selector. + /// Map that provides the ID numbers of each Selector. llvm::MapVector<Selector, serialization::SelectorID> SelectorIDs; - /// \brief Offset of each selector within the method pool/selector + /// Offset of each selector within the method pool/selector /// table, indexed by the Selector ID (-1). std::vector<uint32_t> SelectorOffsets; - /// \brief Mapping from macro definitions (as they occur in the preprocessing + /// Mapping from macro definitions (as they occur in the preprocessing /// record) to the macro IDs. llvm::DenseMap<const MacroDefinitionRecord *, serialization::PreprocessedEntityID> MacroDefinitions; - /// \brief Cache of indices of anonymous declarations within their lexical + /// Cache of indices of anonymous declarations within their lexical /// contexts. llvm::DenseMap<const Decl *, unsigned> AnonymousDeclarationNumbers; @@ -376,17 +375,17 @@ private: using UpdateRecord = SmallVector<DeclUpdate, 1>; using DeclUpdateMap = llvm::MapVector<const Decl *, UpdateRecord>; - /// \brief Mapping from declarations that came from a chained PCH to the + /// Mapping from declarations that came from a chained PCH to the /// record containing modifications to them. DeclUpdateMap DeclUpdates; using FirstLatestDeclMap = llvm::DenseMap<Decl *, Decl *>; - /// \brief Map of first declarations from a chained PCH that point to the + /// Map of first declarations from a chained PCH that point to the /// most recent declarations in another PCH. FirstLatestDeclMap FirstLatestDecls; - /// \brief Declarations encountered that might be external + /// Declarations encountered that might be external /// definitions. /// /// We keep track of external definitions and other 'interesting' declarations @@ -400,7 +399,7 @@ private: SmallVector<uint64_t, 16> EagerlyDeserializedDecls; SmallVector<uint64_t, 16> ModularCodegenDecls; - /// \brief DeclContexts that have received extensions since their serialized + /// DeclContexts that have received extensions since their serialized /// form. /// /// For namespaces, when we're chaining and encountering a namespace, we check @@ -409,52 +408,52 @@ private: /// it. llvm::SmallSetVector<const DeclContext *, 16> UpdatedDeclContexts; - /// \brief Keeps track of declarations that we must emit, even though we're + /// Keeps track of declarations that we must emit, even though we're /// not guaranteed to be able to find them by walking the AST starting at the /// translation unit. SmallVector<const Decl *, 16> DeclsToEmitEvenIfUnreferenced; - /// \brief The set of Objective-C class that have categories we + /// The set of Objective-C class that have categories we /// should serialize. llvm::SetVector<ObjCInterfaceDecl *> ObjCClassesWithCategories; - /// \brief The set of declarations that may have redeclaration chains that + /// The set of declarations that may have redeclaration chains that /// need to be serialized. llvm::SmallVector<const Decl *, 16> Redeclarations; - /// \brief A cache of the first local declaration for "interesting" + /// A cache of the first local declaration for "interesting" /// redeclaration chains. llvm::DenseMap<const Decl *, const Decl *> FirstLocalDeclCache; - /// \brief Mapping from SwitchCase statements to IDs. + /// Mapping from SwitchCase statements to IDs. llvm::DenseMap<SwitchCase *, unsigned> SwitchCaseIDs; - /// \brief The number of statements written to the AST file. + /// The number of statements written to the AST file. unsigned NumStatements = 0; - /// \brief The number of macros written to the AST file. + /// The number of macros written to the AST file. unsigned NumMacros = 0; - /// \brief The number of lexical declcontexts written to the AST + /// The number of lexical declcontexts written to the AST /// file. unsigned NumLexicalDeclContexts = 0; - /// \brief The number of visible declcontexts written to the AST + /// The number of visible declcontexts written to the AST /// file. unsigned NumVisibleDeclContexts = 0; - /// \brief A mapping from each known submodule to its ID number, which will + /// A mapping from each known submodule to its ID number, which will /// be a positive integer. llvm::DenseMap<Module *, unsigned> SubmoduleIDs; - /// \brief A list of the module file extension writers. + /// A list of the module file extension writers. std::vector<std::unique_ptr<ModuleFileExtensionWriter>> ModuleFileExtensionWriters; - /// \brief Retrieve or create a submodule ID for this module. + /// Retrieve or create a submodule ID for this module. unsigned getSubmoduleID(Module *Mod); - /// \brief Write the given subexpression to the bitstream. + /// Write the given subexpression to the bitstream. void WriteSubStmt(Stmt *S); void WriteBlockInfoBlock(); @@ -540,7 +539,7 @@ private: Module *WritingModule); public: - /// \brief Create a new precompiled header writer that outputs to + /// Create a new precompiled header writer that outputs to /// the given bitstream. ASTWriter(llvm::BitstreamWriter &Stream, SmallVectorImpl<char> &Buffer, MemoryBufferCache &PCMCache, @@ -550,12 +549,12 @@ public: const LangOptions &getLangOpts() const; - /// \brief Get a timestamp for output into the AST file. The actual timestamp + /// Get a timestamp for output into the AST file. The actual timestamp /// of the specified file may be ignored if we have been instructed to not /// include timestamps in the output file. time_t getTimestampForOutput(const FileEntry *E) const; - /// \brief Write a precompiled header for the given semantic analysis. + /// Write a precompiled header for the given semantic analysis. /// /// \param SemaRef a reference to the semantic analysis object that processed /// the AST to be written into the precompiled header. @@ -573,46 +572,46 @@ public: Module *WritingModule, StringRef isysroot, bool hasErrors = false); - /// \brief Emit a token. + /// Emit a token. void AddToken(const Token &Tok, RecordDataImpl &Record); - /// \brief Emit a source location. + /// Emit a source location. void AddSourceLocation(SourceLocation Loc, RecordDataImpl &Record); - /// \brief Emit a source range. + /// Emit a source range. void AddSourceRange(SourceRange Range, RecordDataImpl &Record); - /// \brief Emit a reference to an identifier. + /// Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II, RecordDataImpl &Record); - /// \brief Get the unique number used to refer to the given selector. + /// Get the unique number used to refer to the given selector. serialization::SelectorID getSelectorRef(Selector Sel); - /// \brief Get the unique number used to refer to the given identifier. + /// Get the unique number used to refer to the given identifier. serialization::IdentID getIdentifierRef(const IdentifierInfo *II); - /// \brief Get the unique number used to refer to the given macro. + /// Get the unique number used to refer to the given macro. serialization::MacroID getMacroRef(MacroInfo *MI, const IdentifierInfo *Name); - /// \brief Determine the ID of an already-emitted macro. + /// Determine the ID of an already-emitted macro. serialization::MacroID getMacroID(MacroInfo *MI); uint64_t getMacroDirectivesOffset(const IdentifierInfo *Name); - /// \brief Emit a reference to a type. + /// Emit a reference to a type. void AddTypeRef(QualType T, RecordDataImpl &Record); - /// \brief Force a type to be emitted and get its ID. + /// Force a type to be emitted and get its ID. serialization::TypeID GetOrCreateTypeID(QualType T); - /// \brief Determine the type ID of an already-emitted type. + /// Determine the type ID of an already-emitted type. serialization::TypeID getTypeID(QualType T) const; - /// \brief Find the first local declaration of a given local redeclarable + /// Find the first local declaration of a given local redeclarable /// decl. const Decl *getFirstLocalDecl(const Decl *D); - /// \brief Is this a local declaration (that is, one that will be written to + /// Is this a local declaration (that is, one that will be written to /// our AST file)? This is the case for declarations that are neither imported /// from another AST file nor predefined. bool IsLocalDecl(const Decl *D) { @@ -623,52 +622,52 @@ public: I->second >= serialization::NUM_PREDEF_DECL_IDS); }; - /// \brief Emit a reference to a declaration. + /// Emit a reference to a declaration. void AddDeclRef(const Decl *D, RecordDataImpl &Record); - /// \brief Force a declaration to be emitted and get its ID. + /// Force a declaration to be emitted and get its ID. serialization::DeclID GetDeclRef(const Decl *D); - /// \brief Determine the declaration ID of an already-emitted + /// Determine the declaration ID of an already-emitted /// declaration. serialization::DeclID getDeclID(const Decl *D); unsigned getAnonymousDeclarationNumber(const NamedDecl *D); - /// \brief Add a string to the given record. + /// 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 + /// 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. + /// 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. + /// Emit the current record with the given path as a blob. void EmitRecordWithPath(unsigned Abbrev, RecordDataRef Record, StringRef Path); - /// \brief Add a version tuple to the given record + /// Add a version tuple to the given record void AddVersionTuple(const VersionTuple &Version, RecordDataImpl &Record); - /// \brief Retrieve or create a submodule ID for this module, or return 0 if + /// Retrieve or create a submodule ID for this module, or return 0 if /// the submodule is neither local (a submodle of the currently-written module) /// nor from an imported module. unsigned getLocalOrImportedSubmoduleID(Module *Mod); - /// \brief Note that the identifier II occurs at the given offset + /// Note that the identifier II occurs at the given offset /// within the identifier table. void SetIdentifierOffset(const IdentifierInfo *II, uint32_t Offset); - /// \brief Note that the selector Sel occurs at the given offset + /// Note that the selector Sel occurs at the given offset /// within the method pool/selector table. void SetSelectorOffset(Selector Sel, uint32_t Offset); - /// \brief Record an ID for the given switch-case statement. + /// Record an ID for the given switch-case statement. unsigned RecordSwitchCaseID(SwitchCase *S); - /// \brief Retrieve the ID for the given switch-case statement. + /// Retrieve the ID for the given switch-case statement. unsigned getSwitchCaseID(SwitchCase *S); void ClearSwitchCaseIDs(); @@ -743,21 +742,21 @@ private: const RecordDecl *Record) override; }; -/// \brief An object for streaming information to a record. +/// An object for streaming information to a record. class ASTRecordWriter { ASTWriter *Writer; ASTWriter::RecordDataImpl *Record; - /// \brief Statements that we've encountered while serializing a + /// Statements that we've encountered while serializing a /// declaration or type. SmallVector<Stmt *, 16> StmtsToEmit; - /// \brief Indices of record elements that describe offsets within the + /// Indices of record elements that describe offsets within the /// bitcode. These will be converted to offsets relative to the current /// record when emitted. SmallVector<unsigned, 8> OffsetIndices; - /// \brief Flush all of the statements and expressions that have + /// Flush all of the statements and expressions that have /// been added to the queue via AddStmt(). void FlushStmts(); void FlushSubStmts(); @@ -787,10 +786,10 @@ public: ASTRecordWriter(const ASTRecordWriter &) = delete; ASTRecordWriter &operator=(const ASTRecordWriter &) = delete; - /// \brief Extract the underlying record storage. + /// Extract the underlying record storage. ASTWriter::RecordDataImpl &getRecordData() const { return *Record; } - /// \brief Minimal vector-like interface. + /// Minimal vector-like interface. /// @{ void push_back(uint64_t N) { Record->push_back(N); } template<typename InputIterator> @@ -802,7 +801,7 @@ public: uint64_t &operator[](size_t N) { return (*Record)[N]; } /// @} - /// \brief Emit the record to the stream, followed by its substatements, and + /// Emit the record to the stream, followed by its substatements, and /// return its offset. // FIXME: Allow record producers to suggest Abbrevs. uint64_t Emit(unsigned Code, unsigned Abbrev = 0) { @@ -813,7 +812,7 @@ public: return Offset; } - /// \brief Emit the record to the stream, preceded by its substatements. + /// Emit the record to the stream, preceded by its substatements. uint64_t EmitStmt(unsigned Code, unsigned Abbrev = 0) { FlushSubStmts(); PrepareToEmit(Writer->Stream.GetCurrentBitNo()); @@ -821,14 +820,14 @@ public: return Writer->Stream.GetCurrentBitNo(); } - /// \brief Add a bit offset into the record. This will be converted into an + /// Add a bit offset into the record. This will be converted into an /// offset relative to the current record when emitted. void AddOffset(uint64_t BitOffset) { OffsetIndices.push_back(Record->size()); Record->push_back(BitOffset); } - /// \brief Add the given statement or expression to the queue of + /// Add the given statement or expression to the queue of /// statements to emit. /// /// This routine should be used when emitting types and declarations @@ -839,74 +838,74 @@ public: StmtsToEmit.push_back(S); } - /// \brief Add a definition for the given function to the queue of statements + /// Add a definition for the given function to the queue of statements /// to emit. void AddFunctionDefinition(const FunctionDecl *FD); - /// \brief Emit a source location. + /// Emit a source location. void AddSourceLocation(SourceLocation Loc) { return Writer->AddSourceLocation(Loc, *Record); } - /// \brief Emit a source range. + /// Emit a source range. void AddSourceRange(SourceRange Range) { return Writer->AddSourceRange(Range, *Record); } - /// \brief Emit an integral value. + /// Emit an integral value. void AddAPInt(const llvm::APInt &Value); - /// \brief Emit a signed integral value. + /// Emit a signed integral value. void AddAPSInt(const llvm::APSInt &Value); - /// \brief Emit a floating-point value. + /// Emit a floating-point value. void AddAPFloat(const llvm::APFloat &Value); - /// \brief Emit a reference to an identifier. + /// Emit a reference to an identifier. void AddIdentifierRef(const IdentifierInfo *II) { return Writer->AddIdentifierRef(II, *Record); } - /// \brief Emit a Selector (which is a smart pointer reference). + /// Emit a Selector (which is a smart pointer reference). void AddSelectorRef(Selector S); - /// \brief Emit a CXXTemporary. + /// Emit a CXXTemporary. void AddCXXTemporary(const CXXTemporary *Temp); - /// \brief Emit a C++ base specifier. + /// Emit a C++ base specifier. void AddCXXBaseSpecifier(const CXXBaseSpecifier &Base); - /// \brief Emit a set of C++ base specifiers. + /// Emit a set of C++ base specifiers. void AddCXXBaseSpecifiers(ArrayRef<CXXBaseSpecifier> Bases); - /// \brief Emit a reference to a type. + /// Emit a reference to a type. void AddTypeRef(QualType T) { return Writer->AddTypeRef(T, *Record); } - /// \brief Emits a reference to a declarator info. + /// Emits a reference to a declarator info. void AddTypeSourceInfo(TypeSourceInfo *TInfo); - /// \brief Emits a type with source-location information. + /// Emits source location information for a type. Does not emit the type. void AddTypeLoc(TypeLoc TL); - /// \brief Emits a template argument location info. + /// Emits a template argument location info. void AddTemplateArgumentLocInfo(TemplateArgument::ArgKind Kind, const TemplateArgumentLocInfo &Arg); - /// \brief Emits a template argument location. + /// Emits a template argument location. void AddTemplateArgumentLoc(const TemplateArgumentLoc &Arg); - /// \brief Emits an AST template argument list info. + /// Emits an AST template argument list info. void AddASTTemplateArgumentListInfo( const ASTTemplateArgumentListInfo *ASTTemplArgList); - /// \brief Emit a reference to a declaration. + /// Emit a reference to a declaration. void AddDeclRef(const Decl *D) { return Writer->AddDeclRef(D, *Record); } - /// \brief Emit a declaration name. + /// Emit a declaration name. void AddDeclarationName(DeclarationName Name); void AddDeclarationNameLoc(const DeclarationNameLoc &DNLoc, @@ -915,52 +914,52 @@ public: void AddQualifierInfo(const QualifierInfo &Info); - /// \brief Emit a nested name specifier. + /// Emit a nested name specifier. void AddNestedNameSpecifier(NestedNameSpecifier *NNS); - /// \brief Emit a nested name specifier with source-location information. + /// Emit a nested name specifier with source-location information. void AddNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS); - /// \brief Emit a template name. + /// Emit a template name. void AddTemplateName(TemplateName Name); - /// \brief Emit a template argument. + /// Emit a template argument. void AddTemplateArgument(const TemplateArgument &Arg); - /// \brief Emit a template parameter list. + /// Emit a template parameter list. void AddTemplateParameterList(const TemplateParameterList *TemplateParams); - /// \brief Emit a template argument list. + /// Emit a template argument list. void AddTemplateArgumentList(const TemplateArgumentList *TemplateArgs); - /// \brief Emit a UnresolvedSet structure. + /// Emit a UnresolvedSet structure. void AddUnresolvedSet(const ASTUnresolvedSet &Set); - /// \brief Emit a CXXCtorInitializer array. + /// Emit a CXXCtorInitializer array. void AddCXXCtorInitializers(ArrayRef<CXXCtorInitializer *> CtorInits); void AddCXXDefinitionData(const CXXRecordDecl *D); - /// \brief Emit a string. + /// Emit a string. void AddString(StringRef Str) { return Writer->AddString(Str, *Record); } - /// \brief Emit a path. + /// Emit a path. void AddPath(StringRef Path) { return Writer->AddPath(Path, *Record); } - /// \brief Emit a version tuple. + /// Emit a version tuple. void AddVersionTuple(const VersionTuple &Version) { return Writer->AddVersionTuple(Version, *Record); } - /// \brief Emit a list of attributes. + /// Emit a list of attributes. void AddAttributes(ArrayRef<const Attr*> Attrs); }; -/// \brief AST and semantic-analysis consumer that generates a +/// AST and semantic-analysis consumer that generates a /// precompiled header from the parsed source code. class PCHGenerator : public SemaConsumer { const Preprocessor &PP; diff --git a/include/clang/Serialization/ContinuousRangeMap.h b/include/clang/Serialization/ContinuousRangeMap.h index 24bfadd0f8677..2f909965db7ef 100644 --- a/include/clang/Serialization/ContinuousRangeMap.h +++ b/include/clang/Serialization/ContinuousRangeMap.h @@ -16,6 +16,7 @@ #define LLVM_CLANG_SERIALIZATION_CONTINUOUSRANGEMAP_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include <algorithm> #include <cassert> @@ -23,7 +24,7 @@ namespace clang { -/// \brief A map from continuous integer ranges to some value, with a very +/// A map from continuous integer ranges to some value, with a very /// specialized interface. /// /// CRM maps from integer ranges to values. The ranges are continuous, i.e. @@ -106,7 +107,7 @@ public: reference back() { return Rep.back(); } const_reference back() const { return Rep.back(); } - /// \brief An object that helps properly build a continuous range map + /// An object that helps properly build a continuous range map /// from a set of values. class Builder { ContinuousRangeMap &Self; @@ -117,7 +118,7 @@ public: Builder &operator=(const Builder&) = delete; ~Builder() { - std::sort(Self.Rep.begin(), Self.Rep.end(), Compare()); + llvm::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 diff --git a/include/clang/Serialization/GlobalModuleIndex.h b/include/clang/Serialization/GlobalModuleIndex.h index 0f14eca0fd86a..f48d0cf17c493 100644 --- a/include/clang/Serialization/GlobalModuleIndex.h +++ b/include/clang/Serialization/GlobalModuleIndex.h @@ -47,7 +47,7 @@ using llvm::SmallVectorImpl; using llvm::StringRef; using serialization::ModuleFile; -/// \brief A global index for a set of module files, providing information about +/// A global index for a set of module files, providing information about /// the identifiers within those module files. /// /// The global index is an aid for name lookup into modules, offering a central @@ -59,64 +59,64 @@ using serialization::ModuleFile; /// imported, and can be queried to determine which modules the current /// translation could or should load to fix a problem. class GlobalModuleIndex { - /// \brief Buffer containing the index file, which is lazily accessed so long + /// Buffer containing the index file, which is lazily accessed so long /// as the global module index is live. std::unique_ptr<llvm::MemoryBuffer> Buffer; - /// \brief The hash table. + /// The hash table. /// /// This pointer actually points to a IdentifierIndexTable object, /// but that type is only accessible within the implementation of /// GlobalModuleIndex. void *IdentifierIndex; - /// \brief Information about a given module file. + /// Information about a given module file. struct ModuleInfo { ModuleInfo() : File(), Size(), ModTime() { } - /// \brief The module file, once it has been resolved. + /// The module file, once it has been resolved. ModuleFile *File; - /// \brief The module file name. + /// The module file name. std::string FileName; - /// \brief Size of the module file at the time the global index was built. + /// Size of the module file at the time the global index was built. off_t Size; - /// \brief Modification time of the module file at the time the global + /// Modification time of the module file at the time the global /// index was built. time_t ModTime; - /// \brief The module IDs on which this module directly depends. + /// The module IDs on which this module directly depends. /// FIXME: We don't really need a vector here. llvm::SmallVector<unsigned, 4> Dependencies; }; - /// \brief A mapping from module IDs to information about each module. + /// A mapping from module IDs to information about each module. /// /// This vector may have gaps, if module files have been removed or have /// been updated since the index was built. A gap is indicated by an empty /// file name. llvm::SmallVector<ModuleInfo, 16> Modules; - /// \brief Lazily-populated mapping from module files to their + /// Lazily-populated mapping from module files to their /// corresponding index into the \c Modules vector. llvm::DenseMap<ModuleFile *, unsigned> ModulesByFile; - /// \brief The set of modules that have not yet been resolved. + /// The set of modules that have not yet been resolved. /// /// The string is just the name of the module itself, which maps to the /// module ID. llvm::StringMap<unsigned> UnresolvedModules; - /// \brief The number of identifier lookups we performed. + /// The number of identifier lookups we performed. unsigned NumIdentifierLookups; - /// \brief The number of identifier lookup hits, where we recognize the + /// The number of identifier lookup hits, where we recognize the /// identifier. unsigned NumIdentifierLookupHits; - /// \brief Internal constructor. Use \c readIndex() to read an index. + /// Internal constructor. Use \c readIndex() to read an index. explicit GlobalModuleIndex(std::unique_ptr<llvm::MemoryBuffer> Buffer, llvm::BitstreamCursor Cursor); @@ -126,20 +126,20 @@ class GlobalModuleIndex { public: ~GlobalModuleIndex(); - /// \brief An error code returned when trying to read an index. + /// An error code returned when trying to read an index. enum ErrorCode { - /// \brief No error occurred. + /// No error occurred. EC_None, - /// \brief No index was found. + /// No index was found. EC_NotFound, - /// \brief Some other process is currently building the index; it is not + /// Some other process is currently building the index; it is not /// available yet. EC_Building, - /// \brief There was an unspecified I/O error reading or writing the index. + /// There was an unspecified I/O error reading or writing the index. EC_IOError }; - /// \brief Read a global index file for the given directory. + /// Read a global index file for the given directory. /// /// \param Path The path to the specific module cache where the module files /// for the intended configuration reside. @@ -149,26 +149,26 @@ public: static std::pair<GlobalModuleIndex *, ErrorCode> readIndex(StringRef Path); - /// \brief Returns an iterator for identifiers stored in the index table. + /// Returns an iterator for identifiers stored in the index table. /// /// The caller accepts ownership of the returned object. IdentifierIterator *createIdentifierIterator() const; - /// \brief Retrieve the set of modules that have up-to-date indexes. + /// Retrieve the set of modules that have up-to-date indexes. /// /// \param ModuleFiles Will be populated with the set of module files that /// have been indexed. void getKnownModules(SmallVectorImpl<ModuleFile *> &ModuleFiles); - /// \brief Retrieve the set of module files on which the given module file + /// Retrieve the set of module files on which the given module file /// directly depends. void getModuleDependencies(ModuleFile *File, SmallVectorImpl<ModuleFile *> &Dependencies); - /// \brief A set of module files in which we found a result. + /// A set of module files in which we found a result. typedef llvm::SmallPtrSet<ModuleFile *, 4> HitSet; - /// \brief Look for all of the module files with information about the given + /// Look for all of the module files with information about the given /// identifier, e.g., a global function, variable, or type with that name. /// /// \param Name The identifier to look for. @@ -179,19 +179,19 @@ public: /// \returns true if the identifier is known to the index, false otherwise. bool lookupIdentifier(StringRef Name, HitSet &Hits); - /// \brief Note that the given module file has been loaded. + /// Note that the given module file has been loaded. /// /// \returns false if the global module index has information about this /// module file, and true otherwise. bool loadedModuleFile(ModuleFile *File); - /// \brief Print statistics to standard error. + /// Print statistics to standard error. void printStats(); - /// \brief Print debugging view to standard error. + /// Print debugging view to standard error. void dump(); - /// \brief Write a global index into the given + /// Write a global index into the given /// /// \param FileMgr The file manager to use to load module files. /// \param PCHContainerRdr - The PCHContainerOperations to use for loading and diff --git a/include/clang/Serialization/Module.h b/include/clang/Serialization/Module.h index 4e4bf44f34920..653981b1427ca 100644 --- a/include/clang/Serialization/Module.h +++ b/include/clang/Serialization/Module.h @@ -1,4 +1,4 @@ -//===--- Module.h - Module description --------------------------*- C++ -*-===// +//===- Module.h - Module description ----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,45 +15,52 @@ #ifndef LLVM_CLANG_SERIALIZATION_MODULE_H #define LLVM_CLANG_SERIALIZATION_MODULE_H -#include "clang/Basic/FileManager.h" #include "clang/Basic/Module.h" #include "clang/Basic/SourceLocation.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ContinuousRangeMap.h" #include "clang/Serialization/ModuleFileExtension.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/ADT/SetVector.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Support/Endian.h" +#include <cassert> +#include <cstdint> #include <memory> #include <string> - -namespace llvm { -template <typename Info> class OnDiskChainedHashTable; -template <typename Info> class OnDiskIterableChainedHashTable; -} +#include <vector> namespace clang { -class DeclContext; -class Module; +class FileEntry; namespace serialization { -namespace reader { - class ASTDeclContextNameLookupTrait; -} - -/// \brief Specifies the kind of module that has been loaded. +/// Specifies the kind of module that has been loaded. enum ModuleKind { - 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. - MK_PrebuiltModule ///< File is from a prebuilt module path. + /// File is an implicitly-loaded module. + MK_ImplicitModule, + + /// File is an explicitly-loaded module. + MK_ExplicitModule, + + /// File is a PCH file treated as such. + MK_PCH, + + /// File is a PCH file treated as the preamble. + MK_Preamble, + + /// File is a PCH file treated as the actual main file. + MK_MainFile, + + /// File is from a prebuilt module path. + MK_PrebuiltModule }; -/// \brief The input file that has been loaded from this AST file, along with +/// The input file that has been loaded from this AST file, along with /// bools indicating whether this was an overridden buffer or if it was /// out-of-date or not-found. class InputFile { @@ -65,7 +72,8 @@ class InputFile { llvm::PointerIntPair<const FileEntry *, 2, unsigned> Val; public: - InputFile() {} + InputFile() = default; + InputFile(const FileEntry *File, bool isOverridden = false, bool isOutOfDate = false) { assert(!(isOverridden && isOutOfDate) && @@ -90,7 +98,7 @@ public: bool isNotFound() const { return Val.getInt() == NotFound; } }; -/// \brief Information about a module that has been loaded by the ASTReader. +/// Information about a module that has been loaded by the ASTReader. /// /// Each instance of the Module class corresponds to a single AST file, which /// may be a precompiled header, precompiled preamble, a module, or an AST file @@ -105,81 +113,84 @@ public: // === General information === - /// \brief The index of this module in the list of modules. + /// The index of this module in the list of modules. unsigned Index = 0; - /// \brief The type of this module. + /// The type of this module. ModuleKind Kind; - /// \brief The file name of the module file. + /// The file name of the module file. std::string FileName; - /// \brief The name of the module. + /// The name of the module. std::string ModuleName; - /// \brief The base directory of the module. + /// The base directory of the module. std::string BaseDirectory; std::string getTimestampFilename() const { return FileName + ".timestamp"; } - /// \brief The original source file name that was used to build the + /// The original source file name that was used to build the /// primary AST file, which may have been modified for /// relocatable-pch support. std::string OriginalSourceFileName; - /// \brief The actual original source file name that was used to + /// The actual original source file name that was used to /// build this AST file. std::string ActualOriginalSourceFileName; - /// \brief The file ID for the original source file that was used to + /// The file ID for the original source file that was used to /// build this AST file. FileID OriginalSourceFileID; - /// \brief The directory that the PCH was originally created in. Used to + /// The directory that the PCH was originally created in. Used to /// allow resolving headers even after headers+PCH was moved to a new path. std::string OriginalDir; std::string ModuleMapPath; - /// \brief Whether this precompiled header is a relocatable PCH file. + /// Whether this precompiled header is a relocatable PCH file. bool RelocatablePCH = false; - /// \brief Whether timestamps are included in this module file. + /// Whether timestamps are included in this module file. bool HasTimestamps = false; - /// \brief The file entry for the module file. + /// Whether the PCH has a corresponding object file. + bool PCHHasObjectFile = false; + + /// The file entry for the module file. const FileEntry *File = nullptr; /// The signature of the module file, which may be used instead of the size /// and modification time to identify this particular file. ASTFileSignature Signature; - /// \brief Whether this module has been directly imported by the + /// Whether this module has been directly imported by the /// user. bool DirectlyImported = false; - /// \brief The generation of which this module file is a part. + /// The generation of which this module file is a part. unsigned Generation; /// The memory buffer that stores the data associated with /// this AST file, owned by the PCMCache in the ModuleManager. llvm::MemoryBuffer *Buffer; - /// \brief The size of this file, in bits. + /// The size of this file, in bits. uint64_t SizeInBits = 0; - /// \brief The global bit offset (or base) of this module + /// The global bit offset (or base) of this module uint64_t GlobalBitOffset = 0; - /// \brief The serialized bitstream data for this file. + /// The serialized bitstream data for this file. StringRef Data; - /// \brief The main bitstream cursor for the main block. + /// The main bitstream cursor for the main block. llvm::BitstreamCursor Stream; - /// \brief The source location where the module was explicitly or implicitly + /// The source location where the module was explicitly or implicitly /// imported in the local translation unit. /// /// If module A depends on and imports module B, both modules will have the @@ -190,10 +201,10 @@ public: /// made visible, just when the first submodule of that module was imported. SourceLocation DirectImportLoc; - /// \brief The source location where this module was first imported. + /// The source location where this module was first imported. SourceLocation ImportLoc; - /// \brief The first source location in this module. + /// The first source location in this module. SourceLocation FirstLoc; /// The list of extension readers that are attached to this module @@ -205,20 +216,21 @@ public: StringRef ModuleOffsetMap; // === Input Files === - /// \brief The cursor to the start of the input-files block. + + /// The cursor to the start of the input-files block. llvm::BitstreamCursor InputFilesCursor; - /// \brief Offsets for all of the input file entries in the AST file. + /// Offsets for all of the input file entries in the AST file. const llvm::support::unaligned_uint64_t *InputFileOffsets = nullptr; - /// \brief The input files that have been loaded from this AST file. + /// The input files that have been loaded from this AST file. std::vector<InputFile> InputFilesLoaded; // All user input files reside at the index range [0, NumUserInputFiles), and // system input files reside at [NumUserInputFiles, InputFilesLoaded.size()). unsigned NumUserInputFiles = 0; - /// \brief If non-zero, specifies the time when we last validated input + /// If non-zero, specifies the time when we last validated input /// files. Zero means we never validated them. /// /// The time is specified in seconds since the start of the Epoch. @@ -226,153 +238,160 @@ public: // === Source Locations === - /// \brief Cursor used to read source location entries. + /// Cursor used to read source location entries. llvm::BitstreamCursor SLocEntryCursor; - /// \brief The number of source location entries in this AST file. + /// The number of source location entries in this AST file. unsigned LocalNumSLocEntries = 0; - /// \brief The base ID in the source manager's view of this module. + /// The base ID in the source manager's view of this module. int SLocEntryBaseID = 0; - /// \brief The base offset in the source manager's view of this module. + /// The base offset in the source manager's view of this module. unsigned SLocEntryBaseOffset = 0; - /// \brief Offsets for all of the source location entries in the + /// Offsets for all of the source location entries in the /// AST file. const uint32_t *SLocEntryOffsets = nullptr; - /// \brief SLocEntries that we're going to preload. + /// SLocEntries that we're going to preload. SmallVector<uint64_t, 4> PreloadSLocEntries; - /// \brief Remapping table for source locations in this module. + /// Remapping table for source locations in this module. ContinuousRangeMap<uint32_t, int, 2> SLocRemap; // === Identifiers === - /// \brief The number of identifiers in this AST file. + /// The number of identifiers in this AST file. unsigned LocalNumIdentifiers = 0; - /// \brief Offsets into the identifier table data. + /// Offsets into the identifier table data. /// /// This array is indexed by the identifier ID (-1), and provides /// the offset into IdentifierTableData where the string data is /// stored. const uint32_t *IdentifierOffsets = nullptr; - /// \brief Base identifier ID for identifiers local to this module. + /// Base identifier ID for identifiers local to this module. serialization::IdentID BaseIdentifierID = 0; - /// \brief Remapping table for identifier IDs in this module. + /// Remapping table for identifier IDs in this module. ContinuousRangeMap<uint32_t, int, 2> IdentifierRemap; - /// \brief Actual data for the on-disk hash table of identifiers. + /// Actual data for the on-disk hash table of identifiers. /// /// This pointer points into a memory buffer, where the on-disk hash /// table for identifiers actually lives. const char *IdentifierTableData = nullptr; - /// \brief A pointer to an on-disk hash table of opaque type + /// A pointer to an on-disk hash table of opaque type /// IdentifierHashTable. void *IdentifierLookupTable = nullptr; - /// \brief Offsets of identifiers that we're going to preload within + /// Offsets of identifiers that we're going to preload within /// IdentifierTableData. std::vector<unsigned> PreloadIdentifierOffsets; // === Macros === - /// \brief The cursor to the start of the preprocessor block, which stores + /// The cursor to the start of the preprocessor block, which stores /// all of the macro definitions. llvm::BitstreamCursor MacroCursor; - /// \brief The number of macros in this AST file. + /// The number of macros in this AST file. unsigned LocalNumMacros = 0; - /// \brief Offsets of macros in the preprocessor block. + /// Offsets of macros in the preprocessor block. /// /// This array is indexed by the macro ID (-1), and provides /// the offset into the preprocessor block where macro definitions are /// stored. const uint32_t *MacroOffsets = nullptr; - /// \brief Base macro ID for macros local to this module. + /// Base macro ID for macros local to this module. serialization::MacroID BaseMacroID = 0; - /// \brief Remapping table for macro IDs in this module. + /// Remapping table for macro IDs in this module. ContinuousRangeMap<uint32_t, int, 2> MacroRemap; - /// \brief The offset of the start of the set of defined macros. + /// The offset of the start of the set of defined macros. uint64_t MacroStartOffset = 0; // === Detailed PreprocessingRecord === - /// \brief The cursor to the start of the (optional) detailed preprocessing + /// The cursor to the start of the (optional) detailed preprocessing /// record block. llvm::BitstreamCursor PreprocessorDetailCursor; - /// \brief The offset of the start of the preprocessor detail cursor. + /// The offset of the start of the preprocessor detail cursor. uint64_t PreprocessorDetailStartOffset = 0; - /// \brief Base preprocessed entity ID for preprocessed entities local to + /// Base preprocessed entity ID for preprocessed entities local to /// this module. serialization::PreprocessedEntityID BasePreprocessedEntityID = 0; - /// \brief Remapping table for preprocessed entity IDs in this module. + /// Remapping table for preprocessed entity IDs in this module. ContinuousRangeMap<uint32_t, int, 2> PreprocessedEntityRemap; const PPEntityOffset *PreprocessedEntityOffsets = nullptr; unsigned NumPreprocessedEntities = 0; + /// Base ID for preprocessed skipped ranges local to this module. + unsigned BasePreprocessedSkippedRangeID = 0; + + const PPSkippedRange *PreprocessedSkippedRangeOffsets = nullptr; + unsigned NumPreprocessedSkippedRanges = 0; + // === Header search information === - /// \brief The number of local HeaderFileInfo structures. + /// The number of local HeaderFileInfo structures. unsigned LocalNumHeaderFileInfos = 0; - /// \brief Actual data for the on-disk hash table of header file + /// Actual data for the on-disk hash table of header file /// information. /// /// This pointer points into a memory buffer, where the on-disk hash /// table for header file information actually lives. const char *HeaderFileInfoTableData = nullptr; - /// \brief The on-disk hash table that contains information about each of + /// The on-disk hash table that contains information about each of /// the header files. void *HeaderFileInfoTable = nullptr; // === Submodule information === - /// \brief The number of submodules in this module. + + /// The number of submodules in this module. unsigned LocalNumSubmodules = 0; - /// \brief Base submodule ID for submodules local to this module. + /// Base submodule ID for submodules local to this module. serialization::SubmoduleID BaseSubmoduleID = 0; - /// \brief Remapping table for submodule IDs in this module. + /// Remapping table for submodule IDs in this module. ContinuousRangeMap<uint32_t, int, 2> SubmoduleRemap; // === Selectors === - /// \brief The number of selectors new to this file. + /// The number of selectors new to this file. /// /// This is the number of entries in SelectorOffsets. unsigned LocalNumSelectors = 0; - /// \brief Offsets into the selector lookup table's data array + /// Offsets into the selector lookup table's data array /// where each selector resides. const uint32_t *SelectorOffsets = nullptr; - /// \brief Base selector ID for selectors local to this module. + /// Base selector ID for selectors local to this module. serialization::SelectorID BaseSelectorID = 0; - /// \brief Remapping table for selector IDs in this module. + /// Remapping table for selector IDs in this module. ContinuousRangeMap<uint32_t, int, 2> SelectorRemap; - /// \brief A pointer to the character data that comprises the selector table + /// A pointer to the character data that comprises the selector table /// /// The SelectorOffsets table refers into this memory. const unsigned char *SelectorLookupTableData = nullptr; - /// \brief A pointer to an on-disk hash table of opaque type + /// A pointer to an on-disk hash table of opaque type /// ASTSelectorLookupTable. /// /// This hash table provides the IDs of all selectors, and the associated @@ -386,20 +405,20 @@ public: /// jump around with these in context. llvm::BitstreamCursor DeclsCursor; - /// \brief The number of declarations in this AST file. + /// The number of declarations in this AST file. unsigned LocalNumDecls = 0; - /// \brief Offset of each declaration within the bitstream, indexed + /// Offset of each declaration within the bitstream, indexed /// by the declaration ID (-1). const DeclOffset *DeclOffsets = nullptr; - /// \brief Base declaration ID for declarations local to this module. + /// Base declaration ID for declarations local to this module. serialization::DeclID BaseDeclID = 0; - /// \brief Remapping table for declaration IDs in this module. + /// Remapping table for declaration IDs in this module. ContinuousRangeMap<uint32_t, int, 2> DeclRemap; - /// \brief Mapping from the module files that this module file depends on + /// Mapping from the module files that this module file depends on /// to the base declaration ID for that module as it is understood within this /// module. /// @@ -408,64 +427,64 @@ public: /// as a local ID (for this module file). llvm::DenseMap<ModuleFile *, serialization::DeclID> GlobalToLocalDeclIDs; - /// \brief Array of file-level DeclIDs sorted by file. + /// Array of file-level DeclIDs sorted by file. const serialization::DeclID *FileSortedDecls = nullptr; unsigned NumFileSortedDecls = 0; - /// \brief Array of category list location information within this + /// Array of category list location information within this /// module file, sorted by the definition ID. const serialization::ObjCCategoriesInfo *ObjCCategoriesMap = nullptr; - /// \brief The number of redeclaration info entries in ObjCCategoriesMap. + /// The number of redeclaration info entries in ObjCCategoriesMap. unsigned LocalNumObjCCategoriesInMap = 0; - /// \brief The Objective-C category lists for categories known to this + /// The Objective-C category lists for categories known to this /// module. SmallVector<uint64_t, 1> ObjCCategories; // === Types === - /// \brief The number of types in this AST file. + /// The number of types in this AST file. unsigned LocalNumTypes = 0; - /// \brief Offset of each type within the bitstream, indexed by the + /// Offset of each type within the bitstream, indexed by the /// type ID, or the representation of a Type*. const uint32_t *TypeOffsets = nullptr; - /// \brief Base type ID for types local to this module as represented in + /// Base type ID for types local to this module as represented in /// the global type ID space. serialization::TypeID BaseTypeIndex = 0; - /// \brief Remapping table for type IDs in this module. + /// Remapping table for type IDs in this module. ContinuousRangeMap<uint32_t, int, 2> TypeRemap; // === Miscellaneous === - /// \brief Diagnostic IDs and their mappings that the user changed. + /// Diagnostic IDs and their mappings that the user changed. SmallVector<uint64_t, 8> PragmaDiagMappings; - /// \brief List of modules which depend on this module + /// List of modules which depend on this module llvm::SetVector<ModuleFile *> ImportedBy; - /// \brief List of modules which this module depends on + /// List of modules which this module depends on llvm::SetVector<ModuleFile *> Imports; - /// \brief Determine whether this module was directly imported at + /// Determine whether this module was directly imported at /// any point during translation. bool isDirectlyImported() const { return DirectlyImported; } - /// \brief Is this a module file for a module (rather than a PCH or similar). + /// Is this a module file for a module (rather than a PCH or similar). bool isModule() const { return Kind == MK_ImplicitModule || Kind == MK_ExplicitModule || Kind == MK_PrebuiltModule; } - /// \brief Dump debugging output for this module. + /// Dump debugging output for this module. void dump(); }; -} // end namespace serialization +} // namespace serialization -} // end namespace clang +} // namespace clang -#endif +#endif // LLVM_CLANG_SERIALIZATION_MODULE_H diff --git a/include/clang/Serialization/ModuleManager.h b/include/clang/Serialization/ModuleManager.h index 147a6910aa295..e101e60b21a3d 100644 --- a/include/clang/Serialization/ModuleManager.h +++ b/include/clang/Serialization/ModuleManager.h @@ -45,45 +45,45 @@ class PCHContainerReader; namespace serialization { -/// \brief Manages the set of modules loaded by an AST reader. +/// Manages the set of modules loaded by an AST reader. class ModuleManager { - /// \brief The chain of AST files, in the order in which we started to load + /// The chain of AST files, in the order in which we started to load /// them (this order isn't really useful for anything). SmallVector<std::unique_ptr<ModuleFile>, 2> Chain; - /// \brief The chain of non-module PCH files. The first entry is the one named + /// The chain of non-module PCH files. The first entry is the one named /// by the user, the last one is the one that doesn't depend on anything /// further. SmallVector<ModuleFile *, 2> PCHChain; - // \brief The roots of the dependency DAG of AST files. This is used + // The roots of the dependency DAG of AST files. This is used // to implement short-circuiting logic when running DFS over the dependencies. SmallVector<ModuleFile *, 2> Roots; - /// \brief All loaded modules, indexed by name. + /// All loaded modules, indexed by name. llvm::DenseMap<const FileEntry *, ModuleFile *> Modules; - /// \brief FileManager that handles translating between filenames and + /// FileManager that handles translating between filenames and /// FileEntry *. FileManager &FileMgr; /// Cache of PCM files. IntrusiveRefCntPtr<MemoryBufferCache> PCMCache; - /// \brief Knows how to unwrap module containers. + /// Knows how to unwrap module containers. const PCHContainerReader &PCHContainerRdr; - /// \brief Preprocessor's HeaderSearchInfo containing the module map. + /// Preprocessor's HeaderSearchInfo containing the module map. const HeaderSearch &HeaderSearchInfo; - /// \brief A lookup of in-memory (virtual file) buffers + /// A lookup of in-memory (virtual file) buffers llvm::DenseMap<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>> InMemoryBuffers; - /// \brief The visitation order. + /// The visitation order. SmallVector<ModuleFile *, 4> VisitOrder; - /// \brief The list of module files that both we and the global module index + /// The list of module files that both we and the global module index /// know about. /// /// Either the global index or the module manager may have modules that the @@ -93,13 +93,13 @@ class ModuleManager { /// known to the global index. SmallVector<ModuleFile *, 4> ModulesInCommonWithGlobalIndex; - /// \brief The global module index, if one is attached. + /// The global module index, if one is attached. /// /// The global module index will actually be owned by the ASTReader; this is /// just an non-owning pointer. GlobalModuleIndex *GlobalIndex = nullptr; - /// \brief State used by the "visit" operation to avoid malloc traffic in + /// State used by the "visit" operation to avoid malloc traffic in /// calls to visit(). struct VisitState { explicit VisitState(unsigned N) : VisitNumber(N, 0) { @@ -110,22 +110,22 @@ class ModuleManager { delete NextState; } - /// \brief The stack used when marking the imports of a particular module + /// The stack used when marking the imports of a particular module /// as not-to-be-visited. SmallVector<ModuleFile *, 4> Stack; - /// \brief The visit number of each module file, which indicates when + /// The visit number of each module file, which indicates when /// this module file was last visited. SmallVector<unsigned, 4> VisitNumber; - /// \brief The next visit number to use to mark visited module files. + /// The next visit number to use to mark visited module files. unsigned NextVisitNumber = 1; - /// \brief The next visit state. + /// The next visit state. VisitState *NextState = nullptr; }; - /// \brief The first visit() state in the chain. + /// The first visit() state in the chain. VisitState *FirstVisitState = nullptr; VisitState *allocateVisitState(); @@ -145,74 +145,74 @@ public: const HeaderSearch &HeaderSearchInfo); ~ModuleManager(); - /// \brief Forward iterator to traverse all loaded modules. + /// Forward iterator to traverse all loaded modules. ModuleIterator begin() { return Chain.begin(); } - /// \brief Forward iterator end-point to traverse all loaded modules + /// Forward iterator end-point to traverse all loaded modules ModuleIterator end() { return Chain.end(); } - /// \brief Const forward iterator to traverse all loaded modules. + /// Const forward iterator to traverse all loaded modules. ModuleConstIterator begin() const { return Chain.begin(); } - /// \brief Const forward iterator end-point to traverse all loaded modules + /// Const forward iterator end-point to traverse all loaded modules ModuleConstIterator end() const { return Chain.end(); } - /// \brief Reverse iterator to traverse all loaded modules. + /// Reverse iterator to traverse all loaded modules. ModuleReverseIterator rbegin() { return Chain.rbegin(); } - /// \brief Reverse iterator end-point to traverse all loaded modules. + /// Reverse iterator end-point to traverse all loaded modules. ModuleReverseIterator rend() { return Chain.rend(); } - /// \brief A range covering the PCH and preamble module files loaded. + /// A range covering the PCH and preamble module files loaded. llvm::iterator_range<SmallVectorImpl<ModuleFile *>::const_iterator> pch_modules() const { return llvm::make_range(PCHChain.begin(), PCHChain.end()); } - /// \brief Returns the primary module associated with the manager, that is, + /// Returns the primary module associated with the manager, that is, /// the first module loaded ModuleFile &getPrimaryModule() { return *Chain[0]; } - /// \brief Returns the primary module associated with the manager, that is, + /// Returns the primary module associated with the manager, that is, /// the first module loaded. ModuleFile &getPrimaryModule() const { return *Chain[0]; } - /// \brief Returns the module associated with the given index + /// Returns the module associated with the given index ModuleFile &operator[](unsigned Index) const { return *Chain[Index]; } - /// \brief Returns the module associated with the given file name. + /// Returns the module associated with the given file name. ModuleFile *lookupByFileName(StringRef FileName) const; - /// \brief Returns the module associated with the given module name. + /// Returns the module associated with the given module name. ModuleFile *lookupByModuleName(StringRef ModName) const; - /// \brief Returns the module associated with the given module file. + /// Returns the module associated with the given module file. ModuleFile *lookup(const FileEntry *File) const; - /// \brief Returns the in-memory (virtual file) buffer with the given name + /// Returns the in-memory (virtual file) buffer with the given name std::unique_ptr<llvm::MemoryBuffer> lookupBuffer(StringRef Name); - /// \brief Number of modules loaded + /// Number of modules loaded unsigned size() const { return Chain.size(); } - /// \brief The result of attempting to add a new module. + /// The result of attempting to add a new module. enum AddModuleResult { - /// \brief The module file had already been loaded. + /// The module file had already been loaded. AlreadyLoaded, - /// \brief The module file was just loaded in response to this call. + /// The module file was just loaded in response to this call. NewlyLoaded, - /// \brief The module file is missing. + /// The module file is missing. Missing, - /// \brief The module file is out-of-date. + /// The module file is out-of-date. OutOfDate }; using ASTFileSignatureReader = ASTFileSignature (*)(StringRef); - /// \brief Attempts to create a new module and add it to the list of known + /// Attempts to create a new module and add it to the list of known /// modules. /// /// \param FileName The file name of the module to be loaded. @@ -255,23 +255,23 @@ public: ModuleFile *&Module, std::string &ErrorStr); - /// \brief Remove the modules starting from First (to the end). + /// Remove the modules starting from First (to the end). void removeModules(ModuleIterator First, llvm::SmallPtrSetImpl<ModuleFile *> &LoadedSuccessfully, ModuleMap *modMap); - /// \brief Add an in-memory buffer the list of known buffers + /// Add an in-memory buffer the list of known buffers void addInMemoryBuffer(StringRef FileName, std::unique_ptr<llvm::MemoryBuffer> Buffer); - /// \brief Set the global module index. + /// Set the global module index. void setGlobalIndex(GlobalModuleIndex *Index); - /// \brief Notification from the AST reader that the given module file + /// Notification from the AST reader that the given module file /// has been "accepted", and will not (can not) be unloaded. void moduleFileAccepted(ModuleFile *MF); - /// \brief Visit each of the modules. + /// Visit each of the modules. /// /// This routine visits each of the modules, starting with the /// "root" modules that no other loaded modules depend on, and @@ -293,7 +293,7 @@ public: void visit(llvm::function_ref<bool(ModuleFile &M)> Visitor, llvm::SmallPtrSetImpl<ModuleFile *> *ModuleFilesHit = nullptr); - /// \brief Attempt to resolve the given module file name to a file entry. + /// Attempt to resolve the given module file name to a file entry. /// /// \param FileName The name of the module file. /// @@ -315,7 +315,7 @@ public: time_t ExpectedModTime, const FileEntry *&File); - /// \brief View the graphviz representation of the module graph. + /// View the graphviz representation of the module graph. void viewGraph(); MemoryBufferCache &getPCMCache() const { return *PCMCache; } diff --git a/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt b/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt index 37dd9e8482968..236647c534851 100644 --- a/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt +++ b/include/clang/StaticAnalyzer/Checkers/CMakeLists.txt @@ -1,4 +1,3 @@ clang_tablegen(Checkers.inc -gen-clang-sa-checkers - -I ${CMAKE_CURRENT_SOURCE_DIR}/../../../ SOURCE Checkers.td TARGET ClangSACheckers) diff --git a/include/clang/StaticAnalyzer/Checkers/Checkers.td b/include/clang/StaticAnalyzer/Checkers/Checkers.td index e510e84e938af..ab0e4af1361b9 100644 --- a/include/clang/StaticAnalyzer/Checkers/Checkers.td +++ b/include/clang/StaticAnalyzer/Checkers/Checkers.td @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// -include "clang/StaticAnalyzer/Checkers/CheckerBase.td" +include "CheckerBase.td" //===----------------------------------------------------------------------===// // Packages. @@ -86,7 +86,7 @@ def LLVM : Package<"llvm">; // The APIModeling package is for checkers that model APIs and don't perform // any diagnostics. These checkers are always turned on; this package is -// intended for API modeling that is not controlled by the the target triple. +// intended for API modeling that is not controlled by the target triple. def APIModeling : Package<"apiModeling">, Hidden; def GoogleAPIModeling : Package<"google">, InPackage<APIModeling>; @@ -218,6 +218,14 @@ def NullableReturnedFromNonnullChecker : Checker<"NullableReturnedFromNonnull">, } // end "nullability" +let ParentPackage = APIModeling in { + +def TrustNonnullChecker : Checker<"TrustNonnull">, + HelpText<"Trust that returns from framework methods annotated with _Nonnull are not null">, + DescFile<"TrustNonnullChecker.cpp">; + +} + //===----------------------------------------------------------------------===// // Evaluate "builtin" functions. //===----------------------------------------------------------------------===// @@ -297,6 +305,10 @@ def DeleteWithNonVirtualDtorChecker : Checker<"DeleteWithNonVirtualDtor">, "destructor in their base class">, DescFile<"DeleteWithNonVirtualDtorChecker.cpp">; +def InnerPointerChecker : Checker<"InnerPointer">, + HelpText<"Check for inner pointers of C++ containers used after re/deallocation">, + DescFile<"InnerPointerChecker.cpp">; + def IteratorRangeChecker : Checker<"IteratorRange">, HelpText<"Check for iterators used outside their valid ranges">, DescFile<"IteratorChecker.cpp">; @@ -306,6 +318,10 @@ def MisusedMovedObjectChecker: Checker<"MisusedMovedObject">, "object will be reported">, DescFile<"MisusedMovedObjectChecker.cpp">; +def UninitializedObjectChecker: Checker<"UninitializedObject">, + HelpText<"Reports uninitialized fields after object construction">, + DescFile<"UninitializedObjectChecker.cpp">; + } // end: "alpha.cplusplus" @@ -365,6 +381,15 @@ def PaddingChecker : Checker<"Padding">, //===----------------------------------------------------------------------===// let ParentPackage = InsecureAPI in { + def bcmp : Checker<"bcmp">, + HelpText<"Warn on uses of the 'bcmp' function">, + DescFile<"CheckSecuritySyntaxOnly.cpp">; + def bcopy : Checker<"bcopy">, + HelpText<"Warn on uses of the 'bcopy' function">, + DescFile<"CheckSecuritySyntaxOnly.cpp">; + def bzero : Checker<"bzero">, + HelpText<"Warn on uses of the 'bzero' function">, + DescFile<"CheckSecuritySyntaxOnly.cpp">; def gets : Checker<"gets">, HelpText<"Warn on uses of the 'gets' function">, DescFile<"CheckSecuritySyntaxOnly.cpp">; @@ -414,6 +439,13 @@ def MallocOverflowSecurityChecker : Checker<"MallocOverflow">, HelpText<"Check for overflows in the arguments to malloc()">, DescFile<"MallocOverflowSecurityChecker.cpp">; +// Operating systems specific PROT_READ/PROT_WRITE values is not implemented, +// the defaults are correct for several common operating systems though, +// but may need to be overridden via the related analyzer-config flags. +def MmapWriteExecChecker : Checker<"MmapWriteExec">, + HelpText<"Warn on mmap() calls that are both writable and executable">, + DescFile<"MmapWriteExecChecker.cpp">; + } // end "alpha.security" //===----------------------------------------------------------------------===// @@ -536,6 +568,10 @@ def ObjCPropertyChecker : Checker<"ObjCProperty">, let ParentPackage = Cocoa in { +def RunLoopAutoreleaseLeakChecker : Checker<"RunLoopAutoreleaseLeak">, + HelpText<"Check for leaked memory in autorelease pools that will never be drained">, + DescFile<"RunLoopAutoreleaseLeakChecker.cpp">; + def ObjCAtSyncChecker : Checker<"AtSync">, HelpText<"Check for nil pointers used as mutexes for @synchronized">, DescFile<"ObjCAtSyncChecker.cpp">; @@ -601,8 +637,18 @@ def ObjCSuperDeallocChecker : Checker<"SuperDealloc">, HelpText<"Warn about improper use of '[super dealloc]' in Objective-C">, DescFile<"ObjCSuperDeallocChecker.cpp">; +def AutoreleaseWriteChecker : Checker<"AutoreleaseWrite">, + HelpText<"Warn about potentially crashing writes to autoreleasing objects from different autoreleasing pools in Objective-C">, + DescFile<"ObjCAutoreleaseWriteChecker.cpp">; } // end "osx.cocoa" +let ParentPackage = Performance in { + +def GCDAntipattern : Checker<"GCDAntipattern">, + HelpText<"Check for performance anti-patterns when using Grand Central Dispatch">, + DescFile<"GCDAntipatternChecker.cpp">; +} // end "optin.performance" + let ParentPackage = CocoaAlpha in { def InstanceVariableInvalidation : Checker<"InstanceVariableInvalidation">, diff --git a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h index ce50cc582d1e0..9d292cfddb0c8 100644 --- a/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h +++ b/include/clang/StaticAnalyzer/Core/AnalyzerOptions.h @@ -1,4 +1,4 @@ -//===--- AnalyzerOptions.h - Analysis Engine Options ------------*- C++ -*-===// +//===- AnalyzerOptions.h - Analysis Engine Options --------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,18 +19,18 @@ #include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include <string> +#include <utility> #include <vector> namespace clang { -class ASTConsumer; -class DiagnosticsEngine; -class Preprocessor; -class LangOptions; namespace ento { + class CheckerBase; -} + +} // namespace ento /// Analysis - Set of available source code analyses. enum Analyses { @@ -76,7 +76,7 @@ enum AnalysisInliningMode { NumInliningModes }; -/// \brief Describes the different kinds of C++ member functions which can be +/// Describes the different kinds of C++ member functions which can be /// considered for inlining by the analyzer. /// /// These options are cumulative; enabling one kind of member function will @@ -100,7 +100,7 @@ enum CXXInlineableMemberKind { CIMK_Destructors }; -/// \brief Describes the different modes of inter-procedural analysis. +/// Describes the different modes of inter-procedural analysis. enum IPAKind { IPAK_NotSet = 0, @@ -123,28 +123,31 @@ enum IPAKind { class AnalyzerOptions : public RefCountedBase<AnalyzerOptions> { public: - typedef llvm::StringMap<std::string> ConfigTable; + using ConfigTable = llvm::StringMap<std::string>; static std::vector<StringRef> getRegisteredCheckers(bool IncludeExperimental = false); - /// \brief Pair of checker name and enable/disable. - std::vector<std::pair<std::string, bool> > CheckersControlList; + /// Pair of checker name and enable/disable. + std::vector<std::pair<std::string, bool>> CheckersControlList; - /// \brief A key-value table of use-specified configuration values. + /// A key-value table of use-specified configuration values. ConfigTable Config; - AnalysisStores AnalysisStoreOpt; - AnalysisConstraints AnalysisConstraintsOpt; - AnalysisDiagClients AnalysisDiagOpt; - AnalysisPurgeMode AnalysisPurgeOpt; + AnalysisStores AnalysisStoreOpt = RegionStoreModel; + AnalysisConstraints AnalysisConstraintsOpt = RangeConstraintsModel; + AnalysisDiagClients AnalysisDiagOpt = PD_HTML; + AnalysisPurgeMode AnalysisPurgeOpt = PurgeStmt; std::string AnalyzeSpecificFunction; + + /// Store full compiler invocation for reproducible instructions in the + /// generated report. + std::string FullCompilerInvocation; - /// \brief The maximum number of times the analyzer visits a block. + /// The maximum number of times the analyzer visits a block. unsigned maxBlockVisitOnPath; - - /// \brief Disable all analyzer checks. + /// 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 @@ -157,7 +160,7 @@ public: unsigned AnalyzerDisplayProgress : 1; unsigned AnalyzeNestedBlocks : 1; - /// \brief The flag regulates if we should eagerly assume evaluations of + /// The flag regulates if we should eagerly assume evaluations of /// conditionals, thus, bifurcating the path. /// /// This flag indicates how the engine should handle expressions such as: 'x = @@ -174,22 +177,36 @@ public: unsigned UnoptimizedCFG : 1; unsigned PrintStats : 1; - /// \brief Do not re-analyze paths leading to exhausted nodes with a different + /// Do not re-analyze paths leading to exhausted nodes with a different /// strategy. We get better code coverage when retry is enabled. unsigned NoRetryExhausted : 1; - /// \brief The inlining stack depth limit. - unsigned InlineMaxStackDepth; + /// The inlining stack depth limit. + // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). + unsigned InlineMaxStackDepth = 5; - /// \brief The mode of function selection used during inlining. - AnalysisInliningMode InliningMode; + /// The mode of function selection used during inlining. + AnalysisInliningMode InliningMode = NoRedundancy; + + enum class ExplorationStrategyKind { + DFS, + BFS, + UnexploredFirst, + UnexploredFirstQueue, + BFSBlockDFSContents, + NotSet + }; private: - /// \brief Describes the kinds for high-level analyzer mode. + ExplorationStrategyKind ExplorationStrategy = ExplorationStrategyKind::NotSet; + + /// Describes the kinds for high-level analyzer mode. enum UserModeKind { UMK_NotSet = 0, + /// Perform shallow but fast analyzes. UMK_Shallow = 1, + /// Perform deep analyzes. UMK_Deep = 2 }; @@ -197,10 +214,10 @@ private: /// Controls the high-level analyzer mode, which influences the default /// settings for some of the lower-level config options (such as IPAMode). /// \sa getUserMode - UserModeKind UserMode; + UserModeKind UserMode = UMK_NotSet; /// Controls the mode of inter-procedural analysis. - IPAKind IPAMode; + IPAKind IPAMode = IPAK_NotSet; /// Controls which C++ member functions will be considered for inlining. CXXInlineableMemberKind CXXMemberInliningMode; @@ -217,9 +234,15 @@ private: /// \sa IncludeLoopExitInCFG Optional<bool> IncludeLoopExitInCFG; + /// \sa IncludeRichConstructorsInCFG + Optional<bool> IncludeRichConstructorsInCFG; + /// \sa mayInlineCXXStandardLibrary Optional<bool> InlineCXXStandardLibrary; + /// \sa includeScopesInCFG + Optional<bool> IncludeScopesInCFG; + /// \sa mayInlineTemplateFunctions Optional<bool> InlineTemplateFunctions; @@ -232,6 +255,9 @@ private: /// \sa mayInlineCXXSharedPtrDtor Optional<bool> InlineCXXSharedPtrDtor; + /// \sa mayInlineCXXTemporaryDtors + Optional<bool> InlineCXXTemporaryDtors; + /// \sa mayInlineObjCMethod Optional<bool> ObjCInliningMode; @@ -254,15 +280,23 @@ private: /// \sa shouldSuppressFromCXXStandardLibrary Optional<bool> SuppressFromCXXStandardLibrary; + /// \sa shouldCrosscheckWithZ3 + Optional<bool> CrosscheckWithZ3; + /// \sa reportIssuesInMainSourceFile Optional<bool> ReportIssuesInMainSourceFile; /// \sa StableReportFilename Optional<bool> StableReportFilename; + Optional<bool> SerializeStats; + /// \sa getGraphTrimInterval Optional<unsigned> GraphTrimInterval; + /// \sa getMaxSymbolComplexity + Optional<unsigned> MaxSymbolComplexity; + /// \sa getMaxTimesInlineLarge Optional<unsigned> MaxTimesInlineLarge; @@ -284,6 +318,22 @@ private: /// \sa shouldDisplayNotesAsEvents Optional<bool> DisplayNotesAsEvents; + /// \sa shouldAggressivelySimplifyBinaryOperation + Optional<bool> AggressiveBinaryOperationSimplification; + + /// \sa getCTUDir + Optional<StringRef> CTUDir; + + /// \sa getCTUIndexName + Optional<StringRef> CTUIndexName; + + /// \sa naiveCTUEnabled + Optional<bool> NaiveCTU; + + /// \sa shouldElideConstructors + Optional<bool> ElideConstructors; + + /// A helper function that retrieves option for a given full-qualified /// checker name. /// Options for checkers can be specified via 'analyzer-config' command-line @@ -311,6 +361,15 @@ private: bool SearchInParents = false); public: + AnalyzerOptions() + : DisableAllChecks(false), ShowCheckerHelp(false), + ShowEnabledCheckerList(false), AnalyzeAll(false), + AnalyzerDisplayProgress(false), AnalyzeNestedBlocks(false), + eagerlyAssumeBinOpBifurcation(false), TrimGraph(false), + visualizeExplodedGraphWithGraphViz(false), + visualizeExplodedGraphWithUbiGraph(false), UnoptimizedCFG(false), + PrintStats(false), NoRetryExhausted(false), CXXMemberInliningMode() {} + /// Interprets an option's string value as a boolean. The "true" string is /// interpreted as true and the "false" string is interpreted as false. /// @@ -320,7 +379,7 @@ public: /// specified. /// @param [in] C The optional checker parameter that can be used to restrict /// the search to the options of this particular checker (and its parents - /// dependening on search mode). + /// depending on search mode). /// @param [in] SearchInParents If set to true and the searched option was not /// specified for the given checker the options for the parent packages will /// be searched as well. The inner packages take precedence over the outer @@ -338,7 +397,7 @@ public: /// specified. /// @param [in] C The optional checker parameter that can be used to restrict /// the search to the options of this particular checker (and its parents - /// dependening on search mode). + /// depending on search mode). /// @param [in] SearchInParents If set to true and the searched option was not /// specified for the given checker the options for the parent packages will /// be searched as well. The inner packages take precedence over the outer @@ -355,7 +414,7 @@ public: /// specified. /// @param [in] C The optional checker parameter that can be used to restrict /// the search to the options of this particular checker (and its parents - /// dependening on search mode). + /// depending on search mode). /// @param [in] SearchInParents If set to true and the searched option was not /// specified for the given checker the options for the parent packages will /// be searched as well. The inner packages take precedence over the outer @@ -372,7 +431,7 @@ public: /// specified. /// @param [in] C The optional checker parameter that can be used to restrict /// the search to the options of this particular checker (and its parents - /// dependening on search mode). + /// depending on search mode). /// @param [in] SearchInParents If set to true and the searched option was not /// specified for the given checker the options for the parent packages will /// be searched as well. The inner packages take precedence over the outer @@ -381,12 +440,14 @@ public: const ento::CheckerBase *C = nullptr, bool SearchInParents = false); - /// \brief Retrieves and sets the UserMode. This is a high-level option, + /// Retrieves and sets the UserMode. This is a high-level option, /// which is used to set other low-level options. It is not accessible /// outside of AnalyzerOptions. UserModeKind getUserMode(); - /// \brief Returns the inter-procedural analysis mode. + ExplorationStrategyKind getExplorationStrategy(); + + /// Returns the inter-procedural analysis mode. IPAKind getIPAMode(); /// Returns the option controlling which C++ member functions will be @@ -428,6 +489,19 @@ public: /// the values "true" and "false". bool includeLoopExitInCFG(); + /// Returns whether or not construction site information should be included + /// in the CFG C++ constructor elements. + /// + /// This is controlled by the 'cfg-rich-constructors' config options, + /// which accepts the values "true" and "false". + bool includeRichConstructorsInCFG(); + + /// Returns whether or not scope information should be included in the CFG. + /// + /// This is controlled by the 'cfg-scope-info' config option, which accepts + /// the values "true" and "false". + bool includeScopesInCFG(); + /// Returns whether or not C++ standard library functions may be considered /// for inlining. /// @@ -464,6 +538,17 @@ public: /// accepts the values "true" and "false". bool mayInlineCXXSharedPtrDtor(); + /// Returns true if C++ temporary destructors should be inlined during + /// analysis. + /// + /// If temporary destructors are disabled in the CFG via the + /// 'cfg-temporary-dtors' option, temporary destructors would not be + /// inlined anyway. + /// + /// This is controlled by the 'c++-temp-dtor-inlining' config option, which + /// accepts the values "true" and "false". + bool mayInlineCXXTemporaryDtors(); + /// Returns whether or not paths that go through null returns should be /// suppressed. /// @@ -499,6 +584,13 @@ public: /// which accepts the values "true" and "false". bool shouldSuppressFromCXXStandardLibrary(); + /// Returns whether bug reports should be crosschecked with the Z3 + /// constraint manager backend. + /// + /// This is controlled by the 'crosscheck-with-z3' config option, + /// which accepts the values "true" and "false". + bool shouldCrosscheckWithZ3(); + /// Returns whether or not the diagnostic report should be always reported /// in the main source file and not the headers. /// @@ -512,6 +604,14 @@ public: /// which accepts the values "true" and "false". Default = false bool shouldWriteStableReportFilename(); + /// \return Whether the analyzer should + /// serialize statistics to plist output. + /// Statistics would be serialized in JSON format inside the main dictionary + /// under the \c statistics key. + /// Available only if compiled in assert mode or with LLVM statistics + /// explicitly enabled. + bool shouldSerializeStats(); + /// Returns whether irrelevant parts of a bug report path should be pruned /// out of the final output. /// @@ -546,6 +646,11 @@ public: /// node reclamation, set the option to "0". unsigned getGraphTrimInterval(); + /// Returns the maximum complexity of symbolic constraint (50 by default). + /// + /// This is controlled by "-analyzer-config max-symbol-complexity" option. + unsigned getMaxSymbolComplexity(); + /// Returns the maximum times a large function could be inlined. /// /// This is controlled by the 'max-times-inline-large' config option. @@ -585,36 +690,41 @@ public: /// to false when unset. bool shouldDisplayNotesAsEvents(); -public: - AnalyzerOptions() : - AnalysisStoreOpt(RegionStoreModel), - AnalysisConstraintsOpt(RangeConstraintsModel), - AnalysisDiagOpt(PD_HTML), - AnalysisPurgeOpt(PurgeStmt), - DisableAllChecks(0), - ShowCheckerHelp(0), - ShowEnabledCheckerList(0), - AnalyzeAll(0), - AnalyzerDisplayProgress(0), - AnalyzeNestedBlocks(0), - eagerlyAssumeBinOpBifurcation(0), - TrimGraph(0), - visualizeExplodedGraphWithGraphViz(0), - visualizeExplodedGraphWithUbiGraph(0), - UnoptimizedCFG(0), - PrintStats(0), - NoRetryExhausted(0), - // Cap the stack depth at 4 calls (5 stack frames, base + 4 calls). - InlineMaxStackDepth(5), - InliningMode(NoRedundancy), - UserMode(UMK_NotSet), - IPAMode(IPAK_NotSet), - CXXMemberInliningMode() {} - + /// Returns true if SValBuilder should rearrange comparisons and additive + /// operations of symbolic expressions which consist of a sum of a symbol and + /// a concrete integer into the format where symbols are on the left-hand + /// side and the integer is on the right. This is only done if both symbols + /// and both concrete integers are signed, greater than or equal to the + /// quarter of the minimum value of the type and less than or equal to the + /// quarter of the maximum value of that type. + /// + /// A + n <OP> B + m becomes A - B <OP> m - n, where A and B symbolic, + /// n and m are integers. <OP> is any of '==', '!=', '<', '<=', '>', '>=', + /// '+' or '-'. The rearrangement also happens with '-' instead of '+' on + // either or both side and also if any or both integers are missing. + bool shouldAggressivelySimplifyBinaryOperation(); + + /// Returns the directory containing the CTU related files. + StringRef getCTUDir(); + + /// Returns the name of the file containing the CTU index of functions. + StringRef getCTUIndexName(); + + /// Returns true when naive cross translation unit analysis is enabled. + /// This is an experimental feature to inline functions from another + /// translation units. + bool naiveCTUEnabled(); + + /// Returns true if elidable C++ copy-constructors and move-constructors + /// should be actually elided during analysis. Both behaviors are allowed + /// by the C++ standard, and the analyzer, like CodeGen, defaults to eliding. + /// Starting with C++17 some elisions become mandatory, and in these cases + /// the option will be ignored. + bool shouldElideConstructors(); }; -typedef IntrusiveRefCntPtr<AnalyzerOptions> AnalyzerOptionsRef; +using AnalyzerOptionsRef = IntrusiveRefCntPtr<AnalyzerOptions>; -} +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_ANALYZEROPTIONS_H diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h index cd1355d03b639..111e1d1e8e20a 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporter.h @@ -1,4 +1,4 @@ -//===--- BugReporter.h - Generate PathDiagnostics --------------*- C++ -*-===// +//===- BugReporter.h - Generate PathDiagnostics -----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,78 +15,101 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" -#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h" #include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" #include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist_node.h" +#include "llvm/ADT/iterator_range.h" +#include <cassert> +#include <memory> +#include <string> +#include <utility> +#include <vector> namespace clang { +class AnalyzerOptions; class ASTContext; +class Decl; class DiagnosticsEngine; +class LocationContext; +class SourceManager; class Stmt; -class ParentMap; namespace ento { -class PathDiagnostic; -class ExplodedNode; +class BugType; +class CheckerBase; class ExplodedGraph; -class BugReport; -class BugReporter; -class BugReporterContext; +class ExplodedNode; class ExprEngine; -class BugType; +class MemRegion; +class SValBuilder; //===----------------------------------------------------------------------===// // Interface for individual bug reports. //===----------------------------------------------------------------------===// +/// A mapping from diagnostic consumers to the diagnostics they should +/// consume. +using DiagnosticForConsumerMapTy = + llvm::DenseMap<PathDiagnosticConsumer *, std::unique_ptr<PathDiagnostic>>; + /// This class provides an interface through which checkers can create /// individual bug reports. class BugReport : public llvm::ilist_node<BugReport> { public: class NodeResolver { virtual void anchor(); + public: - virtual ~NodeResolver() {} + virtual ~NodeResolver() = default; + virtual const ExplodedNode* getOriginalNode(const ExplodedNode *N) = 0; }; - typedef const SourceRange *ranges_iterator; - typedef SmallVector<std::unique_ptr<BugReporterVisitor>, 8> VisitorList; - typedef VisitorList::iterator visitor_iterator; - typedef SmallVector<StringRef, 2> ExtraTextList; - typedef SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4> NoteList; + using ranges_iterator = const SourceRange *; + using VisitorList = SmallVector<std::unique_ptr<BugReporterVisitor>, 8>; + using visitor_iterator = VisitorList::iterator; + using ExtraTextList = SmallVector<StringRef, 2>; + using NoteList = SmallVector<std::shared_ptr<PathDiagnosticNotePiece>, 4>; protected: - friend class BugReporter; friend class BugReportEquivClass; + friend class BugReporter; BugType& BT; - const Decl *DeclWithIssue; + const Decl *DeclWithIssue = nullptr; std::string ShortDescription; std::string Description; PathDiagnosticLocation Location; PathDiagnosticLocation UniqueingLocation; const Decl *UniqueingDecl; - const ExplodedNode *ErrorNode; + const ExplodedNode *ErrorNode = nullptr; SmallVector<SourceRange, 4> Ranges; ExtraTextList ExtraText; NoteList Notes; - typedef llvm::DenseSet<SymbolRef> Symbols; - typedef llvm::DenseSet<const MemRegion *> Regions; + using Symbols = llvm::DenseSet<SymbolRef>; + using Regions = llvm::DenseSet<const MemRegion *>; /// A (stack of) a set of symbols that are registered with this /// report as being "interesting", and thus used to help decide which @@ -113,20 +136,16 @@ protected: /// Used for ensuring the visitors are only added once. llvm::FoldingSet<BugReporterVisitor> CallbacksSet; - /// Used for clients to tell if the report's configuration has changed - /// since the last time they checked. - unsigned ConfigurationChangeToken; - /// When set, this flag disables all callstack pruning from a diagnostic /// path. This is useful for some reports that want maximum fidelty /// when reporting an issue. - bool DoNotPrunePath; + bool DoNotPrunePath = false; /// Used to track unique reasons why a bug report might be invalid. /// /// \sa markInvalid /// \sa removeInvalidation - typedef std::pair<const void *, const void *> InvalidationRecord; + using InvalidationRecord = std::pair<const void *, const void *>; /// If non-empty, this bug report is likely a false positive and should not be /// shown to the user. @@ -146,20 +165,17 @@ private: public: BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode) - : BT(bt), DeclWithIssue(nullptr), Description(desc), ErrorNode(errornode), - ConfigurationChangeToken(0), DoNotPrunePath(false) {} + : BT(bt), Description(desc), ErrorNode(errornode) {} BugReport(BugType& bt, StringRef shortDesc, StringRef desc, const ExplodedNode *errornode) - : BT(bt), DeclWithIssue(nullptr), ShortDescription(shortDesc), - Description(desc), ErrorNode(errornode), ConfigurationChangeToken(0), - DoNotPrunePath(false) {} + : BT(bt), ShortDescription(shortDesc), Description(desc), + ErrorNode(errornode) {} BugReport(BugType &bt, StringRef desc, PathDiagnosticLocation l) - : BT(bt), DeclWithIssue(nullptr), Description(desc), Location(l), - ErrorNode(nullptr), ConfigurationChangeToken(0), DoNotPrunePath(false) {} + : BT(bt), Description(desc), Location(l) {} - /// \brief Create a BugReport with a custom uniqueing location. + /// Create a BugReport with a custom uniqueing location. /// /// The reports that have the same report location, description, bug type, and /// ranges are uniqued - only one of the equivalent reports will be presented @@ -168,18 +184,15 @@ public: /// the allocation site, rather then the location where the bug is reported. BugReport(BugType& bt, StringRef desc, const ExplodedNode *errornode, PathDiagnosticLocation LocationToUnique, const Decl *DeclToUnique) - : BT(bt), DeclWithIssue(nullptr), Description(desc), - UniqueingLocation(LocationToUnique), - UniqueingDecl(DeclToUnique), - ErrorNode(errornode), ConfigurationChangeToken(0), - DoNotPrunePath(false) {} + : BT(bt), Description(desc), UniqueingLocation(LocationToUnique), + UniqueingDecl(DeclToUnique), ErrorNode(errornode) {} virtual ~BugReport(); const BugType& getBugType() const { return BT; } BugType& getBugType() { return BT; } - /// \brief True when the report has an execution path associated with it. + /// True when the report has an execution path associated with it. /// /// A report is said to be path-sensitive if it was thrown against a /// particular exploded node in the path-sensitive analysis graph. @@ -218,10 +231,6 @@ public: bool isInteresting(SVal V); bool isInteresting(const LocationContext *LC); - unsigned getConfigurationChangeToken() const { - return ConfigurationChangeToken; - } - /// Returns whether or not this report should be considered valid. /// /// Invalid reports are those that have been classified as likely false @@ -242,13 +251,6 @@ public: void markInvalid(const void *Tag, const void *Data) { Invalidations.insert(std::make_pair(Tag, Data)); } - - /// Reverses the effects of a previous invalidation. - /// - /// \sa markInvalid - void removeInvalidation(const void *Tag, const void *Data) { - Invalidations.erase(std::make_pair(Tag, Data)); - } /// Return the canonical declaration, be it a method or class, where /// this issue semantically occurred. @@ -286,7 +288,7 @@ public: return Notes; } - /// \brief This allows for addition of meta data to the diagnostic. + /// This allows for addition of meta data to the diagnostic. /// /// Currently, only the HTMLDiagnosticClient knows how to display it. void addExtraText(StringRef S) { @@ -297,26 +299,26 @@ public: return ExtraText; } - /// \brief Return the "definitive" location of the reported bug. + /// Return the "definitive" location of the reported bug. /// /// While a bug can span an entire path, usually there is a specific /// location that can be used to identify where the key issue occurred. /// This location is used by clients rendering diagnostics. virtual PathDiagnosticLocation getLocation(const SourceManager &SM) const; - /// \brief Get the location on which the report should be uniqued. + /// Get the location on which the report should be uniqued. PathDiagnosticLocation getUniqueingLocation() const { return UniqueingLocation; } - /// \brief Get the declaration containing the uniqueing location. + /// Get the declaration containing the uniqueing location. const Decl *getUniqueingDecl() const { return UniqueingDecl; } const Stmt *getStmt() const; - /// \brief Add a range to a bug report. + /// Add a range to a bug report. /// /// Ranges are used to highlight regions of interest in the source code. /// They should be at the same source code line as the BugReport location. @@ -329,10 +331,10 @@ public: Ranges.push_back(R); } - /// \brief Get the SourceRanges associated with the report. + /// Get the SourceRanges associated with the report. virtual llvm::iterator_range<ranges_iterator> getRanges(); - /// \brief Add custom or predefined bug report visitors to this report. + /// Add custom or predefined bug report visitors to this report. /// /// The visitors should be used when the default trace is not sufficient. /// For example, they allow constructing a more elaborate trace. @@ -341,6 +343,9 @@ public: /// registerVarDeclsLastStore(). void addVisitor(std::unique_ptr<BugReporterVisitor> visitor); + /// Remove all visitors attached to this bug report. + void clearVisitors(); + /// Iterators through the custom diagnostic visitors. visitor_iterator visitor_begin() { return Callbacks.begin(); } visitor_iterator visitor_end() { return Callbacks.end(); } @@ -356,10 +361,11 @@ public: //===----------------------------------------------------------------------===// class BugReportEquivClass : public llvm::FoldingSetNode { + friend class BugReporter; + /// List of *owned* BugReport objects. llvm::ilist<BugReport> Reports; - friend class BugReporter; void AddReport(std::unique_ptr<BugReport> R) { Reports.push_back(R.release()); } @@ -373,8 +379,8 @@ public: Reports.front().Profile(ID); } - typedef llvm::ilist<BugReport>::iterator iterator; - typedef llvm::ilist<BugReport>::const_iterator const_iterator; + using iterator = llvm::ilist<BugReport>::iterator; + using const_iterator = llvm::ilist<BugReport>::const_iterator; iterator begin() { return Reports.begin(); } iterator end() { return Reports.end(); } @@ -390,22 +396,26 @@ public: class BugReporterData { public: virtual ~BugReporterData(); + virtual DiagnosticsEngine& getDiagnostic() = 0; virtual ArrayRef<PathDiagnosticConsumer*> getPathDiagnosticConsumers() = 0; virtual ASTContext &getASTContext() = 0; - virtual SourceManager& getSourceManager() = 0; - virtual AnalyzerOptions& getAnalyzerOptions() = 0; + virtual SourceManager &getSourceManager() = 0; + virtual AnalyzerOptions &getAnalyzerOptions() = 0; }; /// BugReporter is a utility class for generating PathDiagnostics for analysis. /// It collects the BugReports and BugTypes and knows how to generate /// and flush the corresponding diagnostics. +/// +/// The base class is used for generating path-insensitive class BugReporter { public: enum Kind { BaseBRKind, GRBugReporterKind }; private: - typedef llvm::ImmutableSet<BugType*> BugTypesTy; + using BugTypesTy = llvm::ImmutableSet<BugType *>; + BugTypesTy::Factory F; BugTypesTy BugTypes; @@ -415,27 +425,28 @@ private: /// Generate and flush the diagnostics for the given bug report. void FlushReport(BugReportEquivClass& EQ); - /// Generate and flush the diagnostics for the given bug report - /// and PathDiagnosticConsumer. - void FlushReport(BugReport *exampleReport, - PathDiagnosticConsumer &PD, - ArrayRef<BugReport*> BugReports); + /// Generate the diagnostics for the given bug report. + std::unique_ptr<DiagnosticForConsumerMapTy> + generateDiagnosticForConsumerMap(BugReport *exampleReport, + ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> bugReports); /// The set of bug reports tracked by the BugReporter. llvm::FoldingSet<BugReportEquivClass> EQClasses; + /// A vector of BugReports for tracking the allocated pointers and cleanup. std::vector<BugReportEquivClass *> EQClassesVector; protected: - BugReporter(BugReporterData& d, Kind k) : BugTypes(F.getEmptySet()), kind(k), - D(d) {} + BugReporter(BugReporterData& d, Kind k) + : BugTypes(F.getEmptySet()), kind(k), D(d) {} public: - BugReporter(BugReporterData& d) : BugTypes(F.getEmptySet()), kind(BaseBRKind), - D(d) {} + BugReporter(BugReporterData& d) + : BugTypes(F.getEmptySet()), kind(BaseBRKind), D(d) {} virtual ~BugReporter(); - /// \brief Generate and flush diagnostics for all bug reports. + /// Generate and flush diagnostics for all bug reports. void FlushReports(); Kind getKind() const { return kind; } @@ -448,33 +459,31 @@ public: return D.getPathDiagnosticConsumers(); } - /// \brief Iterator over the set of BugTypes tracked by the BugReporter. - typedef BugTypesTy::iterator iterator; + /// Iterator over the set of BugTypes tracked by the BugReporter. + using iterator = BugTypesTy::iterator; iterator begin() { return BugTypes.begin(); } iterator end() { return BugTypes.end(); } - /// \brief Iterator over the set of BugReports tracked by the BugReporter. - typedef llvm::FoldingSet<BugReportEquivClass>::iterator EQClasses_iterator; + /// Iterator over the set of BugReports tracked by the BugReporter. + using EQClasses_iterator = llvm::FoldingSet<BugReportEquivClass>::iterator; EQClasses_iterator EQClasses_begin() { return EQClasses.begin(); } EQClasses_iterator EQClasses_end() { return EQClasses.end(); } ASTContext &getContext() { return D.getASTContext(); } - SourceManager& getSourceManager() { return D.getSourceManager(); } + SourceManager &getSourceManager() { return D.getSourceManager(); } - AnalyzerOptions& getAnalyzerOptions() { return D.getAnalyzerOptions(); } + AnalyzerOptions &getAnalyzerOptions() { return D.getAnalyzerOptions(); } - virtual bool generatePathDiagnostic(PathDiagnostic& pathDiagnostic, - PathDiagnosticConsumer &PC, - ArrayRef<BugReport *> &bugReports) { - return true; + virtual std::unique_ptr<DiagnosticForConsumerMapTy> + generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> &bugReports) { + return {}; } - bool RemoveUnneededCalls(PathPieces &pieces, BugReport *R); - void Register(BugType *BT); - /// \brief Add the given report to the set of reports tracked by BugReporter. + /// Add the given report to the set of reports tracked by BugReporter. /// /// The reports are usually generated by the checkers. Further, they are /// folded based on the profile value, which is done to coalesce similar @@ -494,25 +503,22 @@ public: private: llvm::StringMap<BugType *> StrBugTypes; - /// \brief Returns a BugType that is associated with the given name and + /// Returns a BugType that is associated with the given name and /// category. BugType *getBugTypeForName(CheckName CheckName, StringRef name, StringRef category); }; -// FIXME: Get rid of GRBugReporter. It's the wrong abstraction. +/// GRBugReporter is used for generating path-sensitive reports. class GRBugReporter : public BugReporter { ExprEngine& Eng; + public: GRBugReporter(BugReporterData& d, ExprEngine& eng) - : BugReporter(d, GRBugReporterKind), Eng(eng) {} + : BugReporter(d, GRBugReporterKind), Eng(eng) {} ~GRBugReporter() override; - /// getEngine - Return the analysis engine used to analyze a given - /// function or method. - ExprEngine &getEngine() { return Eng; } - /// getGraph - Get the exploded graph created by the analysis engine /// for the analyzed method or function. ExplodedGraph &getGraph(); @@ -521,16 +527,14 @@ public: /// engine. ProgramStateManager &getStateManager(); - /// Generates a path corresponding to one of the given bug reports. - /// - /// Which report is used for path generation is not specified. The - /// bug reporter will try to pick the shortest path, but this is not - /// guaranteed. + /// \p bugReports A set of bug reports within a *single* equivalence class /// - /// \return True if the report was valid and a path was generated, - /// false if the reports should be considered invalid. - bool generatePathDiagnostic(PathDiagnostic &PD, PathDiagnosticConsumer &PC, - ArrayRef<BugReport*> &bugReports) override; + /// \return A mapping from consumers to the corresponding diagnostics. + /// Iterates through the bug reports within a single equivalence class, + /// stops at a first non-invalidated report. + std::unique_ptr<DiagnosticForConsumerMapTy> + generatePathDiagnostics(ArrayRef<PathDiagnosticConsumer *> consumers, + ArrayRef<BugReport *> &bugReports) override; /// classof - Used by isa<>, cast<>, and dyn_cast<>. static bool classof(const BugReporter* R) { @@ -538,13 +542,29 @@ public: } }; + +class NodeMapClosure : public BugReport::NodeResolver { + InterExplodedGraphMap &M; + +public: + NodeMapClosure(InterExplodedGraphMap &m) : M(m) {} + + const ExplodedNode *getOriginalNode(const ExplodedNode *N) override { + return M.lookup(N); + } +}; + class BugReporterContext { - virtual void anchor(); GRBugReporter &BR; + NodeMapClosure NMC; + + virtual void anchor(); + public: - BugReporterContext(GRBugReporter& br) : BR(br) {} + BugReporterContext(GRBugReporter &br, InterExplodedGraphMap &Backmap) + : BR(br), NMC(Backmap) {} - virtual ~BugReporterContext() {} + virtual ~BugReporterContext() = default; GRBugReporter& getBugReporter() { return BR; } @@ -554,7 +574,7 @@ public: return BR.getStateManager(); } - SValBuilder& getSValBuilder() { + SValBuilder &getSValBuilder() { return getStateManager().getSValBuilder(); } @@ -566,11 +586,15 @@ public: return BR.getSourceManager(); } - virtual BugReport::NodeResolver& getNodeResolver() = 0; + AnalyzerOptions &getAnalyzerOptions() { + return BR.getAnalyzerOptions(); + } + + NodeMapClosure& getNodeResolver() { return NMC; } }; -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTER_H diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h index 2043896fd26fe..92118b0fbee25 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitors.h @@ -1,4 +1,4 @@ -//===--- BugReporterVisitors.h - Generate PathDiagnostics -------*- C++ -*-===// +//===- BugReporterVisitors.h - Generate PathDiagnostics ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,11 +15,21 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H +#include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringRef.h" +#include <memory> namespace clang { + +class BinaryOperator; class CFGBlock; +class DeclRefExpr; +class Expr; +class Stmt; namespace ento { @@ -29,13 +39,7 @@ class ExplodedNode; class MemRegion; class PathDiagnosticPiece; -/// \brief BugReporterVisitors are used to add custom diagnostics along a path. -/// -/// Custom visitors should subclass the BugReporterVisitorImpl class for a -/// default implementation of the clone() method. -/// (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.) +/// BugReporterVisitors are used to add custom diagnostics along a path. class BugReporterVisitor : public llvm::FoldingSetNode { public: BugReporterVisitor() = default; @@ -43,19 +47,13 @@ public: BugReporterVisitor(BugReporterVisitor &&) {} virtual ~BugReporterVisitor(); - /// \brief Returns a copy of this BugReporter. - /// - /// Custom BugReporterVisitors should not override this method directly. - /// Instead, they should inherit from BugReporterVisitorImpl and provide - /// a protected or public copy constructor. - /// - /// (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 std::unique_ptr<BugReporterVisitor> clone() const = 0; - - /// \brief Return a diagnostic piece which should be associated with the + /// Return a diagnostic piece which should be associated with the /// given node. + /// Note that this function does *not* get run on the very last node + /// of the report, as the PathDiagnosticPiece associated with the + /// last node should be unique. + /// Use {@code getEndPath} to customize the note associated with the report + /// end instead. /// /// The last parameter can be used to register a new visitor with the given /// BugReport while processing a node. @@ -63,43 +61,32 @@ public: VisitNode(const ExplodedNode *Succ, const ExplodedNode *Pred, BugReporterContext &BRC, BugReport &BR) = 0; - /// \brief Provide custom definition for the final diagnostic piece on the + /// Last function called on the visitor, no further calls to VisitNode + /// would follow. + virtual void finalizeVisitor(BugReporterContext &BRC, + const ExplodedNode *EndPathNode, + BugReport &BR); + + /// Provide custom definition for the final diagnostic piece on the /// path - the piece, which is displayed before the path is expanded. /// - /// 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 std::unique_ptr<PathDiagnosticPiece> + /// NOTE that this function can be implemented on at most one used visitor, + /// and otherwise it crahes at runtime. + virtual std::shared_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 std::unique_ptr<PathDiagnosticPiece> + /// Generates the default final diagnostic piece. + static std::shared_ptr<PathDiagnosticPiece> getDefaultEndPath(BugReporterContext &BRC, const ExplodedNode *N, BugReport &BR); }; -/// This class provides a convenience implementation for clone() using the -/// Curiously-Recurring Template Pattern. If you are implementing a custom -/// BugReporterVisitor, subclass BugReporterVisitorImpl and provide a public -/// or protected copy constructor. -/// -/// (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.) -template <class DERIVED> -class BugReporterVisitorImpl : public BugReporterVisitor { - std::unique_ptr<BugReporterVisitor> clone() const override { - return llvm::make_unique<DERIVED>(*static_cast<const DERIVED *>(this)); - } -}; - -class FindLastStoreBRVisitor final - : public BugReporterVisitorImpl<FindLastStoreBRVisitor> { +class FindLastStoreBRVisitor final : public BugReporterVisitor { const MemRegion *R; SVal V; - bool Satisfied; + bool Satisfied = false; /// If the visitor is tracking the value directly responsible for the /// bug, we are going to employ false positive suppression. @@ -113,10 +100,7 @@ public: FindLastStoreBRVisitor(KnownSVal V, const MemRegion *R, bool InEnableNullFPSuppression) - : R(R), - V(V), - Satisfied(false), - EnableNullFPSuppression(InEnableNullFPSuppression) {} + : R(R), V(V), EnableNullFPSuppression(InEnableNullFPSuppression) {} void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -126,22 +110,20 @@ public: BugReport &BR) override; }; -class TrackConstraintBRVisitor final - : public BugReporterVisitorImpl<TrackConstraintBRVisitor> { +class TrackConstraintBRVisitor final : public BugReporterVisitor { DefinedSVal Constraint; bool Assumption; - bool IsSatisfied; + bool IsSatisfied = false; bool IsZeroCheck; /// We should start tracking from the last node along the path in which the /// value is constrained. - bool IsTrackingTurnedOn; + bool IsTrackingTurnedOn = false; public: TrackConstraintBRVisitor(DefinedSVal constraint, bool assumption) - : Constraint(constraint), Assumption(assumption), IsSatisfied(false), - IsZeroCheck(!Assumption && Constraint.getAs<Loc>()), - IsTrackingTurnedOn(false) {} + : Constraint(constraint), Assumption(assumption), + IsZeroCheck(!Assumption && Constraint.getAs<Loc>()) {} void Profile(llvm::FoldingSetNodeID &ID) const override; @@ -157,15 +139,12 @@ public: private: /// Checks if the constraint is valid in the current state. bool isUnderconstrained(const ExplodedNode *N) const; - }; /// \class NilReceiverBRVisitor -/// \brief Prints path notes when a message is sent to a nil receiver. -class NilReceiverBRVisitor final - : public BugReporterVisitorImpl<NilReceiverBRVisitor> { +/// Prints path notes when a message is sent to a nil receiver. +class NilReceiverBRVisitor final : public BugReporterVisitor { public: - void Profile(llvm::FoldingSetNodeID &ID) const override { static int x = 0; ID.AddPointer(&x); @@ -182,9 +161,7 @@ public: }; /// Visitor that tries to report interesting diagnostics from conditions. -class ConditionBRVisitor final - : public BugReporterVisitorImpl<ConditionBRVisitor> { - +class ConditionBRVisitor final : public BugReporterVisitor { // FIXME: constexpr initialization isn't supported by MSVC2013. static const char *const GenericTrueMessage; static const char *const GenericFalseMessage; @@ -243,11 +220,11 @@ public: static bool isPieceMessageGeneric(const PathDiagnosticPiece *Piece); }; -/// \brief Suppress reports that might lead to known false positives. +/// Suppress reports that might lead to known false positives. /// /// Currently this suppresses reports based on locations of bugs. class LikelyFalsePositiveSuppressionBRVisitor final - : public BugReporterVisitorImpl<LikelyFalsePositiveSuppressionBRVisitor> { + : public BugReporterVisitor { public: static void *getTag() { static int Tag = 0; @@ -265,19 +242,16 @@ public: return nullptr; } - std::unique_ptr<PathDiagnosticPiece> getEndPath(BugReporterContext &BRC, - const ExplodedNode *N, - BugReport &BR) override; + void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *N, + BugReport &BR) override; }; -/// \brief When a region containing undefined value or '0' value is passed +/// When a region containing undefined value or '0' value is passed /// as an argument in a call, marks the call as interesting. /// /// As a result, BugReporter will not prune the path through the function even /// if the region's contents are not modified/accessed by the call. -class UndefOrNullArgVisitor final - : public BugReporterVisitorImpl<UndefOrNullArgVisitor> { - +class UndefOrNullArgVisitor final : public BugReporterVisitor { /// The interesting memory region this visitor is tracking. const MemRegion *R; @@ -296,21 +270,20 @@ public: BugReport &BR) override; }; -class SuppressInlineDefensiveChecksVisitor final - : public BugReporterVisitorImpl<SuppressInlineDefensiveChecksVisitor> { +class SuppressInlineDefensiveChecksVisitor final : public BugReporterVisitor { /// The symbolic value for which we are tracking constraints. /// This value is constrained to null in the end of path. DefinedSVal V; /// Track if we found the node where the constraint was first added. - bool IsSatisfied; + bool IsSatisfied = false; /// Since the visitors can be registered on nodes previous to the last /// node in the BugReport, but the path traversal always starts with the last /// node, the visitor invariant (that we start with a node in which V is null) /// might not hold when node visitation starts. We are going to start tracking /// from the last node in which the value is null. - bool IsTrackingTurnedOn; + bool IsTrackingTurnedOn = false; public: SuppressInlineDefensiveChecksVisitor(DefinedSVal Val, const ExplodedNode *N); @@ -327,13 +300,11 @@ public: BugReport &BR) override; }; -class CXXSelfAssignmentBRVisitor final - : public BugReporterVisitorImpl<CXXSelfAssignmentBRVisitor> { - - bool Satisfied; +class CXXSelfAssignmentBRVisitor final : public BugReporterVisitor { + bool Satisfied = false; public: - CXXSelfAssignmentBRVisitor() : Satisfied(false) {} + CXXSelfAssignmentBRVisitor() = default; void Profile(llvm::FoldingSetNodeID &ID) const override {} @@ -343,6 +314,44 @@ public: BugReport &BR) override; }; +/// The bug visitor prints a diagnostic message at the location where a given +/// variable was tainted. +class TaintBugVisitor final : public BugReporterVisitor { +private: + const SVal V; + +public: + TaintBugVisitor(const SVal V) : V(V) {} + void Profile(llvm::FoldingSetNodeID &ID) const override { ID.Add(V); } + + std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; +}; + +/// The bug visitor will walk all the nodes in a path and collect all the +/// constraints. When it reaches the root node, will create a refutation +/// manager and check if the constraints are satisfiable +class FalsePositiveRefutationBRVisitor final : public BugReporterVisitor { +private: + /// Holds the constraints in a given path + ConstraintRangeTy Constraints; + +public: + FalsePositiveRefutationBRVisitor(); + + void Profile(llvm::FoldingSetNodeID &ID) const override; + + std::shared_ptr<PathDiagnosticPiece> VisitNode(const ExplodedNode *N, + const ExplodedNode *PrevN, + BugReporterContext &BRC, + BugReport &BR) override; + + void finalizeVisitor(BugReporterContext &BRC, const ExplodedNode *EndPathNode, + BugReport &BR) override; +}; + namespace bugreporter { /// Attempts to add visitors to trace a null or undefined value back to its @@ -370,10 +379,10 @@ const Stmt *GetDenomExpr(const ExplodedNode *N); const Stmt *GetRetValExpr(const ExplodedNode *N); bool isDeclRefExprToReference(const Expr *E); +} // namespace bugreporter -} // end namespace clang -} // end namespace ento -} // end namespace bugreporter +} // namespace ento +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_BUGREPORTERVISITORS_H diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h index 18fa85c9657f6..c723f31aec266 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/BugType.h @@ -1,4 +1,4 @@ -//===--- BugType.h - Bug Information Desciption ----------------*- C++ -*-===// +//===--- BugType.h - Bug Information Description ---------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -32,27 +32,39 @@ private: const CheckName Check; const std::string Name; const std::string Category; - bool SuppressonSink; + const CheckerBase *Checker; + bool SuppressOnSink; virtual void anchor(); + public: - BugType(class CheckName check, StringRef name, StringRef cat) - : Check(check), Name(name), Category(cat), SuppressonSink(false) {} - BugType(const CheckerBase *checker, StringRef name, StringRef cat) - : Check(checker->getCheckName()), Name(name), Category(cat), - SuppressonSink(false) {} - virtual ~BugType() {} - - // FIXME: Should these be made strings as well? + BugType(CheckName Check, StringRef Name, StringRef Cat) + : Check(Check), Name(Name), Category(Cat), Checker(nullptr), + SuppressOnSink(false) {} + BugType(const CheckerBase *Checker, StringRef Name, StringRef Cat) + : Check(Checker->getCheckName()), Name(Name), Category(Cat), + Checker(Checker), SuppressOnSink(false) {} + virtual ~BugType() = default; + StringRef getName() const { return Name; } StringRef getCategory() const { return Category; } - StringRef getCheckName() const { return Check.getName(); } + StringRef getCheckName() const { + // FIXME: This is a workaround to ensure that the correct check name is used + // The check names are set after the constructors are run. + // In case the BugType object is initialized in the checker's ctor + // the Check field will be empty. To circumvent this problem we use + // CheckerBase whenever it is possible. + StringRef CheckName = + Checker ? Checker->getCheckName().getName() : Check.getName(); + assert(!CheckName.empty() && "Check name is not set properly."); + return CheckName; + } /// isSuppressOnSink - Returns true if bug reports associated with this bug /// type should be suppressed if the end node of the report is post-dominated /// by a sink node. - bool isSuppressOnSink() const { return SuppressonSink; } - void setSuppressOnSink(bool x) { SuppressonSink = x; } + bool isSuppressOnSink() const { return SuppressOnSink; } + void setSuppressOnSink(bool x) { SuppressOnSink = x; } virtual void FlushReports(BugReporter& BR); }; @@ -74,7 +86,7 @@ public: StringRef getDescription() const { return desc; } }; -} // end GR namespace +} // end ento namespace } // end clang namespace #endif diff --git a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h index f31ab2cd81cd2..b18d3c9b3031c 100644 --- a/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h +++ b/include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h @@ -1,4 +1,4 @@ -//===--- PathDiagnostic.h - Path-Specific Diagnostic Handling ---*- C++ -*-===// +//===- PathDiagnostic.h - Path-Specific Diagnostic Handling -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,37 +14,49 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H #define LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H -#include "clang/Analysis/ProgramPoint.h" +#include "clang/AST/Stmt.h" +#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Basic/LLVM.h" #include "clang/Basic/SourceLocation.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/FoldingSet.h" -#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include <cassert> #include <deque> #include <iterator> #include <list> +#include <map> +#include <memory> +#include <set> #include <string> +#include <utility> #include <vector> namespace clang { -class ConditionalOperator; + class AnalysisDeclContext; class BinaryOperator; -class CompoundStmt; +class CallEnter; +class CallExitEnd; +class CallExpr; +class ConditionalOperator; class Decl; +class Expr; class LocationContext; class MemberExpr; -class ParentMap; class ProgramPoint; class SourceManager; -class Stmt; -class CallExpr; namespace ento { class ExplodedNode; class SymExpr; -typedef const SymExpr* SymbolRef; + +using SymbolRef = const SymExpr *; //===----------------------------------------------------------------------===// // High-level interface for handlers of path-sensitive diagnostics. @@ -58,15 +70,15 @@ public: public: PDFileEntry(llvm::FoldingSetNodeID &NodeID) : NodeID(NodeID) {} - typedef std::vector<std::pair<StringRef, StringRef> > ConsumerFiles; + using ConsumerFiles = std::vector<std::pair<StringRef, StringRef>>; - /// \brief A vector of <consumer,file> pairs. + /// A vector of <consumer,file> pairs. ConsumerFiles files; - /// \brief A precomputed hash tag used for uniquing PDFileEntry objects. + /// A precomputed hash tag used for uniquing PDFileEntry objects. const llvm::FoldingSetNodeID NodeID; - /// \brief Used for profiling in the FoldingSet. + /// Used for profiling in the FoldingSet. void Profile(llvm::FoldingSetNodeID &ID) { ID = NodeID; } }; @@ -88,8 +100,9 @@ public: private: virtual void anchor(); + public: - PathDiagnosticConsumer() : flushed(false) {} + PathDiagnosticConsumer() = default; virtual ~PathDiagnosticConsumer(); void FlushDiagnostics(FilesMade *FilesMade); @@ -101,7 +114,17 @@ public: void HandlePathDiagnostic(std::unique_ptr<PathDiagnostic> D); - enum PathGenerationScheme { None, Minimal, Extensive, AlternateExtensive }; + enum PathGenerationScheme { + /// Only runs visitors, no output generated. + None, + + /// Used for HTML and text output. + Minimal, + + /// Used for plist output, used for "arrows" generation. + Extensive, + }; + virtual PathGenerationScheme getGenerationScheme() const { return Minimal; } virtual bool supportsLogicalOpControlFlow() const { return false; } @@ -110,7 +133,7 @@ public: virtual bool supportsCrossFileDiagnostics() const { return false; } protected: - bool flushed; + bool flushed = false; llvm::FoldingSet<PathDiagnostic> Diags; }; @@ -120,31 +143,28 @@ protected: class PathDiagnosticRange : public SourceRange { public: - bool isPoint; + bool isPoint = false; PathDiagnosticRange(SourceRange R, bool isP = false) - : SourceRange(R), isPoint(isP) {} - - PathDiagnosticRange() : isPoint(false) {} + : SourceRange(R), isPoint(isP) {} + PathDiagnosticRange() = default; }; -typedef llvm::PointerUnion<const LocationContext*, AnalysisDeclContext*> - LocationOrAnalysisDeclContext; +using LocationOrAnalysisDeclContext = + llvm::PointerUnion<const LocationContext *, AnalysisDeclContext *>; class PathDiagnosticLocation { private: - enum Kind { RangeK, SingleLocK, StmtK, DeclK } K; - const Stmt *S; - const Decl *D; - const SourceManager *SM; + enum Kind { RangeK, SingleLocK, StmtK, DeclK } K = SingleLocK; + + const Stmt *S = nullptr; + const Decl *D = nullptr; + const SourceManager *SM = nullptr; FullSourceLoc Loc; PathDiagnosticRange Range; - PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, - Kind kind) - : K(kind), S(nullptr), D(nullptr), SM(&sm), - Loc(genLocation(L)), Range(genRange()) { - } + PathDiagnosticLocation(SourceLocation L, const SourceManager &sm, Kind kind) + : K(kind), SM(&sm), Loc(genLocation(L)), Range(genRange()) {} FullSourceLoc genLocation( SourceLocation L = SourceLocation(), @@ -155,18 +175,15 @@ private: public: /// Create an invalid location. - PathDiagnosticLocation() - : K(SingleLocK), S(nullptr), D(nullptr), SM(nullptr) {} + PathDiagnosticLocation() = default; /// Create a location corresponding to the given statement. PathDiagnosticLocation(const Stmt *s, const SourceManager &sm, LocationOrAnalysisDeclContext lac) - : K(s->getLocStart().isValid() ? StmtK : SingleLocK), - S(K == StmtK ? s : nullptr), - D(nullptr), SM(&sm), - Loc(genLocation(SourceLocation(), lac)), - Range(genRange(lac)) { + : K(s->getLocStart().isValid() ? StmtK : SingleLocK), + S(K == StmtK ? s : nullptr), SM(&sm), + Loc(genLocation(SourceLocation(), lac)), Range(genRange(lac)) { assert(K == SingleLocK || S); assert(K == SingleLocK || Loc.isValid()); assert(K == SingleLocK || Range.isValid()); @@ -174,8 +191,7 @@ public: /// Create a location corresponding to the given declaration. PathDiagnosticLocation(const Decl *d, const SourceManager &sm) - : K(DeclK), S(nullptr), D(d), SM(&sm), - Loc(genLocation()), Range(genRange()) { + : K(DeclK), D(d), SM(&sm), Loc(genLocation()), Range(genRange()) { assert(D); assert(Loc.isValid()); assert(Range.isValid()); @@ -185,8 +201,7 @@ public: /// /// This should only be used if there are no more appropriate constructors. PathDiagnosticLocation(SourceLocation loc, const SourceManager &sm) - : K(SingleLocK), S(nullptr), D(nullptr), SM(&sm), Loc(loc, sm), - Range(genRange()) { + : SM(&sm), Loc(loc, sm), Range(genRange()) { assert(Loc.isValid()); assert(Range.isValid()); } @@ -201,6 +216,15 @@ public: static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM); + /// Create a location for the beginning of the declaration. + /// The third argument is ignored, useful for generic treatment + /// of statements and declarations. + static PathDiagnosticLocation + createBegin(const Decl *D, const SourceManager &SM, + const LocationOrAnalysisDeclContext LAC) { + return createBegin(D, SM); + } + /// Create a location for the beginning of the statement. static PathDiagnosticLocation createBegin(const Stmt *S, const SourceManager &SM, @@ -248,7 +272,7 @@ public: const SourceManager &SM); /// Create a location corresponding to the given valid ExplodedNode. - static PathDiagnosticLocation create(const ProgramPoint& P, + static PathDiagnosticLocation create(const ProgramPoint &P, const SourceManager &SMng); /// Create a location corresponding to the next valid ExplodedNode as end @@ -281,6 +305,12 @@ public: } const Stmt *asStmt() const { assert(isValid()); return S; } + const Stmt *getStmtOrNull() const { + if (!isValid()) + return nullptr; + return asStmt(); + } + const Decl *asDecl() const { assert(isValid()); return D; } bool hasRange() const { return K == StmtK || K == RangeK || K == DeclK; } @@ -297,21 +327,22 @@ public: void dump() const; - /// \brief Given an exploded node, retrieve the statement that should be used + /// Given an exploded node, retrieve the statement that should be used /// for the diagnostic location. static const Stmt *getStmt(const ExplodedNode *N); - /// \brief Retrieve the statement corresponding to the successor node. + /// Retrieve the statement corresponding to the successor node. static const Stmt *getNextStmt(const ExplodedNode *N); }; class PathDiagnosticLocationPair { private: PathDiagnosticLocation Start, End; + public: PathDiagnosticLocationPair(const PathDiagnosticLocation &start, const PathDiagnosticLocation &end) - : Start(start), End(end) {} + : Start(start), End(end) {} const PathDiagnosticLocation &getStart() const { return Start; } const PathDiagnosticLocation &getEnd() const { return End; } @@ -344,9 +375,9 @@ private: const Kind kind; const DisplayHint Hint; - /// \brief In the containing bug report, this piece is the last piece from + /// In the containing bug report, this piece is the last piece from /// the main source file. - bool LastInMainSourceFile; + bool LastInMainSourceFile = false; /// A constant string that can be used to tag the PathDiagnosticPiece, /// typically with the identification of the creator. The actual pointer @@ -356,16 +387,14 @@ private: std::vector<SourceRange> ranges; - PathDiagnosticPiece() = delete; - PathDiagnosticPiece(const PathDiagnosticPiece &P) = delete; - void operator=(const PathDiagnosticPiece &P) = delete; - protected: PathDiagnosticPiece(StringRef s, Kind k, DisplayHint hint = Below); - PathDiagnosticPiece(Kind k, DisplayHint hint = Below); public: + PathDiagnosticPiece() = delete; + PathDiagnosticPiece(const PathDiagnosticPiece &) = delete; + PathDiagnosticPiece &operator=(const PathDiagnosticPiece &) = delete; virtual ~PathDiagnosticPiece(); StringRef getString() const { return str; } @@ -420,8 +449,8 @@ public: class PathPieces : public std::list<std::shared_ptr<PathDiagnosticPiece>> { void flattenTo(PathPieces &Primary, PathPieces &Current, bool ShouldFlattenMacros) const; -public: +public: PathPieces flatten(bool ShouldFlattenMacros) const { PathPieces Result; flattenTo(Result, Result, ShouldFlattenMacros); @@ -434,12 +463,13 @@ public: class PathDiagnosticSpotPiece : public PathDiagnosticPiece { private: PathDiagnosticLocation Pos; + public: PathDiagnosticSpotPiece(const PathDiagnosticLocation &pos, StringRef s, PathDiagnosticPiece::Kind k, bool addPosRange = true) - : PathDiagnosticPiece(s, k), Pos(pos) { + : PathDiagnosticPiece(s, k), Pos(pos) { assert(Pos.isValid() && Pos.asLocation().isValid() && "PathDiagnosticSpotPiece's must have a valid location."); if (addPosRange && Pos.hasRange()) addRange(Pos.asRange()); @@ -456,7 +486,7 @@ public: } }; -/// \brief Interface for classes constructing Stack hints. +/// Interface for classes constructing Stack hints. /// /// If a PathDiagnosticEvent occurs in a different frame than the final /// diagnostic the hints can be used to summarize the effect of the call. @@ -464,11 +494,11 @@ class StackHintGenerator { public: virtual ~StackHintGenerator() = 0; - /// \brief Construct the Diagnostic message for the given ExplodedNode. + /// Construct the Diagnostic message for the given ExplodedNode. virtual std::string getMessage(const ExplodedNode *N) = 0; }; -/// \brief Constructs a Stack hint for the given symbol. +/// Constructs a Stack hint for the given symbol. /// /// The class knows how to construct the stack hint message based on /// traversing the CallExpr associated with the call and checking if the given @@ -481,18 +511,20 @@ private: public: StackHintGeneratorForSymbol(SymbolRef S, StringRef M) : Sym(S), Msg(M) {} - ~StackHintGeneratorForSymbol() override {} + ~StackHintGeneratorForSymbol() override = default; - /// \brief Search the call expression for the symbol Sym and dispatch the + /// Search the call expression for the symbol Sym and dispatch the /// 'getMessageForX()' methods to construct a specific message. std::string getMessage(const ExplodedNode *N) override; /// Produces the message of the following form: /// 'Msg via Nth parameter' virtual std::string getMessageForArg(const Expr *ArgE, unsigned ArgIndex); + virtual std::string getMessageForReturn(const CallExpr *CallExpr) { return Msg; } + virtual std::string getMessageForSymbolNotFound() { return Msg; } @@ -511,9 +543,8 @@ public: PathDiagnosticEventPiece(const PathDiagnosticLocation &pos, StringRef s, bool addPosRange = true, StackHintGenerator *stackHint = nullptr) - : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), - CallStackHint(stackHint) {} - + : PathDiagnosticSpotPiece(pos, s, Event, addPosRange), + CallStackHint(stackHint) {} ~PathDiagnosticEventPiece() override; /// Mark the diagnostic piece as being potentially prunable. This @@ -537,30 +568,19 @@ public: std::string getCallStackMessage(const ExplodedNode *N) { if (CallStackHint) return CallStackHint->getMessage(N); - return ""; + return {}; } void dump() const override; - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Event; } }; class PathDiagnosticCallPiece : public PathDiagnosticPiece { - PathDiagnosticCallPiece(const Decl *callerD, - const PathDiagnosticLocation &callReturnPos) - : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr), - NoExit(false), IsCalleeAnAutosynthesizedPropertyAccessor(false), - callReturn(callReturnPos) {} - - PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) - : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr), - NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false), - path(oldPath) {} - const Decl *Caller; - const Decl *Callee; + const Decl *Callee = nullptr; // Flag signifying that this diagnostic has only call enter and no matching // call exit. @@ -568,12 +588,20 @@ class PathDiagnosticCallPiece : public PathDiagnosticPiece { // Flag signifying that the callee function is an Objective-C autosynthesized // property getter or setter. - bool IsCalleeAnAutosynthesizedPropertyAccessor; + bool IsCalleeAnAutosynthesizedPropertyAccessor = false; // The custom string, which should appear after the call Return Diagnostic. // TODO: Should we allow multiple diagnostics? std::string CallStackMessage; + PathDiagnosticCallPiece(const Decl *callerD, + const PathDiagnosticLocation &callReturnPos) + : PathDiagnosticPiece(Call), Caller(callerD), NoExit(false), + callReturn(callReturnPos) {} + PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller) + : PathDiagnosticPiece(Call), Caller(caller), NoExit(true), + path(oldPath) {} + public: PathDiagnosticLocation callEnter; PathDiagnosticLocation callEnterWithin; @@ -588,13 +616,9 @@ public: void setCallee(const CallEnter &CE, const SourceManager &SM); bool hasCallStackMessage() { return !CallStackMessage.empty(); } - void setCallStackMessage(StringRef st) { - CallStackMessage = st; - } + void setCallStackMessage(StringRef st) { CallStackMessage = st; } - PathDiagnosticLocation getLocation() const override { - return callEnter; - } + PathDiagnosticLocation getLocation() const override { return callEnter; } std::shared_ptr<PathDiagnosticEventPiece> getCallEnterEvent() const; std::shared_ptr<PathDiagnosticEventPiece> @@ -604,8 +628,8 @@ public: void flattenLocations() override { callEnter.flatten(); callReturn.flatten(); - for (PathPieces::iterator I = path.begin(), - E = path.end(); I != E; ++I) (*I)->flattenLocations(); + for (const auto &I : path) + I->flattenLocations(); } static std::shared_ptr<PathDiagnosticCallPiece> @@ -619,28 +643,29 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const override; - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Call; } }; class PathDiagnosticControlFlowPiece : public PathDiagnosticPiece { std::vector<PathDiagnosticLocationPair> LPairs; + public: PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos, StringRef s) - : PathDiagnosticPiece(s, ControlFlow) { - LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); - } + : PathDiagnosticPiece(s, ControlFlow) { + LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); + } PathDiagnosticControlFlowPiece(const PathDiagnosticLocation &startPos, const PathDiagnosticLocation &endPos) - : PathDiagnosticPiece(ControlFlow) { - LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); - } + : PathDiagnosticPiece(ControlFlow) { + LPairs.push_back(PathDiagnosticLocationPair(startPos, endPos)); + } - ~PathDiagnosticControlFlowPiece() override; + ~PathDiagnosticControlFlowPiece() override; PathDiagnosticLocation getStartLocation() const { assert(!LPairs.empty() && @@ -668,20 +693,23 @@ public: return getStartLocation(); } - typedef std::vector<PathDiagnosticLocationPair>::iterator iterator; + using iterator = std::vector<PathDiagnosticLocationPair>::iterator; + iterator begin() { return LPairs.begin(); } - iterator end() { return LPairs.end(); } + iterator end() { return LPairs.end(); } void flattenLocations() override { - for (iterator I=begin(), E=end(); I!=E; ++I) I->flatten(); + for (auto &I : *this) + I.flatten(); } - typedef std::vector<PathDiagnosticLocationPair>::const_iterator - const_iterator; + using const_iterator = + std::vector<PathDiagnosticLocationPair>::const_iterator; + const_iterator begin() const { return LPairs.begin(); } - const_iterator end() const { return LPairs.end(); } + const_iterator end() const { return LPairs.end(); } - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == ControlFlow; } @@ -693,8 +721,7 @@ public: class PathDiagnosticMacroPiece : public PathDiagnosticSpotPiece { public: PathDiagnosticMacroPiece(const PathDiagnosticLocation &pos) - : PathDiagnosticSpotPiece(pos, "", Macro) {} - + : PathDiagnosticSpotPiece(pos, "", Macro) {} ~PathDiagnosticMacroPiece() override; PathPieces subPieces; @@ -703,11 +730,11 @@ public: void flattenLocations() override { PathDiagnosticSpotPiece::flattenLocations(); - for (PathPieces::iterator I = subPieces.begin(), - E = subPieces.end(); I != E; ++I) (*I)->flattenLocations(); + for (const auto &I : subPieces) + I->flattenLocations(); } - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Macro; } @@ -721,10 +748,9 @@ public: PathDiagnosticNotePiece(const PathDiagnosticLocation &Pos, StringRef S, bool AddPosRange = true) : PathDiagnosticSpotPiece(Pos, S, Note, AddPosRange) {} - ~PathDiagnosticNotePiece() override; - static inline bool classof(const PathDiagnosticPiece *P) { + static bool classof(const PathDiagnosticPiece *P) { return P->getKind() == Note; } @@ -733,6 +759,9 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const override; }; +/// File IDs mapped to sets of line numbers. +using FilesToLineNumsMap = std::map<unsigned, std::set<unsigned>>; + /// PathDiagnostic - PathDiagnostic objects represent a single path-sensitive /// diagnostic. It represents an ordered-collection of PathDiagnosticPieces, /// each which represent the pieces of the path. @@ -745,24 +774,27 @@ class PathDiagnostic : public llvm::FoldingSetNode { std::string Category; std::deque<std::string> OtherDesc; - /// \brief Loc The location of the path diagnostic report. + /// Loc The location of the path diagnostic report. PathDiagnosticLocation Loc; PathPieces pathImpl; SmallVector<PathPieces *, 3> pathStack; - /// \brief Important bug uniqueing location. + /// Important bug uniqueing location. /// The location info is useful to differentiate between bugs. PathDiagnosticLocation UniqueingLoc; const Decl *UniqueingDecl; - PathDiagnostic() = delete; + /// Lines executed in the path. + std::unique_ptr<FilesToLineNumsMap> ExecutedLines; + public: + PathDiagnostic() = delete; PathDiagnostic(StringRef CheckName, const Decl *DeclWithIssue, StringRef bugtype, StringRef verboseDesc, StringRef shortDesc, StringRef category, PathDiagnosticLocation LocationToUnique, - const Decl *DeclToUnique); - + const Decl *DeclToUnique, + std::unique_ptr<FilesToLineNumsMap> ExecutedLines); ~PathDiagnostic(); const PathPieces &path; @@ -788,7 +820,7 @@ public: bool isWithinCall() const { return !pathStack.empty(); } - void setEndOfPath(std::unique_ptr<PathDiagnosticPiece> EndPiece) { + void setEndOfPath(std::shared_ptr<PathDiagnosticPiece> EndPiece) { assert(!Loc.isValid() && "End location already set!"); Loc = EndPiece->getLocation(); assert(Loc.isValid() && "Invalid location for end-of-path piece"); @@ -801,21 +833,17 @@ public: VerboseDesc += S; } - void resetPath() { - pathStack.clear(); - pathImpl.clear(); - Loc = PathDiagnosticLocation(); - } - - /// \brief If the last piece of the report point to the header file, resets + /// If the last piece of the report point to the header file, resets /// the location of the report to be the last location in the main source /// file. void resetDiagnosticLocationToMainFile(); StringRef getVerboseDescription() const { return VerboseDesc; } + StringRef getShortDescription() const { return ShortDesc.empty() ? VerboseDesc : ShortDesc; } + StringRef getCheckName() const { return CheckName; } StringRef getBugType() const { return BugType; } StringRef getCategory() const { return Category; } @@ -825,30 +853,38 @@ public: /// where the bug manifests. const Decl *getDeclWithIssue() const { return DeclWithIssue; } - typedef std::deque<std::string>::const_iterator meta_iterator; + using meta_iterator = std::deque<std::string>::const_iterator; + meta_iterator meta_begin() const { return OtherDesc.begin(); } meta_iterator meta_end() const { return OtherDesc.end(); } void addMeta(StringRef s) { OtherDesc.push_back(s); } + using filesmap_iterator = FilesToLineNumsMap::const_iterator; + + filesmap_iterator executedLines_begin() const { + return ExecutedLines->begin(); + } + + filesmap_iterator executedLines_end() const { return ExecutedLines->end(); } + PathDiagnosticLocation getLocation() const { - assert(Loc.isValid() && "No report location set yet!"); return Loc; } - /// \brief Get the location on which the report should be uniqued. + /// Get the location on which the report should be uniqued. PathDiagnosticLocation getUniqueingLoc() const { return UniqueingLoc; } - /// \brief Get the declaration containing the uniqueing location. + /// Get the declaration containing the uniqueing location. const Decl *getUniqueingDecl() const { return UniqueingDecl; } void flattenLocations() { Loc.flatten(); - for (PathPieces::iterator I = pathImpl.begin(), E = pathImpl.end(); - I != E; ++I) (*I)->flattenLocations(); + for (const auto &I : pathImpl) + I->flattenLocations(); } /// Profiles the diagnostic, independent of the path it references. @@ -864,8 +900,8 @@ public: void FullProfile(llvm::FoldingSetNodeID &ID) const; }; -} // end GR namespace +} // namespace ento -} //end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_BUGREPORTER_PATHDIAGNOSTIC_H diff --git a/include/clang/StaticAnalyzer/Core/Checker.h b/include/clang/StaticAnalyzer/Core/Checker.h index f9477762c7585..45b7a61139ea7 100644 --- a/include/clang/StaticAnalyzer/Core/Checker.h +++ b/include/clang/StaticAnalyzer/Core/Checker.h @@ -254,9 +254,9 @@ public: class EndFunction { template <typename CHECKER> - static void _checkEndFunction(void *checker, + static void _checkEndFunction(void *checker, const ReturnStmt *RS, CheckerContext &C) { - ((const CHECKER *)checker)->checkEndFunction(C); + ((const CHECKER *)checker)->checkEndFunction(RS, C); } public: @@ -283,6 +283,22 @@ public: } }; +class NewAllocator { + template <typename CHECKER> + static void _checkNewAllocator(void *checker, const CXXNewExpr *NE, + SVal Target, CheckerContext &C) { + ((const CHECKER *)checker)->checkNewAllocator(NE, Target, C); + } + +public: + template <typename CHECKER> + static void _register(CHECKER *checker, CheckerManager &mgr) { + mgr._registerForNewAllocator( + CheckerManager::CheckNewAllocatorFunc(checker, + _checkNewAllocator<CHECKER>)); + } +}; + class LiveSymbols { template <typename CHECKER> static void _checkLiveSymbols(void *checker, ProgramStateRef state, @@ -532,7 +548,7 @@ public: } }; -/// \brief We dereferenced a location that may be null. +/// We dereferenced a location that may be null. struct ImplicitNullDerefEvent { SVal Location; bool IsLoad; @@ -544,7 +560,7 @@ struct ImplicitNullDerefEvent { bool IsDirectDereference; }; -/// \brief A helper class which wraps a boolean value set to false by default. +/// A helper class which wraps a boolean value set to false by default. /// /// This class should behave exactly like 'bool' except that it doesn't need to /// be explicitly initialized. diff --git a/include/clang/StaticAnalyzer/Core/CheckerManager.h b/include/clang/StaticAnalyzer/Core/CheckerManager.h index 88cb08a4b647c..33a794061a384 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerManager.h +++ b/include/clang/StaticAnalyzer/Core/CheckerManager.h @@ -1,4 +1,4 @@ -//===--- CheckerManager.h - Static Analyzer Checker Manager -----*- C++ -*-===// +//===- CheckerManager.h - Static Analyzer Checker Manager -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,51 +16,62 @@ #include "clang/Analysis/ProgramPoint.h" #include "clang/Basic/LangOptions.h" -#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/Store.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/SmallVector.h" -#include <utility> +#include "llvm/ADT/StringRef.h" #include <vector> namespace clang { - class Decl; - class Stmt; - class CallExpr; + +class AnalyzerOptions; +class CallExpr; +class CXXNewExpr; +class Decl; +class LocationContext; +class Stmt; +class TranslationUnitDecl; namespace ento { - class CheckerBase; - class CheckerRegistry; - class ExprEngine; - class AnalysisManager; - class BugReporter; - class CheckerContext; - class ObjCMethodCall; - class SVal; - class ExplodedNode; - class ExplodedNodeSet; - class ExplodedGraph; - class ProgramState; - class NodeBuilder; - struct NodeBuilderContext; - class MemRegion; - class SymbolReaper; + +class AnalysisManager; +class BugReporter; +class CallEvent; +class CheckerBase; +class CheckerContext; +class CheckerRegistry; +class ExplodedGraph; +class ExplodedNode; +class ExplodedNodeSet; +class ExprEngine; +class MemRegion; +struct NodeBuilderContext; +class ObjCMethodCall; +class RegionAndSymbolInvalidationTraits; +class SVal; +class SymbolReaper; template <typename T> class CheckerFn; template <typename RET, typename... Ps> class CheckerFn<RET(Ps...)> { - typedef RET (*Func)(void *, Ps...); + using Func = RET (*)(void *, Ps...); + Func Fn; + public: CheckerBase *Checker; - CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) { } + + CheckerFn(CheckerBase *checker, Func fn) : Fn(fn), Checker(checker) {} + RET operator()(Ps... ps) const { return Fn(Checker, ps...); } }; -/// \brief Describes the different reasons a pointer escapes +/// Describes the different reasons a pointer escapes /// during analysis. enum PointerEscapeKind { /// A pointer escapes due to binding its value to a location @@ -85,12 +96,15 @@ enum PointerEscapeKind { // name strings have a lifetime that keeps them alive at least until the path // diagnostics have been processed. class CheckName { - StringRef Name; friend class ::clang::ento::CheckerRegistry; + + StringRef Name; + explicit CheckName(StringRef Name) : Name(Name) {} public: CheckName() = default; + StringRef getName() const { return Name; } }; @@ -121,40 +135,27 @@ public: const LangOptions &getLangOpts() const { return LangOpts; } AnalyzerOptions &getAnalyzerOptions() { return AOptions; } - typedef CheckerBase *CheckerRef; - typedef const void *CheckerTag; - typedef CheckerFn<void ()> CheckerDtor; + using CheckerRef = CheckerBase *; + using CheckerTag = const void *; + using CheckerDtor = CheckerFn<void ()>; //===----------------------------------------------------------------------===// // registerChecker //===----------------------------------------------------------------------===// - /// \brief Used to register checkers. + /// Used to register checkers. + /// All arguments are automatically passed through to the checker + /// constructor. /// /// \returns a pointer to the checker object. - template <typename CHECKER> - CHECKER *registerChecker() { + template <typename CHECKER, typename... AT> + CHECKER *registerChecker(AT... Args) { CheckerTag tag = getTag<CHECKER>(); CheckerRef &ref = CheckerTags[tag]; if (ref) return static_cast<CHECKER *>(ref); // already registered. - CHECKER *checker = new CHECKER(); - checker->Name = CurrentCheckName; - CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); - CHECKER::_register(checker, *this); - ref = checker; - return checker; - } - - template <typename CHECKER> - CHECKER *registerChecker(AnalyzerOptions &AOpts) { - CheckerTag tag = getTag<CHECKER>(); - CheckerRef &ref = CheckerTags[tag]; - if (ref) - return static_cast<CHECKER *>(ref); // already registered. - - CHECKER *checker = new CHECKER(AOpts); + CHECKER *checker = new CHECKER(Args...); checker->Name = CurrentCheckName; CheckerDtors.push_back(CheckerDtor(checker, destruct<CHECKER>)); CHECKER::_register(checker, *this); @@ -166,11 +167,11 @@ public: // Functions for running checkers for AST traversing.. //===----------------------------------------------------------------------===// - /// \brief Run checkers handling Decls. + /// Run checkers handling Decls. void runCheckersOnASTDecl(const Decl *D, AnalysisManager& mgr, BugReporter &BR); - /// \brief Run checkers handling Decls containing a Stmt body. + /// Run checkers handling Decls containing a Stmt body. void runCheckersOnASTBody(const Decl *D, AnalysisManager& mgr, BugReporter &BR); @@ -178,7 +179,7 @@ public: // Functions for running checkers for path-sensitive checking. //===----------------------------------------------------------------------===// - /// \brief Run checkers for pre-visiting Stmts. + /// Run checkers for pre-visiting Stmts. /// /// The notification is performed for every explored CFGElement, which does /// not include the control flow statements such as IfStmt. @@ -191,7 +192,7 @@ public: runCheckersForStmt(/*isPreVisit=*/true, Dst, Src, S, Eng); } - /// \brief Run checkers for post-visiting Stmts. + /// Run checkers for post-visiting Stmts. /// /// The notification is performed for every explored CFGElement, which does /// not include the control flow statements such as IfStmt. @@ -205,13 +206,13 @@ public: runCheckersForStmt(/*isPreVisit=*/false, Dst, Src, S, Eng, wasInlined); } - /// \brief Run checkers for visiting Stmts. + /// Run checkers for visiting Stmts. void runCheckersForStmt(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const Stmt *S, ExprEngine &Eng, bool wasInlined = false); - /// \brief Run checkers for pre-visiting obj-c messages. + /// Run checkers for pre-visiting obj-c messages. void runCheckersForPreObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, @@ -219,7 +220,7 @@ public: runCheckersForObjCMessage(ObjCMessageVisitKind::Pre, Dst, Src, msg, Eng); } - /// \brief Run checkers for post-visiting obj-c messages. + /// Run checkers for post-visiting obj-c messages. void runCheckersForPostObjCMessage(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, @@ -229,7 +230,7 @@ public: wasInlined); } - /// \brief Run checkers for visiting an obj-c message to nil. + /// Run checkers for visiting an obj-c message to nil. void runCheckersForObjCMessageNil(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, @@ -238,21 +239,20 @@ public: Eng); } - - /// \brief Run checkers for visiting obj-c messages. + /// Run checkers for visiting obj-c messages. void runCheckersForObjCMessage(ObjCMessageVisitKind visitKind, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const ObjCMethodCall &msg, ExprEngine &Eng, bool wasInlined = false); - /// \brief Run checkers for pre-visiting obj-c messages. + /// Run checkers for pre-visiting obj-c messages. void runCheckersForPreCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng) { runCheckersForCallEvent(/*isPreVisit=*/true, Dst, Src, Call, Eng); } - /// \brief Run checkers for post-visiting obj-c messages. + /// Run checkers for post-visiting obj-c messages. void runCheckersForPostCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined = false) { @@ -260,13 +260,13 @@ public: wasInlined); } - /// \brief Run checkers for visiting obj-c messages. + /// Run checkers for visiting obj-c messages. void runCheckersForCallEvent(bool isPreVisit, ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &Call, ExprEngine &Eng, bool wasInlined = false); - /// \brief Run checkers for load/store of a location. + /// Run checkers for load/store of a location. void runCheckersForLocation(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, @@ -275,35 +275,43 @@ public: const Stmt *BoundEx, ExprEngine &Eng); - /// \brief Run checkers for binding of a value to a location. + /// Run checkers for binding of a value to a location. void runCheckersForBind(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, SVal location, SVal val, const Stmt *S, ExprEngine &Eng, const ProgramPoint &PP); - /// \brief Run checkers for end of analysis. + /// Run checkers for end of analysis. void runCheckersForEndAnalysis(ExplodedGraph &G, BugReporter &BR, ExprEngine &Eng); - /// \brief Run checkers on beginning of function. + /// Run checkers on beginning of function. void runCheckersForBeginFunction(ExplodedNodeSet &Dst, const BlockEdge &L, ExplodedNode *Pred, ExprEngine &Eng); - /// \brief Run checkers on end of function. + /// Run checkers on end of function. void runCheckersForEndFunction(NodeBuilderContext &BC, ExplodedNodeSet &Dst, ExplodedNode *Pred, - ExprEngine &Eng); + ExprEngine &Eng, + const ReturnStmt *RS); - /// \brief Run checkers for branch condition. + /// Run checkers for branch condition. void runCheckersForBranchCondition(const Stmt *condition, ExplodedNodeSet &Dst, ExplodedNode *Pred, ExprEngine &Eng); - /// \brief Run checkers for live symbols. + /// Run checkers between C++ operator new and constructor calls. + void runCheckersForNewAllocator(const CXXNewExpr *NE, SVal Target, + ExplodedNodeSet &Dst, + ExplodedNode *Pred, + ExprEngine &Eng, + bool wasInlined = false); + + /// Run checkers for live symbols. /// /// Allows modifying SymbolReaper object. For example, checkers can explicitly /// register symbols of interest as live. These symbols will not be marked @@ -311,7 +319,7 @@ public: void runCheckersForLiveSymbols(ProgramStateRef state, SymbolReaper &SymReaper); - /// \brief Run checkers for dead symbols. + /// Run checkers for dead symbols. /// /// Notifies checkers when symbols become dead. For example, this allows /// checkers to aggressively clean up/reduce the checker state and produce @@ -322,7 +330,7 @@ public: ExprEngine &Eng, ProgramPoint::Kind K); - /// \brief Run checkers for region changes. + /// Run checkers for region changes. /// /// This corresponds to the check::RegionChanges callback. /// \param state The current program state. @@ -341,7 +349,7 @@ public: const LocationContext *LCtx, const CallEvent *Call); - /// \brief Run checkers when pointers escape. + /// Run checkers when pointers escape. /// /// This notifies the checkers about pointer escape, which occurs whenever /// the analyzer cannot track the symbol any more. For example, as a @@ -361,25 +369,25 @@ public: const InvalidatedSymbols &Escaped, const CallEvent *Call, PointerEscapeKind Kind, - RegionAndSymbolInvalidationTraits *ITraits); + RegionAndSymbolInvalidationTraits *ITraits); - /// \brief Run checkers for handling assumptions on symbolic values. + /// Run checkers for handling assumptions on symbolic values. ProgramStateRef runCheckersForEvalAssume(ProgramStateRef state, SVal Cond, bool Assumption); - /// \brief Run checkers for evaluating a call. + /// Run checkers for evaluating a call. /// /// Warning: Currently, the CallEvent MUST come from a CallExpr! void runCheckersForEvalCall(ExplodedNodeSet &Dst, const ExplodedNodeSet &Src, const CallEvent &CE, ExprEngine &Eng); - /// \brief Run checkers for the entire Translation Unit. + /// Run checkers for the entire Translation Unit. void runCheckersOnEndOfTranslationUnit(const TranslationUnitDecl *TU, AnalysisManager &mgr, BugReporter &BR); - /// \brief Run checkers for debug-printing a ProgramState. + /// Run checkers for debug-printing a ProgramState. /// /// Unlike most other callbacks, any checker can simply implement the virtual /// method CheckerBase::printState if it has custom data to print. @@ -397,10 +405,11 @@ public: // Functions used by the registration mechanism, checkers should not touch // these directly. - typedef CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)> - CheckDeclFunc; + using CheckDeclFunc = + CheckerFn<void (const Decl *, AnalysisManager&, BugReporter &)>; + + using HandlesDeclFunc = bool (*)(const Decl *D); - typedef bool (*HandlesDeclFunc)(const Decl *D); void _registerForDecl(CheckDeclFunc checkfn, HandlesDeclFunc isForDeclFn); void _registerForBody(CheckDeclFunc checkfn); @@ -409,67 +418,67 @@ public: // Internal registration functions for path-sensitive checking. //===----------------------------------------------------------------------===// - typedef CheckerFn<void (const Stmt *, CheckerContext &)> CheckStmtFunc; + using CheckStmtFunc = CheckerFn<void (const Stmt *, CheckerContext &)>; - typedef CheckerFn<void (const ObjCMethodCall &, CheckerContext &)> - CheckObjCMessageFunc; + using CheckObjCMessageFunc = + CheckerFn<void (const ObjCMethodCall &, CheckerContext &)>; - typedef CheckerFn<void (const CallEvent &, CheckerContext &)> - CheckCallFunc; + using CheckCallFunc = + CheckerFn<void (const CallEvent &, CheckerContext &)>; - typedef CheckerFn<void (const SVal &location, bool isLoad, - const Stmt *S, - CheckerContext &)> - CheckLocationFunc; + using CheckLocationFunc = + CheckerFn<void (const SVal &location, bool isLoad, const Stmt *S, + CheckerContext &)>; - typedef CheckerFn<void (const SVal &location, const SVal &val, - const Stmt *S, CheckerContext &)> - CheckBindFunc; + using CheckBindFunc = + CheckerFn<void (const SVal &location, const SVal &val, const Stmt *S, + CheckerContext &)>; - typedef CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)> - CheckEndAnalysisFunc; + using CheckEndAnalysisFunc = + CheckerFn<void (ExplodedGraph &, BugReporter &, ExprEngine &)>; - typedef CheckerFn<void (CheckerContext &)> - CheckBeginFunctionFunc; + using CheckBeginFunctionFunc = CheckerFn<void (CheckerContext &)>; - typedef CheckerFn<void (CheckerContext &)> - CheckEndFunctionFunc; + using CheckEndFunctionFunc = + CheckerFn<void (const ReturnStmt *, CheckerContext &)>; - typedef CheckerFn<void (const Stmt *, CheckerContext &)> - CheckBranchConditionFunc; + using CheckBranchConditionFunc = + CheckerFn<void (const Stmt *, CheckerContext &)>; + + using CheckNewAllocatorFunc = + CheckerFn<void (const CXXNewExpr *, SVal, CheckerContext &)>; - typedef CheckerFn<void (SymbolReaper &, CheckerContext &)> - CheckDeadSymbolsFunc; + using CheckDeadSymbolsFunc = + CheckerFn<void (SymbolReaper &, CheckerContext &)>; - typedef CheckerFn<void (ProgramStateRef,SymbolReaper &)> CheckLiveSymbolsFunc; + using CheckLiveSymbolsFunc = CheckerFn<void (ProgramStateRef,SymbolReaper &)>; - typedef CheckerFn<ProgramStateRef (ProgramStateRef, - const InvalidatedSymbols *symbols, - ArrayRef<const MemRegion *> ExplicitRegions, - ArrayRef<const MemRegion *> Regions, - const LocationContext *LCtx, - const CallEvent *Call)> - CheckRegionChangesFunc; + using CheckRegionChangesFunc = + CheckerFn<ProgramStateRef (ProgramStateRef, + const InvalidatedSymbols *symbols, + ArrayRef<const MemRegion *> ExplicitRegions, + ArrayRef<const MemRegion *> Regions, + const LocationContext *LCtx, + const CallEvent *Call)>; - typedef CheckerFn<ProgramStateRef (ProgramStateRef, - const InvalidatedSymbols &Escaped, - const CallEvent *Call, - PointerEscapeKind Kind, - RegionAndSymbolInvalidationTraits *ITraits)> - CheckPointerEscapeFunc; + using CheckPointerEscapeFunc = + CheckerFn<ProgramStateRef (ProgramStateRef, + const InvalidatedSymbols &Escaped, + const CallEvent *Call, PointerEscapeKind Kind, + RegionAndSymbolInvalidationTraits *ITraits)>; - typedef CheckerFn<ProgramStateRef (ProgramStateRef, - const SVal &cond, bool assumption)> - EvalAssumeFunc; + using EvalAssumeFunc = + CheckerFn<ProgramStateRef (ProgramStateRef, const SVal &cond, + bool assumption)>; - typedef CheckerFn<bool (const CallExpr *, CheckerContext &)> - EvalCallFunc; + using EvalCallFunc = CheckerFn<bool (const CallExpr *, CheckerContext &)>; - typedef CheckerFn<void (const TranslationUnitDecl *, - AnalysisManager&, BugReporter &)> - CheckEndOfTranslationUnit; + using CheckEndOfTranslationUnit = + CheckerFn<void (const TranslationUnitDecl *, AnalysisManager &, + BugReporter &)>; + + using HandlesStmtFunc = bool (*)(const Stmt *D); - typedef bool (*HandlesStmtFunc)(const Stmt *D); void _registerForPreStmt(CheckStmtFunc checkfn, HandlesStmtFunc isForStmtFn); void _registerForPostStmt(CheckStmtFunc checkfn, @@ -489,11 +498,13 @@ public: void _registerForEndAnalysis(CheckEndAnalysisFunc checkfn); - void _registerForBeginFunction(CheckEndFunctionFunc checkfn); + void _registerForBeginFunction(CheckBeginFunctionFunc checkfn); void _registerForEndFunction(CheckEndFunctionFunc checkfn); void _registerForBranchCondition(CheckBranchConditionFunc checkfn); + void _registerForNewAllocator(CheckNewAllocatorFunc checkfn); + void _registerForLiveSymbols(CheckLiveSymbolsFunc checkfn); void _registerForDeadSymbols(CheckDeadSymbolsFunc checkfn); @@ -514,8 +525,8 @@ public: // Internal registration functions for events. //===----------------------------------------------------------------------===// - typedef void *EventTag; - typedef CheckerFn<void (const void *event)> CheckEventFunc; + using EventTag = void *; + using CheckEventFunc = CheckerFn<void (const void *event)>; template <typename EVENT> void _registerListenerForEvent(CheckEventFunc checkfn) { @@ -535,8 +546,8 @@ public: if (I == Events.end()) return; const EventInfo &info = I->second; - for (unsigned i = 0, e = info.Checkers.size(); i != e; ++i) - info.Checkers[i](&event); + for (const auto Checker : info.Checkers) + Checker(&event); } //===----------------------------------------------------------------------===// @@ -562,8 +573,8 @@ private: std::vector<CheckDeclFunc> BodyCheckers; - typedef SmallVector<CheckDeclFunc, 4> CachedDeclCheckers; - typedef llvm::DenseMap<unsigned, CachedDeclCheckers> CachedDeclCheckersMapTy; + using CachedDeclCheckers = SmallVector<CheckDeclFunc, 4>; + using CachedDeclCheckersMapTy = llvm::DenseMap<unsigned, CachedDeclCheckers>; CachedDeclCheckersMapTy CachedDeclCheckersMap; struct StmtCheckerInfo { @@ -573,8 +584,8 @@ private: }; std::vector<StmtCheckerInfo> StmtCheckers; - typedef SmallVector<CheckStmtFunc, 4> CachedStmtCheckers; - typedef llvm::DenseMap<unsigned, CachedStmtCheckers> CachedStmtCheckersMapTy; + using CachedStmtCheckers = SmallVector<CheckStmtFunc, 4>; + using CachedStmtCheckersMapTy = llvm::DenseMap<unsigned, CachedStmtCheckers>; CachedStmtCheckersMapTy CachedStmtCheckersMap; const CachedStmtCheckers &getCachedStmtCheckersFor(const Stmt *S, @@ -603,6 +614,8 @@ private: std::vector<CheckBranchConditionFunc> BranchConditionCheckers; + std::vector<CheckNewAllocatorFunc> NewAllocatorCheckers; + std::vector<CheckLiveSymbolsFunc> LiveSymbolsCheckers; std::vector<CheckDeadSymbolsFunc> DeadSymbolsCheckers; @@ -619,16 +632,17 @@ private: struct EventInfo { SmallVector<CheckEventFunc, 4> Checkers; - bool HasDispatcher; - EventInfo() : HasDispatcher(false) { } + bool HasDispatcher = false; + + EventInfo() = default; }; - typedef llvm::DenseMap<EventTag, EventInfo> EventsTy; + using EventsTy = llvm::DenseMap<EventTag, EventInfo>; EventsTy Events; }; -} // end ento namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERMANAGER_H diff --git a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h index 3b26ed3e1a09a..912a601b61c49 100644 --- a/include/clang/StaticAnalyzer/Core/CheckerRegistry.h +++ b/include/clang/StaticAnalyzer/Core/CheckerRegistry.h @@ -1,4 +1,4 @@ -//===--- CheckerRegistry.h - Maintains all available checkers ---*- C++ -*-===// +//===- CheckerRegistry.h - Maintains all available checkers -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -12,6 +12,9 @@ #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/CheckerManager.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include <cstddef> #include <vector> // FIXME: move this information to an HTML file in docs/. @@ -64,8 +67,9 @@ #endif namespace clang { -class DiagnosticsEngine; + class AnalyzerOptions; +class DiagnosticsEngine; namespace ento { @@ -81,17 +85,18 @@ class CheckerRegistry { public: /// Initialization functions perform any necessary setup for a checker. /// They should include a call to CheckerManager::registerChecker. - typedef void (*InitializationFunction)(CheckerManager &); + using InitializationFunction = void (*)(CheckerManager &); + struct CheckerInfo { InitializationFunction Initialize; StringRef FullName; StringRef Desc; CheckerInfo(InitializationFunction fn, StringRef name, StringRef desc) - : Initialize(fn), FullName(name), Desc(desc) {} + : Initialize(fn), FullName(name), Desc(desc) {} }; - typedef std::vector<CheckerInfo> CheckerInfoList; + using CheckerInfoList = std::vector<CheckerInfo>; private: template <typename T> @@ -136,7 +141,8 @@ private: mutable llvm::StringMap<size_t> Packages; }; -} // end namespace ento -} // end namespace clang +} // namespace ento -#endif +} // namespace clang + +#endif // LLVM_CLANG_STATICANALYZER_CORE_CHECKERREGISTRY_H diff --git a/include/clang/StaticAnalyzer/Core/IssueHash.h b/include/clang/StaticAnalyzer/Core/IssueHash.h index b3c4f1465594e..8cb6631fae747 100644 --- a/include/clang/StaticAnalyzer/Core/IssueHash.h +++ b/include/clang/StaticAnalyzer/Core/IssueHash.h @@ -17,7 +17,7 @@ class SourceManager; class FullSourceLoc; class LangOptions; -/// \brief Get an MD5 hash to help identify bugs. +/// Get an MD5 hash to help identify bugs. /// /// This function returns a hash that helps identify bugs within a source file. /// This identification can be utilized to diff diagnostic results on different @@ -41,7 +41,7 @@ llvm::SmallString<32> GetIssueHash(const SourceManager &SM, llvm::StringRef BugType, const Decl *D, const LangOptions &LangOpts); -/// \brief Get the string representation of issue hash. See GetIssueHash() for +/// Get the string representation of issue hash. See GetIssueHash() for /// more information. std::string GetIssueString(const SourceManager &SM, FullSourceLoc &IssueLoc, llvm::StringRef CheckerName, llvm::StringRef BugType, diff --git a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h index ce512fd301ee7..2e81aa38c8de3 100644 --- a/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h +++ b/include/clang/StaticAnalyzer/Core/PathDiagnosticConsumers.h @@ -1,4 +1,4 @@ -//===--- PathDiagnosticClients.h - Path Diagnostic Clients ------*- C++ -*-===// +//===--- PathDiagnosticConsumers.h - Path Diagnostic Clients ------*- C++ -*-===// // // The LLVM Compiler Infrastructure // diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h index cc8a9b8ef0719..93edfcef2d5aa 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h @@ -16,7 +16,7 @@ namespace clang { namespace ento { -/// \brief A record of the "type" of an APSInt, used for conversions. +/// A record of the "type" of an APSInt, used for conversions. class APSIntType { uint32_t BitWidth; bool IsUnsigned; @@ -31,7 +31,7 @@ public: uint32_t getBitWidth() const { return BitWidth; } bool isUnsigned() const { return IsUnsigned; } - /// \brief Convert a given APSInt, in place, to match this type. + /// Convert a given APSInt, in place, to match this type. /// /// This behaves like a C cast: converting 255u8 (0xFF) to s16 gives /// 255 (0x00FF), and converting -1s8 (0xFF) to u16 gives 65535 (0xFFFF). @@ -93,7 +93,7 @@ public: return BitWidth == Other.BitWidth && IsUnsigned == Other.IsUnsigned; } - /// \brief Provide an ordering for finding a common conversion type. + /// Provide an ordering for finding a common conversion type. /// /// Unsigned integers are considered to be better conversion types than /// signed integers of the same width. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h index 15b930bc3f1eb..02b335761e708 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h @@ -126,6 +126,36 @@ public: AnalysisDeclContext *getAnalysisDeclContext(const Decl *D) { return AnaCtxMgr.getContext(D); } + + static bool isInCodeFile(SourceLocation SL, const SourceManager &SM) { + if (SM.isInMainFile(SL)) + return true; + + // Support the "unified sources" compilation method (eg. WebKit) that + // involves producing non-header files that include other non-header files. + // We should be included directly from a UnifiedSource* file + // and we shouldn't be a header - which is a very safe defensive check. + SourceLocation IL = SM.getIncludeLoc(SM.getFileID(SL)); + if (!IL.isValid() || !SM.isInMainFile(IL)) + return false; + // Should rather be "file name starts with", but the current .getFilename + // includes the full path. + if (SM.getFilename(IL).contains("UnifiedSource")) { + // It might be great to reuse FrontendOptions::getInputKindForExtension() + // but for now it doesn't discriminate between code and header files. + return llvm::StringSwitch<bool>(SM.getFilename(SL).rsplit('.').second) + .Cases("c", "m", "mm", "C", "cc", "cp", true) + .Cases("cpp", "CPP", "c++", "cxx", "cppm", true) + .Default(false); + } + + return false; + } + + bool isInCodeFile(SourceLocation SL) { + const SourceManager &SM = getASTContext().getSourceManager(); + return isInCodeFile(SL, SM); + } }; } // enAnaCtxMgrspace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h index 4aa87443e4c22..0bbc6500d6ec3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h @@ -1,4 +1,4 @@ -//=== BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*---// +//==- BasicValueFactory.h - Basic values for Path Sens analysis --*- C++ -*-==// // // The LLVM Compiler Infrastructure // @@ -17,12 +17,26 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H #include "clang/AST/ASTContext.h" +#include "clang/AST/Expr.h" +#include "clang/AST/Type.h" #include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "llvm/ADT/APSInt.h" +#include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/ImmutableList.h" +#include "llvm/ADT/iterator_range.h" +#include "llvm/Support/Allocator.h" +#include <cassert> +#include <cstdint> +#include <utility> namespace clang { + +class CXXBaseSpecifier; +class DeclaratorDecl; + namespace ento { class CompoundValData : public llvm::FoldingSetNode { @@ -34,7 +48,8 @@ public: assert(NonLoc::isCompoundType(t)); } - typedef llvm::ImmutableList<SVal>::iterator iterator; + using iterator = llvm::ImmutableList<SVal>::iterator; + iterator begin() const { return L.begin(); } iterator end() const { return L.end(); } @@ -47,6 +62,7 @@ public: class LazyCompoundValData : public llvm::FoldingSetNode { StoreRef store; const TypedValueRegion *region; + public: LazyCompoundValData(const StoreRef &st, const TypedValueRegion *r) : store(st), region(r) { @@ -63,16 +79,17 @@ public: void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, store, region); } }; -class PointerToMemberData: public llvm::FoldingSetNode { +class PointerToMemberData : public llvm::FoldingSetNode { const DeclaratorDecl *D; llvm::ImmutableList<const CXXBaseSpecifier *> L; public: PointerToMemberData(const DeclaratorDecl *D, llvm::ImmutableList<const CXXBaseSpecifier *> L) - : D(D), L(L) {} + : D(D), L(L) {} + + using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator; - typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator; iterator begin() const { return L.begin(); } iterator end() const { return L.end(); } @@ -81,24 +98,25 @@ public: void Profile(llvm::FoldingSetNodeID& ID) { Profile(ID, D, L); } const DeclaratorDecl *getDeclaratorDecl() const {return D;} + llvm::ImmutableList<const CXXBaseSpecifier *> getCXXBaseList() const { return L; } }; class BasicValueFactory { - typedef llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt> > - APSIntSetTy; + using APSIntSetTy = + llvm::FoldingSet<llvm::FoldingSetNodeWrapper<llvm::APSInt>>; ASTContext &Ctx; llvm::BumpPtrAllocator& BPAlloc; - APSIntSetTy APSIntSet; - void * PersistentSVals; - void * PersistentSValPairs; + APSIntSetTy APSIntSet; + void *PersistentSVals = nullptr; + void *PersistentSValPairs = nullptr; llvm::ImmutableList<SVal>::Factory SValListFactory; - llvm::ImmutableList<const CXXBaseSpecifier*>::Factory CXXBaseListFactory; + llvm::ImmutableList<const CXXBaseSpecifier *>::Factory CXXBaseListFactory; llvm::FoldingSet<CompoundValData> CompoundValDataSet; llvm::FoldingSet<LazyCompoundValData> LazyCompoundValDataSet; llvm::FoldingSet<PointerToMemberData> PointerToMemberDataSet; @@ -109,9 +127,8 @@ class BasicValueFactory { public: BasicValueFactory(ASTContext &ctx, llvm::BumpPtrAllocator &Alloc) - : Ctx(ctx), BPAlloc(Alloc), PersistentSVals(nullptr), - PersistentSValPairs(nullptr), SValListFactory(Alloc), - CXXBaseListFactory(Alloc) {} + : Ctx(ctx), BPAlloc(Alloc), SValListFactory(Alloc), + CXXBaseListFactory(Alloc) {} ~BasicValueFactory(); @@ -147,57 +164,57 @@ public: return getValue(TargetType.convert(From)); } - const llvm::APSInt& getIntValue(uint64_t X, bool isUnsigned) { + const llvm::APSInt &getIntValue(uint64_t X, bool isUnsigned) { QualType T = isUnsigned ? Ctx.UnsignedIntTy : Ctx.IntTy; return getValue(X, T); } - inline const llvm::APSInt& getMaxValue(const llvm::APSInt &v) { + const llvm::APSInt &getMaxValue(const llvm::APSInt &v) { return getValue(APSIntType(v).getMaxValue()); } - inline const llvm::APSInt& getMinValue(const llvm::APSInt &v) { + const llvm::APSInt &getMinValue(const llvm::APSInt &v) { return getValue(APSIntType(v).getMinValue()); } - inline const llvm::APSInt& getMaxValue(QualType T) { + const llvm::APSInt &getMaxValue(QualType T) { return getValue(getAPSIntType(T).getMaxValue()); } - inline const llvm::APSInt& getMinValue(QualType T) { + const llvm::APSInt &getMinValue(QualType T) { return getValue(getAPSIntType(T).getMinValue()); } - inline const llvm::APSInt& Add1(const llvm::APSInt& V) { + const llvm::APSInt &Add1(const llvm::APSInt &V) { llvm::APSInt X = V; ++X; return getValue(X); } - inline const llvm::APSInt& Sub1(const llvm::APSInt& V) { + const llvm::APSInt &Sub1(const llvm::APSInt &V) { llvm::APSInt X = V; --X; return getValue(X); } - inline const llvm::APSInt& getZeroWithTypeSize(QualType T) { + const llvm::APSInt &getZeroWithTypeSize(QualType T) { assert(T->isScalarType()); return getValue(0, Ctx.getTypeSize(T), true); } - inline const llvm::APSInt& getZeroWithPtrWidth(bool isUnsigned = true) { + const llvm::APSInt &getZeroWithPtrWidth(bool isUnsigned = true) { return getValue(0, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); } - inline const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) { + const llvm::APSInt &getIntWithPtrWidth(uint64_t X, bool isUnsigned) { return getValue(X, Ctx.getTypeSize(Ctx.VoidPtrTy), isUnsigned); } - inline const llvm::APSInt& getTruthValue(bool b, QualType T) { - return getValue(b ? 1 : 0, Ctx.getTypeSize(T), false); + const llvm::APSInt &getTruthValue(bool b, QualType T) { + return getValue(b ? 1 : 0, Ctx.getIntWidth(T), true); } - inline const llvm::APSInt& getTruthValue(bool b) { + const llvm::APSInt &getTruthValue(bool b) { return getTruthValue(b, Ctx.getLogicalOperationType()); } @@ -229,7 +246,7 @@ public: return CXXBaseListFactory.add(CBS, L); } - const clang::ento::PointerToMemberData *accumCXXBase( + const PointerToMemberData *accumCXXBase( llvm::iterator_range<CastExpr::path_const_iterator> PathRange, const nonloc::PointerToMember &PTM); @@ -246,8 +263,8 @@ public: const SVal* getPersistentSVal(SVal X); }; -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_BASICVALUEFACTORY_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h index 1d779e6cb6ec0..b94dadff23427 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h @@ -25,7 +25,7 @@ class StackFrameContext; namespace ento { /// \class BlockCounter -/// \brief An abstract data type used to count the number of times a given +/// An abstract data type used to count the number of times a given /// block has been visited along a path analyzed by CoreEngine. class BlockCounter { void *Data; diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h index 9fec217aca725..9c667f912e9fd 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h @@ -1,4 +1,4 @@ -//===- CallEvent.h - Wrapper for all function and method calls ----*- C++ -*--// +//===- CallEvent.h - Wrapper for all function and method calls --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,19 +16,42 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H +#include "clang/AST/Decl.h" +#include "clang/AST/DeclBase.h" #include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExprObjC.h" -#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/AST/Stmt.h" +#include "clang/AST/Type.h" +#include "clang/Basic/IdentifierTable.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/PointerIntPair.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Allocator.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/ErrorHandling.h" +#include <cassert> +#include <limits> #include <utility> namespace clang { + +class LocationContext; class ProgramPoint; class ProgramPointTag; +class StackFrameContext; namespace ento { @@ -48,31 +71,31 @@ enum CallEventKind { }; class CallEvent; -class CallEventManager; /// This class represents a description of a function call using the number of /// arguments and the name of the function. class CallDescription { friend CallEvent; - mutable IdentifierInfo *II; - mutable bool IsLookupDone; + + mutable IdentifierInfo *II = nullptr; + mutable bool IsLookupDone = false; StringRef FuncName; unsigned RequiredArgs; public: - const static unsigned NoArgRequirement = ~0; - /// \brief Constructs a CallDescription object. + const static unsigned NoArgRequirement = std::numeric_limits<unsigned>::max(); + + /// Constructs a CallDescription object. /// /// @param FuncName The name of the function that will be matched. /// /// @param RequiredArgs The number of arguments that is expected to match a - /// call. Omit this parameter to match every occurance of call with a given + /// call. Omit this parameter to match every occurrence of call with a given /// name regardless the number of arguments. CallDescription(StringRef FuncName, unsigned RequiredArgs = NoArgRequirement) - : II(nullptr), IsLookupDone(false), FuncName(FuncName), - RequiredArgs(RequiredArgs) {} + : FuncName(FuncName), RequiredArgs(RequiredArgs) {} - /// \brief Get the name of the function that this object matches. + /// Get the name of the function that this object matches. StringRef getFunctionName() const { return FuncName; } }; @@ -95,7 +118,7 @@ public: }; /// \class RuntimeDefinition -/// \brief Defines the runtime definition of the called function. +/// Defines the runtime definition of the called function. /// /// Encapsulates the information we have about which Decl will be used /// when the call is executed on the given path. When dealing with dynamic @@ -104,21 +127,22 @@ public: class RuntimeDefinition { /// The Declaration of the function which could be called at runtime. /// NULL if not available. - const Decl *D; + const Decl *D = nullptr; /// The region representing an object (ObjC/C++) on which the method is /// called. With dynamic dispatch, the method definition depends on the /// runtime type of this object. NULL when the DynamicTypeInfo is /// precise. - const MemRegion *R; + const MemRegion *R = nullptr; public: - RuntimeDefinition(): D(nullptr), R(nullptr) {} - RuntimeDefinition(const Decl *InD): D(InD), R(nullptr) {} + RuntimeDefinition() = default; + RuntimeDefinition(const Decl *InD): D(InD) {} RuntimeDefinition(const Decl *InD, const MemRegion *InR): D(InD), R(InR) {} + const Decl *getDecl() { return D; } - /// \brief Check if the definition we have is precise. + /// Check if the definition we have is precise. /// If not, it is possible that the call dispatches to another definition at /// execution time. bool mayHaveOtherDefinitions() { return R != nullptr; } @@ -128,7 +152,7 @@ public: const MemRegion *getDispatchRegion() { return R; } }; -/// \brief Represents an abstract call to a function or method along a +/// Represents an abstract call to a function or method along a /// particular path. /// /// CallEvents are created through the factory methods of CallEventManager. @@ -139,15 +163,13 @@ public: /// Use the "Data" and "Location" fields instead. class CallEvent { public: - typedef CallEventKind Kind; + using Kind = CallEventKind; private: ProgramStateRef State; const LocationContext *LCtx; llvm::PointerUnion<const Expr *, const Decl *> Origin; - void operator=(const CallEvent &) = delete; - protected: // This is user data for subclasses. const void *Data; @@ -158,9 +180,10 @@ protected: SourceLocation Location; private: - mutable unsigned RefCount; - template <typename T> friend struct llvm::IntrusiveRefCntPtrInfo; + + mutable unsigned RefCount = 0; + void Retain() const { ++RefCount; } void Release() const; @@ -168,72 +191,72 @@ protected: friend class CallEventManager; CallEvent(const Expr *E, ProgramStateRef state, const LocationContext *lctx) - : State(std::move(state)), LCtx(lctx), Origin(E), RefCount(0) {} + : State(std::move(state)), LCtx(lctx), Origin(E) {} CallEvent(const Decl *D, ProgramStateRef state, const LocationContext *lctx) - : State(std::move(state)), LCtx(lctx), Origin(D), RefCount(0) {} + : State(std::move(state)), LCtx(lctx), Origin(D) {} // DO NOT MAKE PUBLIC CallEvent(const CallEvent &Original) - : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin), - Data(Original.Data), Location(Original.Location), RefCount(0) {} + : State(Original.State), LCtx(Original.LCtx), Origin(Original.Origin), + Data(Original.Data), Location(Original.Location) {} /// Copies this CallEvent, with vtable intact, into a new block of memory. virtual void cloneTo(void *Dest) const = 0; - /// \brief Get the value of arbitrary expressions at this point in the path. + /// Get the value of arbitrary expressions at this point in the path. SVal getSVal(const Stmt *S) const { return getState()->getSVal(S, getLocationContext()); } + using ValueList = SmallVectorImpl<SVal>; - typedef SmallVectorImpl<SVal> ValueList; - - /// \brief Used to specify non-argument regions that will be invalidated as a + /// Used to specify non-argument regions that will be invalidated as a /// result of this call. virtual void getExtraInvalidatedValues(ValueList &Values, RegionAndSymbolInvalidationTraits *ETraits) const {} public: - virtual ~CallEvent() {} + CallEvent &operator=(const CallEvent &) = delete; + virtual ~CallEvent() = default; - /// \brief Returns the kind of call this is. + /// Returns the kind of call this is. virtual Kind getKind() const = 0; - /// \brief Returns the declaration of the function or method that will be + /// Returns the declaration of the function or method that will be /// called. May be null. virtual const Decl *getDecl() const { return Origin.dyn_cast<const Decl *>(); } - /// \brief The state in which the call is being evaluated. + /// The state in which the call is being evaluated. const ProgramStateRef &getState() const { return State; } - /// \brief The context in which the call is being evaluated. + /// The context in which the call is being evaluated. const LocationContext *getLocationContext() const { return LCtx; } - /// \brief Returns the definition of the function or method that will be + /// Returns the definition of the function or method that will be /// called. virtual RuntimeDefinition getRuntimeDefinition() const = 0; - /// \brief Returns the expression whose value will be the result of this call. + /// Returns the expression whose value will be the result of this call. /// May be null. const Expr *getOriginExpr() const { return Origin.dyn_cast<const Expr *>(); } - /// \brief Returns the number of arguments (explicit and implicit). + /// Returns the number of arguments (explicit and implicit). /// /// Note that this may be greater than the number of parameters in the /// callee's declaration, and that it may include arguments not written in /// the source. virtual unsigned getNumArgs() const = 0; - /// \brief Returns true if the callee is known to be from a system header. + /// Returns true if the callee is known to be from a system header. bool isInSystemHeader() const { const Decl *D = getDecl(); if (!D) @@ -248,57 +271,57 @@ public: // Special case for implicitly-declared global operator new/delete. // These should be considered system functions. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) + if (const auto *FD = dyn_cast<FunctionDecl>(D)) return FD->isOverloadedOperator() && FD->isImplicit() && FD->isGlobal(); return false; } - /// \brief Returns true if the CallEvent is a call to a function that matches + /// Returns true if the CallEvent is a call to a function that matches /// the CallDescription. /// /// Note that this function is not intended to be used to match Obj-C method /// calls. bool isCalled(const CallDescription &CD) const; - /// \brief Returns a source range for the entire call, suitable for + /// Returns a source range for the entire call, suitable for /// outputting in diagnostics. virtual SourceRange getSourceRange() const { return getOriginExpr()->getSourceRange(); } - /// \brief Returns the value of a given argument at the time of the call. + /// Returns the value of a given argument at the time of the call. virtual SVal getArgSVal(unsigned Index) const; - /// \brief Returns the expression associated with a given argument. + /// Returns the expression associated with a given argument. /// May be null if this expression does not appear in the source. virtual const Expr *getArgExpr(unsigned Index) const { return nullptr; } - /// \brief Returns the source range for errors associated with this argument. + /// Returns the source range for errors associated with this argument. /// /// May be invalid if the argument is not written in the source. virtual SourceRange getArgSourceRange(unsigned Index) const; - /// \brief Returns the result type, adjusted for references. + /// Returns the result type, adjusted for references. QualType getResultType() const; - /// \brief Returns the return value of the call. + /// Returns the return value of the call. /// /// This should only be called if the CallEvent was created using a state in /// which the return value has already been bound to the origin expression. SVal getReturnValue() const; - /// \brief Returns true if the type of any of the non-null arguments satisfies + /// Returns true if the type of any of the non-null arguments satisfies /// the condition. bool hasNonNullArgumentsWithType(bool (*Condition)(QualType)) const; - /// \brief Returns true if any of the arguments appear to represent callbacks. + /// Returns true if any of the arguments appear to represent callbacks. bool hasNonZeroCallbackArg() const; - /// \brief Returns true if any of the arguments is void*. + /// Returns true if any of the arguments is void*. bool hasVoidPointerToNonConstArg() const; - /// \brief Returns true if any of the arguments are known to escape to long- + /// Returns true if any of the arguments are known to escape to long- /// term storage, even if this method will not modify them. // NOTE: The exact semantics of this are still being defined! // We don't really want a list of hardcoded exceptions in the long run, @@ -307,7 +330,7 @@ public: return hasNonZeroCallbackArg(); } - /// \brief Returns true if the callee is an externally-visible function in the + /// Returns true if the callee is an externally-visible function in the /// top-level namespace, such as \c malloc. /// /// You can use this call to determine that a particular function really is @@ -325,7 +348,7 @@ public: // precise callbacks. bool isGlobalCFunction(StringRef SpecificName = StringRef()) const; - /// \brief Returns the name of the callee, if its name is a simple identifier. + /// Returns the name of the callee, if its name is a simple identifier. /// /// Note that this will fail for Objective-C methods, blocks, and C++ /// overloaded operators. The former is named by a Selector rather than a @@ -333,25 +356,25 @@ public: // FIXME: Move this down to AnyFunctionCall once checkers have more // precise callbacks. const IdentifierInfo *getCalleeIdentifier() const { - const NamedDecl *ND = dyn_cast_or_null<NamedDecl>(getDecl()); + const auto *ND = dyn_cast_or_null<NamedDecl>(getDecl()); if (!ND) return nullptr; return ND->getIdentifier(); } - /// \brief Returns an appropriate ProgramPoint for this call. + /// Returns an appropriate ProgramPoint for this call. ProgramPoint getProgramPoint(bool IsPreVisit = false, const ProgramPointTag *Tag = nullptr) const; - /// \brief Returns a new state with all argument regions invalidated. + /// Returns a new state with all argument regions invalidated. /// /// This accepts an alternate state in case some processing has already /// occurred. ProgramStateRef invalidateRegions(unsigned BlockCount, ProgramStateRef Orig = nullptr) const; - typedef std::pair<Loc, SVal> FrameBindingTy; - typedef SmallVectorImpl<FrameBindingTy> BindingsTy; + using FrameBindingTy = std::pair<Loc, SVal>; + using BindingsTy = SmallVectorImpl<FrameBindingTy>; /// Populates the given SmallVector with the bindings in the callee's stack /// frame at the start of this call. @@ -367,16 +390,16 @@ public: return cloneWithState<CallEvent>(NewState); } - /// \brief Returns true if this is a statement is a function or method call + /// Returns true if this is a statement is a function or method call /// of some kind. static bool isCallStmt(const Stmt *S); - /// \brief Returns the result type of a function or method declaration. + /// Returns the result type of a function or method declaration. /// /// This will return a null QualType if the result type cannot be determined. static QualType getDeclaredResultType(const Decl *D); - /// \brief Returns true if the given decl is known to be variadic. + /// Returns true if the given decl is known to be variadic. /// /// \p D must not be null. static bool isVariadic(const Decl *D); @@ -393,10 +416,10 @@ public: /// Remember that the number of formal parameters may not match the number /// of arguments for all calls. However, the first parameter will always /// correspond with the argument value returned by \c getArgSVal(0). - virtual ArrayRef<ParmVarDecl*> parameters() const = 0; + virtual ArrayRef<ParmVarDecl *> parameters() const = 0; - typedef llvm::mapped_iterator<ArrayRef<ParmVarDecl*>::iterator, GetTypeFn> - param_type_iterator; + using param_type_iterator = + llvm::mapped_iterator<ArrayRef<ParmVarDecl *>::iterator, GetTypeFn>; /// Returns an iterator over the types of the call's formal parameters. /// @@ -416,18 +439,17 @@ public: void dump() const; }; - -/// \brief Represents a call to any sort of function that might have a +/// Represents a call to any sort of function that might have a /// FunctionDecl. class AnyFunctionCall : public CallEvent { protected: AnyFunctionCall(const Expr *E, ProgramStateRef St, const LocationContext *LCtx) - : CallEvent(E, St, LCtx) {} + : CallEvent(E, St, LCtx) {} AnyFunctionCall(const Decl *D, ProgramStateRef St, const LocationContext *LCtx) - : CallEvent(D, St, LCtx) {} - AnyFunctionCall(const AnyFunctionCall &Other) : CallEvent(Other) {} + : CallEvent(D, St, LCtx) {} + AnyFunctionCall(const AnyFunctionCall &Other) = default; public: // This function is overridden by subclasses, but they must return @@ -451,7 +473,7 @@ public: } }; -/// \brief Represents a C function or static C++ member function call. +/// Represents a C function or static C++ member function call. /// /// Example: \c fun() class SimpleFunctionCall : public AnyFunctionCall { @@ -460,9 +482,9 @@ class SimpleFunctionCall : public AnyFunctionCall { protected: SimpleFunctionCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(CE, St, LCtx) {} - SimpleFunctionCall(const SimpleFunctionCall &Other) - : AnyFunctionCall(Other) {} + : AnyFunctionCall(CE, St, LCtx) {} + SimpleFunctionCall(const SimpleFunctionCall &Other) = default; + void cloneTo(void *Dest) const override { new (Dest) SimpleFunctionCall(*this); } @@ -487,7 +509,7 @@ public: } }; -/// \brief Represents a call to a block. +/// Represents a call to a block. /// /// Example: <tt>^{ /* ... */ }()</tt> class BlockCall : public CallEvent { @@ -496,9 +518,9 @@ class BlockCall : public CallEvent { protected: BlockCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : CallEvent(CE, St, LCtx) {} + : CallEvent(CE, St, LCtx) {} + BlockCall(const BlockCall &Other) = default; - BlockCall(const BlockCall &Other) : CallEvent(Other) {} void cloneTo(void *Dest) const override { new (Dest) BlockCall(*this); } void getExtraInvalidatedValues(ValueList &Values, @@ -515,7 +537,7 @@ public: return getOriginExpr()->getArg(Index); } - /// \brief Returns the region associated with this instance of the block. + /// Returns the region associated with this instance of the block. /// /// This may be NULL if the block's origin is unknown. const BlockDataRegion *getBlockRegion() const; @@ -535,7 +557,7 @@ public: return BD->isConversionFromLambda(); } - /// \brief For a block converted from a C++ lambda, returns the block + /// For a block converted from a C++ lambda, returns the block /// VarRegion for the variable holding the captured C++ lambda record. const VarRegion *getRegionStoringCapturedLambda() const { assert(isConversionFromLambda()); @@ -594,28 +616,26 @@ public: } }; -/// \brief Represents a non-static C++ member function call, no matter how +/// Represents a non-static C++ member function call, no matter how /// it is written. class CXXInstanceCall : public AnyFunctionCall { protected: - void getExtraInvalidatedValues(ValueList &Values, - RegionAndSymbolInvalidationTraits *ETraits) const override; - CXXInstanceCall(const CallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(CE, St, LCtx) {} + : AnyFunctionCall(CE, St, LCtx) {} CXXInstanceCall(const FunctionDecl *D, ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(D, St, LCtx) {} - + : AnyFunctionCall(D, St, LCtx) {} + CXXInstanceCall(const CXXInstanceCall &Other) = default; - CXXInstanceCall(const CXXInstanceCall &Other) : AnyFunctionCall(Other) {} + void getExtraInvalidatedValues(ValueList &Values, + RegionAndSymbolInvalidationTraits *ETraits) const override; public: - /// \brief Returns the expression representing the implicit 'this' object. + /// Returns the expression representing the implicit 'this' object. virtual const Expr *getCXXThisExpr() const { return nullptr; } - /// \brief Returns the value of the implicit 'this' object. + /// Returns the value of the implicit 'this' object. virtual SVal getCXXThisVal() const; const FunctionDecl *getDecl() const override; @@ -631,7 +651,7 @@ public: } }; -/// \brief Represents a non-static C++ member function call. +/// Represents a non-static C++ member function call. /// /// Example: \c obj.fun() class CXXMemberCall : public CXXInstanceCall { @@ -640,9 +660,9 @@ class CXXMemberCall : public CXXInstanceCall { protected: CXXMemberCall(const CXXMemberCallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : CXXInstanceCall(CE, St, LCtx) {} + : CXXInstanceCall(CE, St, LCtx) {} + CXXMemberCall(const CXXMemberCall &Other) = default; - CXXMemberCall(const CXXMemberCall &Other) : CXXInstanceCall(Other) {} void cloneTo(void *Dest) const override { new (Dest) CXXMemberCall(*this); } public: @@ -671,7 +691,7 @@ public: } }; -/// \brief Represents a C++ overloaded operator call where the operator is +/// Represents a C++ overloaded operator call where the operator is /// implemented as a non-static member function. /// /// Example: <tt>iter + 1</tt> @@ -681,10 +701,9 @@ class CXXMemberOperatorCall : public CXXInstanceCall { protected: CXXMemberOperatorCall(const CXXOperatorCallExpr *CE, ProgramStateRef St, const LocationContext *LCtx) - : CXXInstanceCall(CE, St, LCtx) {} + : CXXInstanceCall(CE, St, LCtx) {} + CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) = default; - CXXMemberOperatorCall(const CXXMemberOperatorCall &Other) - : CXXInstanceCall(Other) {} void cloneTo(void *Dest) const override { new (Dest) CXXMemberOperatorCall(*this); } @@ -697,6 +716,7 @@ public: unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs() - 1; } + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index + 1); } @@ -710,7 +730,7 @@ public: } }; -/// \brief Represents an implicit call to a C++ destructor. +/// Represents an implicit call to a C++ destructor. /// /// This can occur at the end of a scope (for automatic objects), at the end /// of a full-expression (for temporaries), or as part of a delete. @@ -718,7 +738,7 @@ class CXXDestructorCall : public CXXInstanceCall { friend class CallEventManager; protected: - typedef llvm::PointerIntPair<const MemRegion *, 1, bool> DtorDataTy; + using DtorDataTy = llvm::PointerIntPair<const MemRegion *, 1, bool>; /// Creates an implicit destructor. /// @@ -730,12 +750,13 @@ protected: CXXDestructorCall(const CXXDestructorDecl *DD, const Stmt *Trigger, const MemRegion *Target, bool IsBaseDestructor, ProgramStateRef St, const LocationContext *LCtx) - : CXXInstanceCall(DD, St, LCtx) { + : CXXInstanceCall(DD, St, LCtx) { Data = DtorDataTy(Target, IsBaseDestructor).getOpaqueValue(); Location = Trigger->getLocEnd(); } - CXXDestructorCall(const CXXDestructorCall &Other) : CXXInstanceCall(Other) {} + CXXDestructorCall(const CXXDestructorCall &Other) = default; + void cloneTo(void *Dest) const override {new (Dest) CXXDestructorCall(*this);} public: @@ -744,7 +765,7 @@ public: RuntimeDefinition getRuntimeDefinition() const override; - /// \brief Returns the value of the implicit 'this' object. + /// Returns the value of the implicit 'this' object. SVal getCXXThisVal() const override; /// Returns true if this is a call to a base class destructor. @@ -759,7 +780,7 @@ public: } }; -/// \brief Represents a call to a C++ constructor. +/// Represents a call to a C++ constructor. /// /// Example: \c T(1) class CXXConstructorCall : public AnyFunctionCall { @@ -775,11 +796,12 @@ protected: /// \param LCtx The location context at this point in the program. CXXConstructorCall(const CXXConstructExpr *CE, const MemRegion *Target, ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(CE, St, LCtx) { + : AnyFunctionCall(CE, St, LCtx) { Data = Target; } - CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){} + CXXConstructorCall(const CXXConstructorCall &Other) = default; + void cloneTo(void *Dest) const override { new (Dest) CXXConstructorCall(*this); } void getExtraInvalidatedValues(ValueList &Values, @@ -800,7 +822,7 @@ public: return getOriginExpr()->getArg(Index); } - /// \brief Returns the value of the implicit 'this' object. + /// Returns the value of the implicit 'this' object. SVal getCXXThisVal() const; void getInitialStackFrameContents(const StackFrameContext *CalleeCtx, @@ -813,7 +835,7 @@ public: } }; -/// \brief Represents the memory allocation call in a C++ new-expression. +/// Represents the memory allocation call in a C++ new-expression. /// /// This is a call to "operator new". class CXXAllocatorCall : public AnyFunctionCall { @@ -822,9 +844,9 @@ class CXXAllocatorCall : public AnyFunctionCall { protected: CXXAllocatorCall(const CXXNewExpr *E, ProgramStateRef St, const LocationContext *LCtx) - : AnyFunctionCall(E, St, LCtx) {} + : AnyFunctionCall(E, St, LCtx) {} + CXXAllocatorCall(const CXXAllocatorCall &Other) = default; - CXXAllocatorCall(const CXXAllocatorCall &Other) : AnyFunctionCall(Other) {} void cloneTo(void *Dest) const override { new (Dest) CXXAllocatorCall(*this); } public: @@ -854,7 +876,7 @@ public: } }; -/// \brief Represents the ways an Objective-C message send can occur. +/// Represents the ways an Objective-C message send can occur. // // Note to maintainers: OCM_Message should always be last, since it does not // need to fit in the Data field's low bits. @@ -864,7 +886,7 @@ enum ObjCMessageKind { OCM_Message }; -/// \brief Represents any expression that calls an Objective-C method. +/// Represents any expression that calls an Objective-C method. /// /// This includes all of the kinds listed in ObjCMessageKind. class ObjCMethodCall : public CallEvent { @@ -875,11 +897,12 @@ class ObjCMethodCall : public CallEvent { protected: ObjCMethodCall(const ObjCMessageExpr *Msg, ProgramStateRef St, const LocationContext *LCtx) - : CallEvent(Msg, St, LCtx) { + : CallEvent(Msg, St, LCtx) { Data = nullptr; } - ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {} + ObjCMethodCall(const ObjCMethodCall &Other) = default; + void cloneTo(void *Dest) const override { new (Dest) ObjCMethodCall(*this); } void getExtraInvalidatedValues(ValueList &Values, @@ -893,12 +916,15 @@ public: virtual const ObjCMessageExpr *getOriginExpr() const { return cast<ObjCMessageExpr>(CallEvent::getOriginExpr()); } + const ObjCMethodDecl *getDecl() const override { return getOriginExpr()->getMethodDecl(); } + unsigned getNumArgs() const override { return getOriginExpr()->getNumArgs(); } + const Expr *getArgExpr(unsigned Index) const override { return getOriginExpr()->getArg(Index); } @@ -906,22 +932,24 @@ public: bool isInstanceMessage() const { return getOriginExpr()->isInstanceMessage(); } + ObjCMethodFamily getMethodFamily() const { return getOriginExpr()->getMethodFamily(); } + Selector getSelector() const { return getOriginExpr()->getSelector(); } SourceRange getSourceRange() const override; - /// \brief Returns the value of the receiver at the time of this call. + /// Returns the value of the receiver at the time of this call. SVal getReceiverSVal() const; - /// \brief Return the value of 'self' if available. + /// Return the value of 'self' if available. SVal getSelfSVal() const; - /// \brief Get the interface for the receiver. + /// Get the interface for the receiver. /// /// This works whether this is an instance message or a class message. /// However, it currently just uses the static type of the receiver. @@ -929,7 +957,7 @@ public: return getOriginExpr()->getReceiverInterface(); } - /// \brief Checks if the receiver refers to 'self' or 'super'. + /// Checks if the receiver refers to 'self' or 'super'. bool isReceiverSelfOrSuper() const; /// Returns how the message was written in the source (property access, @@ -971,8 +999,7 @@ public: } }; - -/// \brief Manages the lifetime of CallEvent objects. +/// Manages the lifetime of CallEvent objects. /// /// CallEventManager provides a way to create arbitrary CallEvents "on the /// stack" as if they were value objects by keeping a cache of CallEvent-sized @@ -984,7 +1011,8 @@ class CallEventManager { llvm::BumpPtrAllocator &Alloc; SmallVector<void *, 8> Cache; - typedef SimpleFunctionCall CallEventTemplateTy; + + using CallEventTemplateTy = SimpleFunctionCall; void reclaim(const void *Memory) { Cache.push_back(const_cast<void *>(Memory)); @@ -1032,11 +1060,9 @@ class CallEventManager { public: CallEventManager(llvm::BumpPtrAllocator &alloc) : Alloc(alloc) {} - CallEventRef<> getCaller(const StackFrameContext *CalleeCtx, ProgramStateRef State); - CallEventRef<> getSimpleCall(const CallExpr *E, ProgramStateRef State, const LocationContext *LCtx); @@ -1067,7 +1093,6 @@ public: } }; - template <typename T> CallEventRef<T> CallEvent::cloneWithState(ProgramStateRef NewState) const { assert(isa<T>(*this) && "Cloning to unrelated type"); @@ -1099,19 +1124,22 @@ inline void CallEvent::Release() const { this->~CallEvent(); } -} // end namespace ento -} // end namespace clang +} // namespace ento + +} // namespace clang namespace llvm { - // Support isa<>, cast<>, and dyn_cast<> for CallEventRef. - template<class T> struct simplify_type< clang::ento::CallEventRef<T> > { - typedef const T *SimpleType; - static SimpleType - getSimplifiedValue(clang::ento::CallEventRef<T> Val) { - return Val.get(); - } - }; -} +// Support isa<>, cast<>, and dyn_cast<> for CallEventRef. +template<class T> struct simplify_type< clang::ento::CallEventRef<T>> { + using SimpleType = const T *; + + static SimpleType + getSimplifiedValue(clang::ento::CallEventRef<T> Val) { + return Val.get(); + } +}; + +} // namespace llvm -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CALLEVENT_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h index 78d38a3d598dc..f3a0ca7b66081 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h @@ -111,17 +111,17 @@ public: return Eng.getStoreManager(); } - /// \brief Returns the previous node in the exploded graph, which includes + /// Returns the previous node in the exploded graph, which includes /// the state of the program before the checker ran. Note, checkers should /// not retain the node in their state since the nodes might get invalidated. ExplodedNode *getPredecessor() { return Pred; } const ProgramStateRef &getState() const { return Pred->getState(); } - /// \brief Check if the checker changed the state of the execution; ex: added + /// Check if the checker changed the state of the execution; ex: added /// a new transition or a bug report. bool isDifferent() { return Changed; } - /// \brief Returns the number of times the current block has been visited + /// Returns the number of times the current block has been visited /// along the analyzed path. unsigned blockCount() const { return NB.getContext().blockCount(); @@ -174,12 +174,12 @@ public: return Pred->getLocationContext()->getAnalysisDeclContext(); } - /// \brief Get the blockID. + /// Get the blockID. unsigned getBlockID() const { return NB.getContext().getBlock()->getBlockID(); } - /// \brief If the given node corresponds to a PostStore program point, + /// If the given node corresponds to a PostStore program point, /// retrieve the location region as it was uttered in the code. /// /// This utility can be useful for generating extensive diagnostics, for @@ -191,19 +191,19 @@ public: return nullptr; } - /// \brief Get the value of arbitrary expressions at this point in the path. + /// Get the value of arbitrary expressions at this point in the path. SVal getSVal(const Stmt *S) const { - return getState()->getSVal(S, getLocationContext()); + return Pred->getSVal(S); } - /// \brief Returns true if the value of \p E is greater than or equal to \p + /// Returns true if the value of \p E is greater than or equal to \p /// Val under unsigned comparison bool isGreaterOrEqual(const Expr *E, unsigned long long Val); /// Returns true if the value of \p E is negative. bool isNegative(const Expr *E); - /// \brief Generates a new transition in the program state graph + /// Generates a new transition in the program state graph /// (ExplodedGraph). Uses the default CheckerContext predecessor node. /// /// @param State The state of the generated node. If not specified, the state @@ -217,7 +217,7 @@ public: return addTransitionImpl(State ? State : getState(), false, nullptr, Tag); } - /// \brief Generates a new transition with the given predecessor. + /// Generates a new transition with the given predecessor. /// Allows checkers to generate a chain of nodes. /// /// @param State The state of the generated node. @@ -230,7 +230,7 @@ public: return addTransitionImpl(State, false, Pred, Tag); } - /// \brief Generate a sink node. Generating a sink stops exploration of the + /// Generate a sink node. Generating a sink stops exploration of the /// given path. To create a sink node for the purpose of reporting an error, /// checkers should use generateErrorNode() instead. ExplodedNode *generateSink(ProgramStateRef State, ExplodedNode *Pred, @@ -238,7 +238,7 @@ public: return addTransitionImpl(State ? State : getState(), true, Pred, Tag); } - /// \brief Generate a transition to a node that will be used to report + /// Generate a transition to a node that will be used to report /// an error. This node will be a sink. That is, it will stop exploration of /// the given path. /// @@ -251,7 +251,7 @@ public: (Tag ? Tag : Location.getTag())); } - /// \brief Generate a transition to a node that will be used to report + /// Generate a transition to a node that will be used to report /// an error. This node will not be a sink. That is, exploration will /// continue along this path. /// @@ -264,23 +264,23 @@ public: return addTransition(State, (Tag ? Tag : Location.getTag())); } - /// \brief Emit the diagnostics report. + /// Emit the diagnostics report. void emitReport(std::unique_ptr<BugReport> R) { Changed = true; Eng.getBugReporter().emitReport(std::move(R)); } - /// \brief Returns the word that should be used to refer to the declaration + /// Returns the word that should be used to refer to the declaration /// in the report. StringRef getDeclDescription(const Decl *D); - /// \brief Get the declaration of the called function (path-sensitive). + /// Get the declaration of the called function (path-sensitive). const FunctionDecl *getCalleeDecl(const CallExpr *CE) const; - /// \brief Get the name of the called function (path-sensitive). + /// Get the name of the called function (path-sensitive). StringRef getCalleeName(const FunctionDecl *FunDecl) const; - /// \brief Get the identifier of the called function (path-sensitive). + /// Get the identifier of the called function (path-sensitive). const IdentifierInfo *getCalleeIdentifier(const CallExpr *CE) const { const FunctionDecl *FunDecl = getCalleeDecl(CE); if (FunDecl) @@ -289,13 +289,13 @@ public: return nullptr; } - /// \brief Get the name of the called function (path-sensitive). + /// Get the name of the called function (path-sensitive). StringRef getCalleeName(const CallExpr *CE) const { const FunctionDecl *FunDecl = getCalleeDecl(CE); return getCalleeName(FunDecl); } - /// \brief Returns true if the callee is an externally-visible function in the + /// Returns true if the callee is an externally-visible function in the /// top-level namespace, such as \c malloc. /// /// If a name is provided, the function must additionally match the given @@ -308,7 +308,7 @@ public: static bool isCLibraryFunction(const FunctionDecl *FD, StringRef Name = StringRef()); - /// \brief Depending on wither the location corresponds to a macro, return + /// Depending on wither the location corresponds to a macro, return /// either the macro name or the token spelling. /// /// This could be useful when checkers' logic depends on whether a function diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h index 8dda6367c2e00..7f34a7a5b19dd 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CheckerHelpers.h @@ -21,6 +21,8 @@ namespace clang { class Expr; class VarDecl; +class QualType; +class AttributedType; namespace ento { @@ -42,6 +44,25 @@ template <class T> bool containsStmt(const Stmt *S) { std::pair<const clang::VarDecl *, const clang::Expr *> parseAssignment(const Stmt *S); +// Do not reorder! The getMostNullable method relies on the order. +// Optimization: Most pointers expected to be unspecified. When a symbol has an +// unspecified or nonnull type non of the rules would indicate any problem for +// that symbol. For this reason only nullable and contradicted nullability are +// stored for a symbol. When a symbol is already contradicted, it can not be +// casted back to nullable. +enum class Nullability : char { + Contradicted, // Tracked nullability is contradicted by an explicit cast. Do + // not report any nullability related issue for this symbol. + // This nullability is propagated aggressively to avoid false + // positive results. See the comment on getMostNullable method. + Nullable, + Unspecified, + Nonnull +}; + +/// Get nullability annotation for a given type. +Nullability getNullabilityAnnotation(QualType Type); + } // end GR namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h index c01600d5c969e..d4f8fbaa43df3 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h @@ -1,4 +1,4 @@ -//== ConstraintManager.h - Constraints on symbolic values.-------*- C++ -*--==// +//===- ConstraintManager.h - Constraints on symbolic values. ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,28 +14,44 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H +#include "clang/Basic/LLVM.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "llvm/ADT/Optional.h" #include "llvm/Support/SaveAndRestore.h" +#include <memory> +#include <utility> namespace llvm { + class APSInt; -} + +} // namespace llvm namespace clang { namespace ento { +class ProgramStateManager; class SubEngine; +class SymbolReaper; class ConditionTruthVal { Optional<bool> Val; + public: /// Construct a ConditionTruthVal indicating the constraint is constrained /// to either true or false, depending on the boolean value provided. ConditionTruthVal(bool constraint) : Val(constraint) {} /// Construct a ConstraintVal indicating the constraint is underconstrained. - ConditionTruthVal() {} + ConditionTruthVal() = default; + + /// \return Stored value, assuming that the value is known. + /// Crashes otherwise. + bool getValue() const { + return *Val; + } /// Return true if the constraint is perfectly constrained to 'true'. bool isConstrainedTrue() const { @@ -61,14 +77,14 @@ public: class ConstraintManager { public: - ConstraintManager() : NotifyAssumeClients(true) {} - + ConstraintManager() = default; virtual ~ConstraintManager(); + virtual ProgramStateRef assume(ProgramStateRef state, DefinedSVal Cond, bool Assumption) = 0; - typedef std::pair<ProgramStateRef, ProgramStateRef> ProgramStatePair; + using ProgramStatePair = std::pair<ProgramStateRef, ProgramStateRef>; /// Returns a pair of states (StTrue, StFalse) where the given condition is /// assumed to be true or false, respectively. @@ -129,7 +145,7 @@ public: return ProgramStatePair(StInRange, StOutOfRange); } - /// \brief If a symbol is perfectly constrained to a constant, attempt + /// If a symbol is perfectly constrained to a constant, attempt /// to return the concrete value. /// /// Note that a ConstraintManager is not obligated to return a concretized @@ -166,7 +182,7 @@ protected: /// /// Note that this flag allows the ConstraintManager to be re-entrant, /// but not thread-safe. - bool NotifyAssumeClients; + bool NotifyAssumeClients = true; /// canReasonAbout - Not all ConstraintManagers can accurately reason about /// all SVal values. This method returns true if the ConstraintManager can @@ -187,8 +203,7 @@ CreateRangeConstraintManager(ProgramStateManager &statemgr, std::unique_ptr<ConstraintManager> CreateZ3ConstraintManager(ProgramStateManager &statemgr, SubEngine *subengine); -} // end GR namespace +} // namespace ento +} // namespace clang -} // end clang namespace - -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_CONSTRAINTMANAGER_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h index 7472a7147fca6..5755818cd9716 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h @@ -1,4 +1,4 @@ -//==- CoreEngine.h - Path-Sensitive Dataflow Engine ----------------*- C++ -*-// +//===- CoreEngine.h - Path-Sensitive Dataflow Engine ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,21 +15,33 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H -#include "clang/AST/Expr.h" +#include "clang/AST/Stmt.h" #include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BlockCounter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/Casting.h" +#include <cassert> #include <memory> +#include <utility> +#include <vector> namespace clang { -class ProgramPointTag; - +class AnalyzerOptions; +class CXXBindTemporaryExpr; +class Expr; +class LabelDecl; + namespace ento { -class NodeBuilder; +class FunctionSummariesTy; +class SubEngine; //===----------------------------------------------------------------------===// /// CoreEngine - Implements the core logic of the graph-reachability @@ -41,23 +53,23 @@ class NodeBuilder; /// at the statement and block-level. The analyses themselves must implement /// any transfer function logic and the sub-expression level (if any). class CoreEngine { - friend struct NodeBuilderContext; - friend class NodeBuilder; - friend class ExprEngine; friend class CommonNodeBuilder; + friend class EndOfFunctionNodeBuilder; + friend class ExprEngine; friend class IndirectGotoNodeBuilder; + friend class NodeBuilder; + friend struct NodeBuilderContext; friend class SwitchNodeBuilder; - friend class EndOfFunctionNodeBuilder; + public: - typedef std::vector<std::pair<BlockEdge, const ExplodedNode*> > - BlocksExhausted; + using BlocksExhausted = + std::vector<std::pair<BlockEdge, const ExplodedNode *>>; - typedef std::vector<std::pair<const CFGBlock*, const ExplodedNode*> > - BlocksAborted; + using BlocksAborted = + std::vector<std::pair<const CFGBlock *, const ExplodedNode *>>; private: - - SubEngine& SubEng; + SubEngine &SubEng; /// G - The simulation graph. Each node is a (location,state) pair. mutable ExplodedGraph G; @@ -106,17 +118,17 @@ private: ExplodedNode *Pred); private: - CoreEngine(const CoreEngine &) = delete; - void operator=(const CoreEngine &) = delete; - ExplodedNode *generateCallExitBeginNode(ExplodedNode *N, const ReturnStmt *RS); public: /// Construct a CoreEngine object to analyze the provided CFG. - CoreEngine(SubEngine &subengine, FunctionSummariesTy *FS) - : SubEng(subengine), WList(WorkList::makeDFS()), - BCounterFactory(G.getAllocator()), FunctionSummaries(FS) {} + CoreEngine(SubEngine &subengine, + FunctionSummariesTy *FS, + AnalyzerOptions &Opts); + + CoreEngine(const CoreEngine &) = delete; + CoreEngine &operator=(const CoreEngine &) = delete; /// getGraph - Returns the exploded graph. ExplodedGraph &getGraph() { return G; } @@ -125,6 +137,7 @@ public: /// steps. Returns true if there is still simulation state on the worklist. bool ExecuteWorkList(const LocationContext *L, unsigned Steps, ProgramStateRef InitState); + /// Returns true if there is still simulation state on the worklist. bool ExecuteWorkListWithInitialState(const LocationContext *L, unsigned Steps, @@ -154,28 +167,31 @@ public: BlocksExhausted::const_iterator blocks_exhausted_begin() const { return blocksExhausted.begin(); } + BlocksExhausted::const_iterator blocks_exhausted_end() const { return blocksExhausted.end(); } + BlocksAborted::const_iterator blocks_aborted_begin() const { return blocksAborted.begin(); } + BlocksAborted::const_iterator blocks_aborted_end() const { return blocksAborted.end(); } - /// \brief Enqueue the given set of nodes onto the work list. + /// Enqueue the given set of nodes onto the work list. void enqueue(ExplodedNodeSet &Set); - /// \brief Enqueue nodes that were created as a result of processing + /// Enqueue nodes that were created as a result of processing /// a statement onto the work list. void enqueue(ExplodedNodeSet &Set, const CFGBlock *Block, unsigned Idx); - /// \brief enqueue the nodes corresponding to the end of function onto the + /// enqueue the nodes corresponding to the end of function onto the /// end of path / work list. void enqueueEndOfFunction(ExplodedNodeSet &Set, const ReturnStmt *RS); - /// \brief Enqueue a single node created as a result of statement processing. + /// Enqueue a single node created as a result of statement processing. void enqueueStmtNode(ExplodedNode *N, const CFGBlock *Block, unsigned Idx); }; @@ -184,23 +200,24 @@ struct NodeBuilderContext { const CoreEngine &Eng; const CFGBlock *Block; const LocationContext *LC; + NodeBuilderContext(const CoreEngine &E, const CFGBlock *B, ExplodedNode *N) - : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); } + : Eng(E), Block(B), LC(N->getLocationContext()) { assert(B); } - /// \brief Return the CFGBlock associated with this builder. + /// Return the CFGBlock associated with this builder. const CFGBlock *getBlock() const { return Block; } - /// \brief Returns the number of times the current basic block has been + /// Returns the number of times the current basic block has been /// visited on the exploded graph path. unsigned blockCount() const { return Eng.WList->getBlockCounter().getNumVisited( - LC->getCurrentStackFrame(), + LC->getStackFrame(), Block->getBlockID()); } }; /// \class NodeBuilder -/// \brief This is the simplest builder which generates nodes in the +/// This is the simplest builder which generates nodes in the /// ExplodedGraph. /// /// The main benefit of the builder is that it automatically tracks the @@ -210,29 +227,29 @@ struct NodeBuilderContext { /// constructed nodes) but did not have any outgoing transitions added. class NodeBuilder { virtual void anchor(); + protected: const NodeBuilderContext &C; /// Specifies if the builder results have been finalized. For example, if it /// is set to false, autotransitions are yet to be generated. bool Finalized; - bool HasGeneratedNodes; - /// \brief The frontier set - a set of nodes which need to be propagated after + + bool HasGeneratedNodes = false; + + /// The frontier set - a set of nodes which need to be propagated after /// the builder dies. ExplodedNodeSet &Frontier; - /// Checkes if the results are ready. + /// Checks if the results are ready. virtual bool checkResults() { - if (!Finalized) - return false; - return true; + return Finalized; } bool hasNoSinksInFrontier() { - for (iterator I = Frontier.begin(), E = Frontier.end(); I != E; ++I) { - if ((*I)->isSink()) + for (const auto I : Frontier) + if (I->isSink()) return false; - } return true; } @@ -247,27 +264,27 @@ protected: public: NodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx, bool F = true) - : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) { + : C(Ctx), Finalized(F), Frontier(DstSet) { Frontier.Add(SrcNode); } NodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx, bool F = true) - : C(Ctx), Finalized(F), HasGeneratedNodes(false), Frontier(DstSet) { + : C(Ctx), Finalized(F), Frontier(DstSet) { Frontier.insert(SrcSet); assert(hasNoSinksInFrontier()); } - virtual ~NodeBuilder() {} + virtual ~NodeBuilder() = default; - /// \brief Generates a node in the ExplodedGraph. + /// Generates a node in the ExplodedGraph. ExplodedNode *generateNode(const ProgramPoint &PP, ProgramStateRef State, ExplodedNode *Pred) { return generateNodeImpl(PP, State, Pred, false); } - /// \brief Generates a sink in the ExplodedGraph. + /// Generates a sink in the ExplodedGraph. /// /// When a node is marked as sink, the exploration from the node is stopped - /// the node becomes the last node on the path and certain kinds of bugs are @@ -284,14 +301,16 @@ public: return Frontier; } - typedef ExplodedNodeSet::iterator iterator; - /// \brief Iterators through the results frontier. - inline iterator begin() { + using iterator = ExplodedNodeSet::iterator; + + /// Iterators through the results frontier. + iterator begin() { finalizeResults(); assert(checkResults()); return Frontier.begin(); } - inline iterator end() { + + iterator end() { finalizeResults(); return Frontier.end(); } @@ -300,18 +319,20 @@ public: bool hasGeneratedNodes() { return HasGeneratedNodes; } void takeNodes(const ExplodedNodeSet &S) { - for (ExplodedNodeSet::iterator I = S.begin(), E = S.end(); I != E; ++I ) - Frontier.erase(*I); + for (const auto I : S) + Frontier.erase(I); } + void takeNodes(ExplodedNode *N) { Frontier.erase(N); } void addNodes(const ExplodedNodeSet &S) { Frontier.insert(S); } void addNodes(ExplodedNode *N) { Frontier.Add(N); } }; /// \class NodeBuilderWithSinks -/// \brief This node builder keeps track of the generated sink nodes. +/// This node builder keeps track of the generated sink nodes. class NodeBuilderWithSinks: public NodeBuilder { void anchor() override; + protected: SmallVector<ExplodedNode*, 2> sinksGenerated; ProgramPoint &Location; @@ -319,7 +340,7 @@ protected: public: NodeBuilderWithSinks(ExplodedNode *Pred, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx, ProgramPoint &L) - : NodeBuilder(Pred, DstSet, Ctx), Location(L) {} + : NodeBuilder(Pred, DstSet, Ctx), Location(L) {} ExplodedNode *generateNode(ProgramStateRef State, ExplodedNode *Pred, @@ -343,20 +364,20 @@ public: }; /// \class StmtNodeBuilder -/// \brief This builder class is useful for generating nodes that resulted from +/// This builder class is useful for generating nodes that resulted from /// visiting a statement. The main difference from its parent NodeBuilder is /// that it creates a statement specific ProgramPoint. class StmtNodeBuilder: public NodeBuilder { NodeBuilder *EnclosingBldr; -public: - /// \brief Constructs a StmtNodeBuilder. If the builder is going to process +public: + /// Constructs a StmtNodeBuilder. If the builder is going to process /// nodes currently owned by another builder(with larger scope), use /// Enclosing builder to transfer ownership. StmtNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = nullptr) - : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) { + : NodeBuilder(SrcNode, DstSet, Ctx), EnclosingBldr(Enclosing) { if (EnclosingBldr) EnclosingBldr->takeNodes(SrcNode); } @@ -364,11 +385,10 @@ public: StmtNodeBuilder(ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, const NodeBuilderContext &Ctx, NodeBuilder *Enclosing = nullptr) - : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) { + : NodeBuilder(SrcSet, DstSet, Ctx), EnclosingBldr(Enclosing) { if (EnclosingBldr) - for (ExplodedNodeSet::iterator I = SrcSet.begin(), - E = SrcSet.end(); I != E; ++I ) - EnclosingBldr->takeNodes(*I); + for (const auto I : SrcSet) + EnclosingBldr->takeNodes(I); } ~StmtNodeBuilder() override; @@ -397,22 +417,23 @@ public: } }; -/// \brief BranchNodeBuilder is responsible for constructing the nodes +/// BranchNodeBuilder is responsible for constructing the nodes /// corresponding to the two branches of the if statement - true and false. class BranchNodeBuilder: public NodeBuilder { - void anchor() override; const CFGBlock *DstT; const CFGBlock *DstF; bool InFeasibleTrue; bool InFeasibleFalse; + void anchor() override; + public: BranchNodeBuilder(ExplodedNode *SrcNode, ExplodedNodeSet &DstSet, const NodeBuilderContext &C, const CFGBlock *dstT, const CFGBlock *dstF) - : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF), - InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { + : NodeBuilder(SrcNode, DstSet, C), DstT(dstT), DstF(dstF), + InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { // The branch node builder does not generate autotransitions. // If there are no successors it means that both branches are infeasible. takeNodes(SrcNode); @@ -421,8 +442,8 @@ public: BranchNodeBuilder(const ExplodedNodeSet &SrcSet, ExplodedNodeSet &DstSet, const NodeBuilderContext &C, const CFGBlock *dstT, const CFGBlock *dstF) - : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF), - InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { + : NodeBuilder(SrcSet, DstSet, C), DstT(dstT), DstF(dstF), + InFeasibleTrue(!DstT), InFeasibleFalse(!DstF) { takeNodes(SrcSet); } @@ -455,15 +476,16 @@ class IndirectGotoNodeBuilder { public: IndirectGotoNodeBuilder(ExplodedNode *pred, const CFGBlock *src, const Expr *e, const CFGBlock *dispatch, CoreEngine* eng) - : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} + : Eng(*eng), Src(src), DispatchBlock(*dispatch), E(e), Pred(pred) {} class iterator { + friend class IndirectGotoNodeBuilder; + CFGBlock::const_succ_iterator I; - friend class IndirectGotoNodeBuilder; iterator(CFGBlock::const_succ_iterator i) : I(i) {} - public: + public: iterator &operator++() { ++I; return *this; } bool operator!=(const iterator &X) const { return I != X.I; } @@ -501,12 +523,13 @@ class SwitchNodeBuilder { public: SwitchNodeBuilder(ExplodedNode *pred, const CFGBlock *src, const Expr *condition, CoreEngine* eng) - : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} + : Eng(*eng), Src(src), Condition(condition), Pred(pred) {} class iterator { + friend class SwitchNodeBuilder; + CFGBlock::const_succ_reverse_iterator I; - friend class SwitchNodeBuilder; iterator(CFGBlock::const_succ_reverse_iterator i) : I(i) {} public: @@ -545,7 +568,8 @@ public: } }; -} // end ento namespace -} // end clang namespace +} // namespace ento + +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_COREENGINE_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h index e13c6410c7be9..092e23ce73c8b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h @@ -14,7 +14,7 @@ namespace clang { namespace ento { -/// \brief Stores the currently inferred strictest bound on the runtime type +/// Stores the currently inferred strictest bound on the runtime type /// of a region in a given state along the analysis path. class DynamicTypeInfo { private: @@ -27,13 +27,13 @@ public: DynamicTypeInfo(QualType WithType, bool CanBeSub = true) : T(WithType), CanBeASubClass(CanBeSub) {} - /// \brief Return false if no dynamic type info is available. + /// Return false if no dynamic type info is available. bool isValid() const { return !T.isNull(); } - /// \brief Returns the currently inferred upper bound on the runtime type. + /// Returns the currently inferred upper bound on the runtime type. QualType getType() const { return T; } - /// \brief Returns false if the type information is precise (the type T is + /// Returns false if the type information is precise (the type T is /// the only type in the lattice), true otherwise. bool canBeASubClass() const { return CanBeASubClass; } diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h index 555191d997099..2f8ead0746cac 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h @@ -1,4 +1,4 @@ -//== DynamicTypeMap.h - Dynamic type map ----------------------- -*- C++ -*--=// +//===- DynamicTypeMap.h - Dynamic type map ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -13,19 +13,26 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H -#include "clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h" + +#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeInfo.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" #include "llvm/ADT/ImmutableMap.h" +#include "clang/AST/Type.h" namespace clang { namespace ento { +class MemRegion; + /// The GDM component containing the dynamic type info. This is a map from a /// symbol to its most likely type. struct DynamicTypeMap {}; -typedef llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo> - DynamicTypeMapImpl; + +using DynamicTypeMapImpl = + llvm::ImmutableMap<const MemRegion *, DynamicTypeInfo>; + template <> struct ProgramStateTrait<DynamicTypeMap> : public ProgramStatePartialTrait<DynamicTypeMapImpl> { @@ -35,15 +42,15 @@ struct ProgramStateTrait<DynamicTypeMap> } }; -/// \brief Get dynamic type information for a region. +/// Get dynamic type information for a region. DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg); -/// \brief Set dynamic type information of the region; return the new state. +/// Set dynamic type information of the region; return the new state. ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg, DynamicTypeInfo NewTy); -/// \brief Set dynamic type information of the region; return the new state. +/// Set dynamic type information of the region; return the new state. inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg, QualType NewTy, bool CanBeSubClassed = true) { @@ -51,7 +58,10 @@ inline ProgramStateRef setDynamicTypeInfo(ProgramStateRef State, DynamicTypeInfo(NewTy, CanBeSubClassed)); } -} // ento -} // clang +void printDynamicTypeInfo(ProgramStateRef State, raw_ostream &Out, + const char *NL, const char *Sep); + +} // namespace ento +} // namespace clang #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_DYNAMICTYPEMAP_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h index c63ed4a013aa6..d49aa81bc9585 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Environment.h @@ -1,4 +1,4 @@ -//== Environment.h - Map from Stmt* to Locations/Values ---------*- C++ -*--==// +//===- Environment.h - Map from Stmt* to Locations/Values -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,17 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H #include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "llvm/ADT/ImmutableMap.h" +#include <utility> namespace clang { -class LiveVariables; +class Stmt; namespace ento { -class EnvironmentManager; class SValBuilder; class SymbolReaper; @@ -32,7 +33,7 @@ class SymbolReaper; /// This allows the environment to manage context-sensitive bindings, /// which is essentially for modeling recursive function analysis, among /// other things. -class EnvironmentEntry : public std::pair<const Stmt*, +class EnvironmentEntry : public std::pair<const Stmt *, const StackFrameContext *> { public: EnvironmentEntry(const Stmt *s, const LocationContext *L); @@ -57,19 +58,17 @@ class Environment { private: friend class EnvironmentManager; - // Type definitions. - typedef llvm::ImmutableMap<EnvironmentEntry, SVal> BindingsTy; + using BindingsTy = llvm::ImmutableMap<EnvironmentEntry, SVal>; - // Data. BindingsTy ExprBindings; - Environment(BindingsTy eb) - : ExprBindings(eb) {} + Environment(BindingsTy eb) : ExprBindings(eb) {} SVal lookupExpr(const EnvironmentEntry &E) const; public: - typedef BindingsTy::iterator iterator; + using iterator = BindingsTy::iterator; + iterator begin() const { return ExprBindings.begin(); } iterator end() const { return ExprBindings.end(); } @@ -92,21 +91,19 @@ public: bool operator==(const Environment& RHS) const { return ExprBindings == RHS.ExprBindings; } - - void print(raw_ostream &Out, const char *NL, const char *Sep) const; - -private: - void printAux(raw_ostream &Out, bool printLocations, - const char *NL, const char *Sep) const; + + void print(raw_ostream &Out, const char *NL, const char *Sep, + const LocationContext *WithLC = nullptr) const; }; class EnvironmentManager { private: - typedef Environment::BindingsTy::Factory FactoryTy; + using FactoryTy = Environment::BindingsTy::Factory; + FactoryTy F; public: - EnvironmentManager(llvm::BumpPtrAllocator& Allocator) : F(Allocator) {} + EnvironmentManager(llvm::BumpPtrAllocator &Allocator) : F(Allocator) {} Environment getInitialEnvironment() { return Environment(F.getEmptyMap()); @@ -121,8 +118,8 @@ public: ProgramStateRef state); }; -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_ENVIRONMENT_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h index dcea5e461d27c..c12198db6598d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExplodedGraph.h @@ -1,4 +1,4 @@ -//=-- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -*- C++ -*-------==// +//===- ExplodedGraph.h - Local, Path-Sens. "Exploded Graph" -----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,17 +19,25 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H -#include "clang/AST/Decl.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Analysis/ProgramPoint.h" #include "clang/Analysis/Support/BumpVector.h" +#include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/GraphTraits.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SetVector.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/Casting.h" +#include "llvm/Support/Compiler.h" +#include <cassert> +#include <cstdint> #include <memory> #include <utility> #include <vector> @@ -37,6 +45,10 @@ namespace clang { class CFG; +class Decl; +class Expr; +class ParentMap; +class Stmt; namespace ento { @@ -52,13 +64,13 @@ class ExplodedGraph; // successors to it at any time after creating it. class ExplodedNode : public llvm::FoldingSetNode { - friend class ExplodedGraph; - friend class CoreEngine; - friend class NodeBuilder; friend class BranchNodeBuilder; + friend class CoreEngine; + friend class EndOfFunctionNodeBuilder; + friend class ExplodedGraph; friend class IndirectGotoNodeBuilder; + friend class NodeBuilder; friend class SwitchNodeBuilder; - friend class EndOfFunctionNodeBuilder; /// Efficiently stores a list of ExplodedNodes, or an optional flag. /// @@ -135,7 +147,7 @@ public: } const StackFrameContext *getStackFrame() const { - return getLocationContext()->getCurrentStackFrame(); + return getLocation().getStackFrame(); } const Decl &getCodeDecl() const { return *getLocationContext()->getDecl(); } @@ -156,6 +168,11 @@ public: return Location.getAs<T>(); } + /// Get the value of an arbitrary expression at this node. + SVal getSVal(const Stmt *S) const { + return getState()->getSVal(S, getLocationContext()); + } + static void Profile(llvm::FoldingSetNodeID &ID, const ProgramPoint &Loc, const ProgramStateRef &state, @@ -198,10 +215,10 @@ public: } // Iterators over successor and predecessor vertices. - typedef ExplodedNode* const * succ_iterator; - typedef const ExplodedNode* const * const_succ_iterator; - typedef ExplodedNode* const * pred_iterator; - typedef const ExplodedNode* const * const_pred_iterator; + using succ_iterator = ExplodedNode * const *; + using const_succ_iterator = const ExplodedNode * const *; + using pred_iterator = ExplodedNode * const *; + using const_pred_iterator = const ExplodedNode * const *; pred_iterator pred_begin() { return Preds.begin(); } pred_iterator pred_end() { return Preds.end(); } @@ -226,10 +243,10 @@ public: // For debugging. public: - class Auditor { public: virtual ~Auditor(); + virtual void AddEdge(ExplodedNode *Src, ExplodedNode *Dst) = 0; }; @@ -240,15 +257,15 @@ private: void replacePredecessor(ExplodedNode *node) { Preds.replaceNode(node); } }; -typedef llvm::DenseMap<const ExplodedNode *, const ExplodedNode *> - InterExplodedGraphMap; +using InterExplodedGraphMap = + llvm::DenseMap<const ExplodedNode *, const ExplodedNode *>; class ExplodedGraph { protected: friend class CoreEngine; // Type definitions. - typedef std::vector<ExplodedNode *> NodeVector; + using NodeVector = std::vector<ExplodedNode *>; /// The roots of the simulation graph. Usually there will be only /// one, but clients are free to establish multiple subgraphs within a single @@ -268,7 +285,7 @@ protected: BumpVectorContext BVC; /// NumNodes - The number of nodes in the graph. - unsigned NumNodes; + unsigned NumNodes = 0; /// A list of recently allocated nodes that can potentially be recycled. NodeVector ChangedNodes; @@ -279,14 +296,16 @@ protected: /// Determines how often nodes are reclaimed. /// /// If this is 0, nodes will never be reclaimed. - unsigned ReclaimNodeInterval; + unsigned ReclaimNodeInterval = 0; /// Counter to determine when to reclaim nodes. unsigned ReclaimCounter; public: + ExplodedGraph(); + ~ExplodedGraph(); - /// \brief Retrieve the node associated with a (Location,State) pair, + /// Retrieve the node associated with a (Location,State) pair, /// where the 'Location' is a ProgramPoint in the CFG. If no node for /// this pair exists, it is created. IsNew is set to true if /// the node was freshly created. @@ -294,7 +313,7 @@ public: bool IsSink = false, bool* IsNew = nullptr); - /// \brief Create a node for a (Location, State) pair, + /// Create a node for a (Location, State) pair, /// but don't store it for deduplication later. This /// is useful when copying an already completed /// ExplodedGraph for further processing. @@ -318,10 +337,6 @@ public: return V; } - ExplodedGraph(); - - ~ExplodedGraph(); - unsigned num_roots() const { return Roots.size(); } unsigned num_eops() const { return EndNodes.size(); } @@ -331,14 +346,14 @@ public: void reserve(unsigned NodeCount) { Nodes.reserve(NodeCount); } // Iterators. - typedef ExplodedNode NodeTy; - typedef llvm::FoldingSet<ExplodedNode> AllNodesTy; - typedef NodeVector::iterator roots_iterator; - typedef NodeVector::const_iterator const_roots_iterator; - typedef NodeVector::iterator eop_iterator; - typedef NodeVector::const_iterator const_eop_iterator; - typedef AllNodesTy::iterator node_iterator; - typedef AllNodesTy::const_iterator const_node_iterator; + using NodeTy = ExplodedNode; + using AllNodesTy = llvm::FoldingSet<ExplodedNode>; + using roots_iterator = NodeVector::iterator; + using const_roots_iterator = NodeVector::const_iterator; + using eop_iterator = NodeVector::iterator; + using const_eop_iterator = NodeVector::const_iterator; + using node_iterator = AllNodesTy::iterator; + using const_node_iterator = AllNodesTy::const_iterator; node_iterator nodes_begin() { return Nodes.begin(); } @@ -367,7 +382,7 @@ public: llvm::BumpPtrAllocator & getAllocator() { return BVC.getAllocator(); } BumpVectorContext &getNodeAllocator() { return BVC; } - typedef llvm::DenseMap<const ExplodedNode*, ExplodedNode*> NodeMap; + using NodeMap = llvm::DenseMap<const ExplodedNode *, ExplodedNode *>; /// Creates a trimmed version of the graph that only contains paths leading /// to the given nodes. @@ -394,7 +409,7 @@ public: /// was called. void reclaimRecentlyAllocatedNodes(); - /// \brief Returns true if nodes for the given expression kind are always + /// Returns true if nodes for the given expression kind are always /// kept around. static bool isInterestingLValueExpr(const Expr *Ex); @@ -404,29 +419,30 @@ private: }; class ExplodedNodeSet { - typedef llvm::SmallSetVector<ExplodedNode*, 4> ImplTy; + using ImplTy = llvm::SmallSetVector<ExplodedNode *, 4>; ImplTy Impl; public: ExplodedNodeSet(ExplodedNode *N) { - assert (N && !static_cast<ExplodedNode*>(N)->isSink()); + assert(N && !static_cast<ExplodedNode*>(N)->isSink()); Impl.insert(N); } - ExplodedNodeSet() {} + ExplodedNodeSet() = default; - inline void Add(ExplodedNode *N) { + void Add(ExplodedNode *N) { if (N && !static_cast<ExplodedNode*>(N)->isSink()) Impl.insert(N); } - typedef ImplTy::iterator iterator; - typedef ImplTy::const_iterator const_iterator; + using iterator = ImplTy::iterator; + using const_iterator = ImplTy::const_iterator; unsigned size() const { return Impl.size(); } bool empty() const { return Impl.empty(); } bool erase(ExplodedNode *N) { return Impl.remove(N); } void clear() { Impl.clear(); } + void insert(const ExplodedNodeSet &S) { assert(&S != this); if (empty()) @@ -435,24 +451,25 @@ public: Impl.insert(S.begin(), S.end()); } - inline iterator begin() { return Impl.begin(); } - inline iterator end() { return Impl.end(); } + iterator begin() { return Impl.begin(); } + iterator end() { return Impl.end(); } - inline const_iterator begin() const { return Impl.begin(); } - inline const_iterator end() const { return Impl.end(); } + const_iterator begin() const { return Impl.begin(); } + const_iterator end() const { return Impl.end(); } }; -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang // GraphTraits namespace llvm { + template<> struct GraphTraits<clang::ento::ExplodedNode*> { - typedef clang::ento::ExplodedNode *NodeRef; - typedef clang::ento::ExplodedNode::succ_iterator ChildIteratorType; - typedef llvm::df_iterator<NodeRef> nodes_iterator; + using NodeRef = clang::ento::ExplodedNode *; + using ChildIteratorType = clang::ento::ExplodedNode::succ_iterator; + using nodes_iterator = llvm::df_iterator<NodeRef>; static NodeRef getEntryNode(NodeRef N) { return N; } @@ -466,9 +483,9 @@ namespace llvm { }; template<> struct GraphTraits<const clang::ento::ExplodedNode*> { - typedef const clang::ento::ExplodedNode *NodeRef; - typedef clang::ento::ExplodedNode::const_succ_iterator ChildIteratorType; - typedef llvm::df_iterator<NodeRef> nodes_iterator; + using NodeRef = const clang::ento::ExplodedNode *; + using ChildIteratorType = clang::ento::ExplodedNode::const_succ_iterator; + using nodes_iterator = llvm::df_iterator<NodeRef>; static NodeRef getEntryNode(NodeRef N) { return N; } @@ -481,6 +498,6 @@ namespace llvm { static nodes_iterator nodes_end(NodeRef N) { return df_end(N); } }; -} // end llvm namespace +} // namespace llvm -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPLODEDGRAPH_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h index 712cd6361e118..25849e94c8ff1 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h @@ -1,4 +1,4 @@ -//===-- ExprEngine.h - Path-Sensitive Expression-Level Dataflow ---*- C++ -*-=// +//===- ExprEngine.h - Path-Sensitive Expression-Level Dataflow --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,32 +18,68 @@ #include "clang/AST/Expr.h" #include "clang/AST/Type.h" +#include "clang/Analysis/CFG.h" #include "clang/Analysis/DomainSpecific/ObjCNoReturn.h" +#include "clang/Analysis/ProgramPoint.h" +#include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" #include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" #include "clang/StaticAnalyzer/Core/PathSensitive/CoreEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/WorkList.h" +#include "llvm/ADT/ArrayRef.h" +#include <cassert> +#include <utility> namespace clang { class AnalysisDeclContextManager; +class AnalyzerOptions; +class ASTContext; +class ConstructionContext; +class CXXBindTemporaryExpr; class CXXCatchStmt; class CXXConstructExpr; class CXXDeleteExpr; class CXXNewExpr; -class CXXTemporaryObjectExpr; class CXXThisExpr; +class Decl; +class DeclStmt; +class GCCAsmStmt; +class LambdaExpr; +class LocationContext; class MaterializeTemporaryExpr; +class MSAsmStmt; +class NamedDecl; class ObjCAtSynchronizedStmt; class ObjCForCollectionStmt; +class ObjCIvarRefExpr; +class ObjCMessageExpr; +class ReturnStmt; +class Stmt; + +namespace cross_tu { + +class CrossTranslationUnitContext; + +} // namespace cross_tu namespace ento { -class AnalysisManager; +class BasicValueFactory; class CallEvent; -class CXXConstructorCall; +class CheckerManager; +class ConstraintManager; +class CXXTempObjectRegion; +class MemRegion; +class RegionAndSymbolInvalidationTraits; +class SymbolManager; class ExprEngine : public SubEngine { public: @@ -51,11 +87,35 @@ public: enum InliningModes { /// Follow the default settings for inlining callees. Inline_Regular = 0, + /// Do minimal inlining of callees. Inline_Minimal = 0x1 }; + /// Hints for figuring out of a call should be inlined during evalCall(). + struct EvalCallOptions { + /// This call is a constructor or a destructor for which we do not currently + /// compute the this-region correctly. + bool IsCtorOrDtorWithImproperlyModeledTargetRegion = false; + + /// This call is a constructor or a destructor for a single element within + /// an array, a part of array construction or destruction. + bool IsArrayCtorOrDtor = false; + + /// This call is a constructor or a destructor of a temporary value. + bool IsTemporaryCtorOrDtor = false; + + /// This call is a constructor for a temporary that is lifetime-extended + /// by binding it to a reference-type field within an aggregate, + /// for example 'A { const C &c; }; A a = { C() };' + bool IsTemporaryLifetimeExtendedViaAggregate = false; + + EvalCallOptions() {} + }; + private: + cross_tu::CrossTranslationUnitContext &CTU; + AnalysisManager &AMgr; AnalysisDeclContextManager &AnalysisDeclContexts; @@ -63,19 +123,19 @@ private: CoreEngine Engine; /// G - the simulation graph. - ExplodedGraph& G; + ExplodedGraph &G; /// StateMgr - Object that manages the data for all created states. ProgramStateManager StateMgr; /// SymMgr - Object that manages the symbol information. - SymbolManager& SymMgr; + SymbolManager &SymMgr; /// svalBuilder - SValBuilder object that creates SVals from expressions. SValBuilder &svalBuilder; - unsigned int currStmtIdx; - const NodeBuilderContext *currBldrCtx; + unsigned int currStmtIdx = 0; + const NodeBuilderContext *currBldrCtx = nullptr; /// Helper object to determine if an Objective-C message expression /// implicitly never returns. @@ -97,10 +157,9 @@ private: InliningModes HowToInline; public: - ExprEngine(AnalysisManager &mgr, bool gcEnabled, - SetOfConstDecls *VisitedCalleesIn, - FunctionSummariesTy *FS, - InliningModes HowToInlineIn); + ExprEngine(cross_tu::CrossTranslationUnitContext &CTU, AnalysisManager &mgr, + bool gcEnabled, SetOfConstDecls *VisitedCalleesIn, + FunctionSummariesTy *FS, InliningModes HowToInlineIn); ~ExprEngine() override; @@ -130,7 +189,12 @@ public: SValBuilder &getSValBuilder() { return svalBuilder; } - BugReporter& getBugReporter() { return BR; } + BugReporter &getBugReporter() { return BR; } + + cross_tu::CrossTranslationUnitContext * + getCrossTranslationUnitContext() override { + return &CTU; + } const NodeBuilderContext &getBuilderContext() { assert(currBldrCtx); @@ -150,16 +214,16 @@ public: /// Visualize a trimmed ExplodedGraph that only contains paths to the given /// nodes. - void ViewGraph(ArrayRef<const ExplodedNode*> Nodes); + void ViewGraph(ArrayRef<const ExplodedNode *> Nodes); /// getInitialState - Return the initial state used for the root vertex /// in the ExplodedGraph. ProgramStateRef getInitialState(const LocationContext *InitLoc) override; - ExplodedGraph& getGraph() { return G; } - const ExplodedGraph& getGraph() const { return G; } + ExplodedGraph &getGraph() { return G; } + const ExplodedGraph &getGraph() const { return G; } - /// \brief Run the analyzer's garbage collection - remove dead symbols and + /// Run the analyzer's garbage collection - remove dead symbols and /// bindings from the state. /// /// Checkers can participate in this process with two callbacks: @@ -194,7 +258,7 @@ public: void processCFGElement(const CFGElement E, ExplodedNode *Pred, unsigned StmtIdx, NodeBuilderContext *Ctx) override; - void ProcessStmt(const CFGStmt S, ExplodedNode *Pred); + void ProcessStmt(const Stmt *S, ExplodedNode *Pred); void ProcessLoopExit(const Stmt* S, ExplodedNode *Pred); @@ -299,25 +363,26 @@ public: const CallEvent *Call) override; /// printState - Called by ProgramStateManager to print checker-specific data. - void printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep) override; + void printState(raw_ostream &Out, ProgramStateRef State, const char *NL, + const char *Sep, + const LocationContext *LCtx = nullptr) override; - ProgramStateManager& getStateManager() override { return StateMgr; } + ProgramStateManager &getStateManager() override { return StateMgr; } - StoreManager& getStoreManager() { return StateMgr.getStoreManager(); } + StoreManager &getStoreManager() { return StateMgr.getStoreManager(); } - ConstraintManager& getConstraintManager() { + ConstraintManager &getConstraintManager() { return StateMgr.getConstraintManager(); } // FIXME: Remove when we migrate over to just using SValBuilder. - BasicValueFactory& getBasicVals() { + BasicValueFactory &getBasicVals() { return StateMgr.getBasicVals(); } // FIXME: Remove when we migrate over to just using ValueManager. - SymbolManager& getSymbolManager() { return SymMgr; } - const SymbolManager& getSymbolManager() const { return SymMgr; } + SymbolManager &getSymbolManager() { return SymMgr; } + const SymbolManager &getSymbolManager() const { return SymMgr; } // Functions for external checking of whether we have unfinished work bool wasBlocksExhausted() const { return Engine.wasBlocksExhausted(); } @@ -363,7 +428,7 @@ public: /// VisitCast - Transfer function logic for all casts (implicit and explicit). void VisitCast(const CastExpr *CastE, const Expr *Ex, ExplodedNode *Pred, - ExplodedNodeSet &Dst); + ExplodedNodeSet &Dst); /// VisitCompoundLiteralExpr - Transfer function logic for compound literals. void VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, @@ -390,9 +455,9 @@ public: /// VisitMemberExpr - Transfer function for member expressions. void VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, - ExplodedNodeSet &Dst); + ExplodedNodeSet &Dst); - /// VisitMemberExpr - Transfer function for builtin atomic expressions + /// VisitAtomicExpr - Transfer function for builtin atomic expressions void VisitAtomicExpr(const AtomicExpr *E, ExplodedNode *Pred, ExplodedNodeSet &Dst); @@ -422,7 +487,7 @@ public: /// VisitUnaryExprOrTypeTraitExpr - Transfer function for sizeof. void VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, - ExplodedNode *Pred, ExplodedNodeSet &Dst); + ExplodedNode *Pred, ExplodedNodeSet &Dst); /// VisitUnaryOperator - Transfer function logic for unary operators. void VisitUnaryOperator(const UnaryOperator* B, ExplodedNode *Pred, @@ -448,7 +513,8 @@ public: void VisitCXXDestructor(QualType ObjectType, const MemRegion *Dest, const Stmt *S, bool IsBaseDtor, - ExplodedNode *Pred, ExplodedNodeSet &Dst); + ExplodedNode *Pred, ExplodedNodeSet &Dst, + const EvalCallOptions &Options); void VisitCXXNewAllocatorCall(const CXXNewExpr *CNE, ExplodedNode *Pred, @@ -471,7 +537,7 @@ public: void evalEagerlyAssumeBinOpBifurcation(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, const Expr *Ex); - std::pair<const ProgramPointTag *, const ProgramPointTag*> + static std::pair<const ProgramPointTag *, const ProgramPointTag *> geteagerlyAssumeBinOpBifurcationTags(); SVal evalMinus(SVal X) { @@ -499,7 +565,6 @@ public: StmtNodeBuilder &Bldr); public: - SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, NonLoc L, NonLoc R, QualType T) { return svalBuilder.evalBinOpNN(state, op, L, R, T); @@ -539,6 +604,11 @@ protected: const CallEvent *Call, RegionAndSymbolInvalidationTraits &ITraits) override; + /// A simple wrapper when you only need to notify checkers of pointer-escape + /// of a single value. + ProgramStateRef escapeValue(ProgramStateRef State, SVal V, + PointerEscapeKind K) const; + public: // FIXME: 'tag' should be removed, and a LocationContext should be used // instead. @@ -561,7 +631,13 @@ public: ExplodedNode *Pred, ProgramStateRef St, SVal TargetLV, SVal Val, const ProgramPointTag *tag = nullptr); - /// \brief Create a new state in which the call return value is binded to the + /// Return the CFG element corresponding to the worklist element + /// that is currently being processed by ExprEngine. + CFGElement getCurrentCFGElement() { + return (*currBldrCtx->getBlock())[currStmtIdx]; + } + + /// Create a new state in which the call return value is binded to the /// call origin expression. ProgramStateRef bindReturnValue(const CallEvent &Call, const LocationContext *LCtx, @@ -572,9 +648,11 @@ public: void evalCall(ExplodedNodeSet &Dst, ExplodedNode *Pred, const CallEvent &Call); - /// \brief Default implementation of call evaluation. + /// Default implementation of call evaluation. void defaultEvalCall(NodeBuilder &B, ExplodedNode *Pred, - const CallEvent &Call); + const CallEvent &Call, + const EvalCallOptions &CallOpts = {}); + private: void evalLoadCommon(ExplodedNodeSet &Dst, const Expr *NodeEx, /* Eventually will be a CFGStmt */ @@ -598,19 +676,33 @@ private: void examineStackFrames(const Decl *D, const LocationContext *LCtx, bool &IsRecursive, unsigned &StackDepth); + enum CallInlinePolicy { + CIP_Allowed, + CIP_DisallowedOnce, + CIP_DisallowedAlways + }; + + /// See if a particular call should be inlined, by only looking + /// at the call event and the current state of analysis. + CallInlinePolicy mayInlineCallKind(const CallEvent &Call, + const ExplodedNode *Pred, + AnalyzerOptions &Opts, + const EvalCallOptions &CallOpts); + /// Checks our policies and decides weither the given call should be inlined. bool shouldInlineCall(const CallEvent &Call, const Decl *D, - const ExplodedNode *Pred); + const ExplodedNode *Pred, + const EvalCallOptions &CallOpts = {}); bool inlineCall(const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State); - /// \brief Conservatively evaluate call by invalidating regions and binding + /// Conservatively evaluate call by invalidating regions and binding /// a conjured return value. void conservativeEvalCall(const CallEvent &Call, NodeBuilder &Bldr, ExplodedNode *Pred, ProgramStateRef State); - /// \brief Either inline or process the call conservatively (or both), based + /// Either inline or process the call conservatively (or both), based /// on DynamicDispatchBifurcation data. void BifurcateCall(const MemRegion *BifurReg, const CallEvent &Call, const Decl *D, NodeBuilder &Bldr, @@ -634,6 +726,17 @@ private: const Expr *InitWithAdjustments, const Expr *Result = nullptr); + /// Returns a region representing the first element of a (possibly + /// multi-dimensional) array, for the purposes of element construction or + /// destruction. + /// + /// On return, \p Ty will be set to the base type of the array. + /// + /// If the type is not an array type at all, the original value is returned. + /// Otherwise the "IsArray" flag is set. + static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue, + QualType &Ty, bool &IsArray); + /// For a DeclStmt or CXXInitCtorInitializer, walk backward in the current CFG /// block to find the constructor expression that directly constructed into /// the storage for this statement. Returns null if the constructor for this @@ -641,20 +744,69 @@ private: /// constructing into an existing region. const CXXConstructExpr *findDirectConstructorForCurrentCFGElement(); - /// For a CXXConstructExpr, walk forward in the current CFG block to find the - /// CFGElement for the DeclStmt or CXXInitCtorInitializer for which is - /// directly constructed by this constructor. Returns None if the current - /// constructor expression did not directly construct into an existing - /// region. - Optional<CFGElement> findElementDirectlyInitializedByCurrentConstructor(); - - /// For a given constructor, look forward in the current CFG block to - /// determine the region into which an object will be constructed by \p CE. - /// Returns either a field or local variable region if the object will be - /// directly constructed in an existing region or a temporary object region - /// if not. - const MemRegion *getRegionForConstructedObject(const CXXConstructExpr *CE, - ExplodedNode *Pred); + /// Update the program state with all the path-sensitive information + /// that's necessary to perform construction of an object with a given + /// syntactic construction context. If the construction context is unavailable + /// or unusable for any reason, a dummy temporary region is returned, and the + /// IsConstructorWithImproperlyModeledTargetRegion flag is set in \p CallOpts. + /// Returns the updated program state and the new object's this-region. + std::pair<ProgramStateRef, SVal> prepareForObjectConstruction( + const Expr *E, ProgramStateRef State, const LocationContext *LCtx, + const ConstructionContext *CC, EvalCallOptions &CallOpts); + + /// Store the location of a C++ object corresponding to a statement + /// until the statement is actually encountered. For example, if a DeclStmt + /// has CXXConstructExpr as its initializer, the object would be considered + /// to be "under construction" between CXXConstructExpr and DeclStmt. + /// This allows, among other things, to keep bindings to variable's fields + /// made within the constructor alive until its declaration actually + /// goes into scope. + static ProgramStateRef addObjectUnderConstruction( + ProgramStateRef State, + llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P, + const LocationContext *LC, SVal V); + + /// Mark the object sa fully constructed, cleaning up the state trait + /// that tracks objects under construction. + static ProgramStateRef finishObjectConstruction( + ProgramStateRef State, + llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P, + const LocationContext *LC); + + /// If the given statement corresponds to an object under construction, + /// being part of its construciton context, retrieve that object's location. + static Optional<SVal> getObjectUnderConstruction( + ProgramStateRef State, + llvm::PointerUnion<const Stmt *, const CXXCtorInitializer *> P, + const LocationContext *LC); + + /// If the given expression corresponds to a temporary that was used for + /// passing into an elidable copy/move constructor and that constructor + /// was actually elided, track that we also need to elide the destructor. + static ProgramStateRef elideDestructor(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC); + + /// Stop tracking the destructor that corresponds to an elided constructor. + static ProgramStateRef + cleanupElidedDestructor(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC); + + /// Returns true if the given expression corresponds to a temporary that + /// was constructed for passing into an elidable copy/move constructor + /// and that constructor was actually elided. + static bool isDestructorElided(ProgramStateRef State, + const CXXBindTemporaryExpr *BTE, + const LocationContext *LC); + + /// Check if all objects under construction have been fully constructed + /// for the given context range (including FromLC, not including ToLC). + /// This is useful for assertions. Also checks if elided destructors + /// were cleaned up. + static bool areAllObjectsFullyConstructed(ProgramStateRef State, + const LocationContext *FromLC, + const LocationContext *ToLC); }; /// Traits for storing the call processing policy inside GDM. @@ -668,8 +820,8 @@ struct ProgramStateTrait<ReplayWithoutInlining> : static void *GDMIndex() { static int index = 0; return &index; } }; -} // end ento namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_EXPRENGINE_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h index ce81c98c206b2..b70faa10f0b2c 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/FunctionSummary.h @@ -1,4 +1,4 @@ -//== FunctionSummary.h - Stores summaries of functions. ------------*- C++ -*-// +//===- FunctionSummary.h - Stores summaries of functions. -------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,15 +18,18 @@ #include "clang/Basic/LLVM.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/SmallBitVector.h" +#include <cassert> #include <deque> +#include <utility> namespace clang { - namespace ento { -typedef std::deque<Decl*> SetOfDecls; -typedef llvm::DenseSet<const Decl*> SetOfConstDecls; + +using SetOfDecls = std::deque<Decl *>; +using SetOfConstDecls = llvm::DenseSet<const Decl *>; class FunctionSummariesTy { class FunctionSummary { @@ -47,13 +50,12 @@ class FunctionSummariesTy { /// The number of times the function has been inlined. unsigned TimesInlined : 32; - FunctionSummary() : - TotalBasicBlocks(0), - InlineChecked(0), - TimesInlined(0) {} + FunctionSummary() + : TotalBasicBlocks(0), InlineChecked(0), MayInline(0), + TimesInlined(0) {} }; - typedef llvm::DenseMap<const Decl *, FunctionSummary> MapTy; + using MapTy = llvm::DenseMap<const Decl *, FunctionSummary>; MapTy Map; public: @@ -62,7 +64,8 @@ public: if (I != Map.end()) return I; - typedef std::pair<const Decl *, FunctionSummary> KVPair; + using KVPair = std::pair<const Decl *, FunctionSummary>; + I = Map.insert(KVPair(D, FunctionSummary())).first; assert(I != Map.end()); return I; @@ -132,9 +135,9 @@ public: unsigned getTotalNumBasicBlocks(); unsigned getTotalNumVisitedBasicBlocks(); - }; -}} // end clang ento namespaces +} // namespace ento +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_FUNCTIONSUMMARY_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h index 3168733e4258e..f494c5d6dab82 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/LoopWidening.h @@ -22,7 +22,7 @@ namespace clang { namespace ento { -/// \brief Get the states that result from widening the loop. +/// Get the states that result from widening the loop. /// /// Widen the loop by invalidating anything that might be modified /// by the loop body in any iteration. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 8ab6656230888..f3846eba6b963 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -1,4 +1,4 @@ -//== MemRegion.h - Abstract memory regions for static analysis --*- C++ -*--==// +//==- MemRegion.h - Abstract memory regions for static analysis -*- C++ -*--==// // // The LLVM Compiler Infrastructure // @@ -19,24 +19,39 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/CharUnits.h" #include "clang/AST/Decl.h" -#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" +#include "clang/AST/DeclarationName.h" +#include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" -#include "clang/Analysis/AnalysisDeclContext.h" +#include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" +#include "clang/Basic/SourceLocation.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/FoldingSet.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerIntPair.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstdint> +#include <limits> #include <string> +#include <utility> namespace clang { +class AnalysisDeclContext; +class CXXRecordDecl; +class Decl; class LocationContext; class StackFrameContext; namespace ento { class CodeTextRegion; +class MemRegion; class MemRegionManager; class MemSpaceRegion; class SValBuilder; @@ -46,7 +61,7 @@ class VarRegion; /// Represent a region's offset within the top level base region. class RegionOffset { /// The base region. - const MemRegion *R; + const MemRegion *R = nullptr; /// The bit offset within the base region. Can be negative. int64_t Offset; @@ -54,9 +69,9 @@ class RegionOffset { public: // We're using a const instead of an enumeration due to the size required; // Visual Studio will only create enumerations of size int, not long long. - static const int64_t Symbolic = INT64_MAX; + static const int64_t Symbolic = std::numeric_limits<int64_t>::max(); - RegionOffset() : R(nullptr) {} + RegionOffset() = default; RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {} const MemRegion *getRegion() const { return R; } @@ -86,6 +101,7 @@ public: private: const Kind kind; + mutable Optional<RegionOffset> cachedOffset; protected: MemRegion(Kind k) : kind(k) {} @@ -103,11 +119,12 @@ public: const MemRegion *getBaseRegion() const; /// Check if the region is a subregion of the given region. + /// Each region is a subregion of itself. virtual bool isSubRegionOf(const MemRegion *R) const; const MemRegion *StripCasts(bool StripBaseCasts = true) const; - /// \brief If this is a symbolic region, returns the region. Otherwise, + /// If this is a symbolic region, returns the region. Otherwise, /// goes up the base chain looking for the first symbolic base region. const SymbolicRegion *getSymbolicBase() const; @@ -122,24 +139,24 @@ public: /// Compute the offset within the top level memory object. RegionOffset getAsOffset() const; - /// \brief Get a string representation of a region for debug use. + /// Get a string representation of a region for debug use. std::string getString() const; virtual void dumpToStream(raw_ostream &os) const; void dump() const; - /// \brief Returns true if this region can be printed in a user-friendly way. + /// Returns true if this region can be printed in a user-friendly way. virtual bool canPrintPretty() const; - /// \brief Print the region for use in diagnostics. + /// Print the region for use in diagnostics. virtual void printPretty(raw_ostream &os) const; - /// \brief Returns true if this region's textual representation can be used + /// Returns true if this region's textual representation can be used /// as part of a larger expression. virtual bool canPrintPrettyAsExpr() const; - /// \brief Print the region as expression. + /// Print the region as expression. /// /// When this region represents a subexpression, the method is for printing /// an expression containing it. @@ -151,7 +168,6 @@ public: virtual bool isBoundable() const { return false; } - /// Get descriptive name for memory region. The name is obtained from /// the variable/field declaration retrieved from the memory region. /// Regions that point to an element of an array are returned as: "arr[0]". @@ -162,7 +178,6 @@ public: /// \returns variable name for memory region std::string getDescriptiveName(bool UseQuotes = true) const; - /// Retrieve source range from memory region. The range retrieval /// is based on the decl obtained from the memory region. /// For a VarRegion the range of the base region is returned. @@ -171,7 +186,7 @@ public: /// The client is responsible for checking if the returned range is valid. /// /// \returns source range for declaration retrieved from memory region - clang::SourceRange sourceRange() const; + SourceRange sourceRange() const; }; /// MemSpaceRegion - A memory region that represents a "memory space"; @@ -229,7 +244,7 @@ public: } }; -/// \brief The region of the static variables within the current CodeTextRegion +/// The region of the static variables within the current CodeTextRegion /// scope. /// /// Currently, only the static locals are placed there, so we know that these @@ -240,7 +255,7 @@ class StaticGlobalSpaceRegion : public GlobalsSpaceRegion { const CodeTextRegion *CR; StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr) - : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) { + : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) { assert(cr); } @@ -256,14 +271,14 @@ public: } }; -/// \brief The region for all the non-static global variables. +/// The region for all the non-static global variables. /// /// This class is further split into subclasses for efficient implementation of /// invalidating a set of related global values as is done in /// RegionStoreManager::invalidateRegions (instead of finding all the dependent /// globals, we invalidate the whole parent region). class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion { - virtual void anchor() override; + void anchor() override; protected: NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k) @@ -272,7 +287,6 @@ protected: } public: - static bool classof(const MemRegion *R) { Kind k = R->getKind(); return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES && @@ -280,16 +294,15 @@ public: } }; -/// \brief The region containing globals which are defined in system/external +/// The region containing globals which are defined in system/external /// headers and are considered modifiable by system calls (ex: errno). class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion { friend class MemRegionManager; GlobalSystemSpaceRegion(MemRegionManager *mgr) - : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {} + : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -297,7 +310,7 @@ public: } }; -/// \brief The region containing globals which are considered not to be modified +/// The region containing globals which are considered not to be modified /// or point to data which could be modified as a result of a function call /// (system or internal). Ex: Const global scalars would be modeled as part of /// this region. This region also includes most system globals since they have @@ -306,10 +319,9 @@ class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion { friend class MemRegionManager; GlobalImmutableSpaceRegion(MemRegionManager *mgr) - : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {} + : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -317,17 +329,16 @@ public: } }; -/// \brief The region containing globals which can be modified by calls to +/// The region containing globals which can be modified by calls to /// "internally" defined functions - (for now just) functions other then system /// calls. class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion { friend class MemRegionManager; GlobalInternalSpaceRegion(MemRegionManager *mgr) - : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {} + : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -339,9 +350,9 @@ class HeapSpaceRegion : public MemSpaceRegion { friend class MemRegionManager; HeapSpaceRegion(MemRegionManager *mgr) - : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} -public: + : MemSpaceRegion(mgr, HeapSpaceRegionKind) {} +public: void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -351,11 +362,11 @@ public: class UnknownSpaceRegion : public MemSpaceRegion { friend class MemRegionManager; + UnknownSpaceRegion(MemRegionManager *mgr) : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {} public: - void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -370,7 +381,7 @@ class StackSpaceRegion : public MemSpaceRegion { protected: StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc) - : MemSpaceRegion(mgr, k), SFC(sfc) { + : MemSpaceRegion(mgr, k), SFC(sfc) { assert(classof(this)); assert(sfc); } @@ -388,10 +399,11 @@ public: class StackLocalsSpaceRegion : public StackSpaceRegion { friend class MemRegionManager; + StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) - : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} -public: + : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {} +public: void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -402,10 +414,11 @@ public: class StackArgumentsSpaceRegion : public StackSpaceRegion { private: friend class MemRegionManager; + StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc) - : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} -public: + : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {} +public: void dumpToStream(raw_ostream &os) const override; static bool classof(const MemRegion *R) { @@ -413,7 +426,6 @@ public: } }; - /// SubRegion - A region that subsets another larger region. Most regions /// are subclasses of SubRegion. class SubRegion : public MemRegion { @@ -421,6 +433,7 @@ class SubRegion : public MemRegion { protected: const MemRegion* superRegion; + SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) { assert(classof(this)); assert(sReg); @@ -454,8 +467,10 @@ public: class AllocaRegion : public SubRegion { friend class MemRegionManager; - unsigned Cnt; // Block counter. Used to distinguish different pieces of - // memory allocated by alloca at the same call site. + // Block counter. Used to distinguish different pieces of memory allocated by + // alloca at the same call site. + unsigned Cnt; + const Expr *Ex; AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion) @@ -467,7 +482,6 @@ class AllocaRegion : public SubRegion { unsigned Cnt, const MemRegion *superRegion); public: - const Expr *getExpr() const { return Ex; } bool isBoundable() const override { return true; } @@ -485,7 +499,7 @@ public: /// TypedRegion - An abstract class representing regions that are typed. class TypedRegion : public SubRegion { - virtual void anchor() override; + void anchor() override; protected: TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) { @@ -509,7 +523,7 @@ public: /// TypedValueRegion - An abstract class representing regions having a typed value. class TypedValueRegion : public TypedRegion { - virtual void anchor() override; + void anchor() override; protected: TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) { @@ -541,9 +555,8 @@ public: } }; - class CodeTextRegion : public TypedRegion { - virtual void anchor() override; + void anchor() override; protected: CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) { @@ -566,7 +579,7 @@ class FunctionCodeRegion : public CodeTextRegion { const NamedDecl *FD; FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg) - : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { + : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) { assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd)); } @@ -576,7 +589,7 @@ class FunctionCodeRegion : public CodeTextRegion { public: QualType getLocationType() const override { const ASTContext &Ctx = getContext(); - if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) { + if (const auto *D = dyn_cast<FunctionDecl>(FD)) { return Ctx.getPointerType(D->getType()); } @@ -585,7 +598,7 @@ public: // TODO: We might want to return a different type here (ex: id (*ty)(...)) // depending on how it is used. - return QualType(); + return {}; } const NamedDecl *getDecl() const { @@ -601,7 +614,6 @@ public: } }; - /// BlockCodeRegion - A region that represents code texts of blocks (closures). /// Blocks are represented with two kinds of regions. BlockCodeRegions /// represent the "code", while BlockDataRegions represent instances of blocks, @@ -657,15 +669,15 @@ class BlockDataRegion : public TypedRegion { friend class MemRegionManager; const BlockCodeRegion *BC; - const LocationContext *LC; // Can be null */ + const LocationContext *LC; // Can be null unsigned BlockCount; - void *ReferencedVars; - void *OriginalVars; + void *ReferencedVars = nullptr; + void *OriginalVars = nullptr; BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc, unsigned count, const MemSpaceRegion *sreg) : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc), - BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) { + BlockCount(count) { assert(bc); assert(lc); assert(isa<GlobalImmutableSpaceRegion>(sreg) || @@ -679,7 +691,7 @@ class BlockDataRegion : public TypedRegion { public: const BlockCodeRegion *getCodeRegion() const { return BC; } - + const BlockDecl *getDecl() const { return BC->getDecl(); } QualType getLocationType() const override { return BC->getLocationType(); } @@ -687,14 +699,16 @@ public: class referenced_vars_iterator { const MemRegion * const *R; const MemRegion * const *OriginalR; + public: explicit referenced_vars_iterator(const MemRegion * const *r, const MemRegion * const *originalR) - : R(r), OriginalR(originalR) {} + : R(r), OriginalR(originalR) {} const VarRegion *getCapturedRegion() const { return cast<VarRegion>(*R); } + const VarRegion *getOriginalRegion() const { return cast<VarRegion>(*OriginalR); } @@ -703,10 +717,12 @@ public: assert((R == nullptr) == (I.R == nullptr)); return I.R == R; } + bool operator!=(const referenced_vars_iterator &I) const { assert((R == nullptr) == (I.R == nullptr)); return I.R != R; } + referenced_vars_iterator &operator++() { ++R; ++OriginalR; @@ -728,6 +744,7 @@ public: static bool classof(const MemRegion* R) { return R->getKind() == BlockDataRegionKind; } + private: void LazyInitializeReferencedVars(); std::pair<const VarRegion *, const VarRegion *> @@ -754,9 +771,7 @@ class SymbolicRegion : public SubRegion { } public: - SymbolRef getSymbol() const { - return sym; - } + SymbolRef getSymbol() const { return sym; } bool isBoundable() const override { return true; } @@ -779,24 +794,21 @@ public: class StringRegion : public TypedValueRegion { friend class MemRegionManager; - const StringLiteral* Str; + const StringLiteral *Str; StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg) : TypedValueRegion(sreg, StringRegionKind), Str(str) { assert(str); } - static void ProfileRegion(llvm::FoldingSetNodeID& ID, - const StringLiteral* Str, - const MemRegion* superRegion); + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + const StringLiteral *Str, + const MemRegion *superRegion); public: + const StringLiteral *getStringLiteral() const { return Str; } - const StringLiteral* getStringLiteral() const { return Str; } - - QualType getValueType() const override { - return Str->getType(); - } + QualType getValueType() const override { return Str->getType(); } DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; @@ -817,7 +829,7 @@ public: class ObjCStringRegion : public TypedValueRegion { friend class MemRegionManager; - const ObjCStringLiteral* Str; + const ObjCStringLiteral *Str; ObjCStringRegion(const ObjCStringLiteral *str, const GlobalInternalSpaceRegion *sreg) @@ -825,17 +837,14 @@ class ObjCStringRegion : public TypedValueRegion { assert(str); } - static void ProfileRegion(llvm::FoldingSetNodeID& ID, - const ObjCStringLiteral* Str, - const MemRegion* superRegion); + static void ProfileRegion(llvm::FoldingSetNodeID &ID, + const ObjCStringLiteral *Str, + const MemRegion *superRegion); public: - - const ObjCStringLiteral* getObjCStringLiteral() const { return Str; } + const ObjCStringLiteral *getObjCStringLiteral() const { return Str; } - QualType getValueType() const override { - return Str->getType(); - } + QualType getValueType() const override { return Str->getType(); } bool isBoundable() const override { return false; } @@ -869,10 +878,9 @@ class CompoundLiteralRegion : public TypedValueRegion { static void ProfileRegion(llvm::FoldingSetNodeID& ID, const CompoundLiteralExpr *CL, const MemRegion* superRegion); + public: - QualType getValueType() const override { - return CL->getType(); - } + QualType getValueType() const override { return CL->getType(); } bool isBoundable() const override { return !CL->isFileScope(); } @@ -943,13 +951,13 @@ public: void dumpToStream(raw_ostream &os) const override; - static bool classof(const MemRegion* R) { - return R->getKind() == VarRegionKind; - } - bool canPrintPrettyAsExpr() const override; void printPrettyAsExpr(raw_ostream &os) const override; + + static bool classof(const MemRegion* R) { + return R->getKind() == VarRegionKind; + } }; /// CXXThisRegion - Represents the region for the implicit 'this' parameter @@ -961,7 +969,10 @@ class CXXThisRegion : public TypedValueRegion { CXXThisRegion(const PointerType *thisPointerTy, const StackArgumentsSpaceRegion *sReg) : TypedValueRegion(sReg, CXXThisRegionKind), - ThisPointerTy(thisPointerTy) {} + ThisPointerTy(thisPointerTy) { + assert(ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() && + "Invalid region type!"); + } static void ProfileRegion(llvm::FoldingSetNodeID &ID, const PointerType *PT, @@ -988,7 +999,7 @@ class FieldRegion : public DeclRegion { friend class MemRegionManager; FieldRegion(const FieldDecl *fd, const SubRegion* sReg) - : DeclRegion(fd, sReg, FieldRegionKind) {} + : DeclRegion(fd, sReg, FieldRegionKind) {} static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD, const MemRegion* superRegion) { @@ -1005,16 +1016,16 @@ public: DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override; - static bool classof(const MemRegion* R) { - return R->getKind() == FieldRegionKind; - } - void dumpToStream(raw_ostream &os) const override; bool canPrintPretty() const override; void printPretty(raw_ostream &os) const override; bool canPrintPrettyAsExpr() const override; void printPrettyAsExpr(raw_ostream &os) const override; + + static bool classof(const MemRegion* R) { + return R->getKind() == FieldRegionKind; + } }; class ObjCIvarRegion : public DeclRegion { @@ -1038,12 +1049,11 @@ public: return R->getKind() == ObjCIvarRegionKind; } }; + //===----------------------------------------------------------------------===// // Auxiliary data classes for use with MemRegions. //===----------------------------------------------------------------------===// -class ElementRegion; - class RegionRawOffset { friend class ElementRegion; @@ -1051,7 +1061,7 @@ class RegionRawOffset { CharUnits Offset; RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero()) - : Region(reg), Offset(offset) {} + : Region(reg), Offset(offset) {} public: // FIXME: Eventually support symbolic offsets. @@ -1062,7 +1072,7 @@ public: void dump() const; }; -/// \brief ElementRegin is used to represent both array elements and casts. +/// ElementRegin is used to represent both array elements and casts. class ElementRegion : public TypedValueRegion { friend class MemRegionManager; @@ -1070,27 +1080,25 @@ class ElementRegion : public TypedValueRegion { NonLoc Index; ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg) - : TypedValueRegion(sReg, ElementRegionKind), - ElementType(elementType), Index(Idx) { + : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType), + Index(Idx) { assert((!Idx.getAs<nonloc::ConcreteInt>() || Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) && "The index must be signed"); + assert(!elementType.isNull() && !elementType->isVoidType() && + "Invalid region type!"); } static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType, SVal Idx, const MemRegion* superRegion); public: - NonLoc getIndex() const { return Index; } - QualType getValueType() const override { - return ElementType; - } + QualType getValueType() const override { return ElementType; } + + QualType getElementType() const { return ElementType; } - QualType getElementType() const { - return ElementType; - } /// Compute the offset within the array. The array might also be a subobject. RegionRawOffset getAsArrayOffset() const; @@ -1122,9 +1130,7 @@ class CXXTempObjectRegion : public TypedValueRegion { public: const Expr *getExpr() const { return Ex; } - QualType getValueType() const override { - return Ex->getType(); - } + QualType getValueType() const override { return Ex->getType(); } void dumpToStream(raw_ostream &os) const override; @@ -1161,18 +1167,18 @@ public: void Profile(llvm::FoldingSetNodeID &ID) const override; - static bool classof(const MemRegion *region) { - return region->getKind() == CXXBaseObjectRegionKind; - } - bool canPrintPrettyAsExpr() const override; void printPrettyAsExpr(raw_ostream &os) const override; + + static bool classof(const MemRegion *region) { + return region->getKind() == CXXBaseObjectRegionKind; + } }; template<typename RegionTy> const RegionTy* MemRegion::getAs() const { - if (const RegionTy* RT = dyn_cast<RegionTy>(this)) + if (const auto *RT = dyn_cast<RegionTy>(this)) return RT; return nullptr; @@ -1187,11 +1193,10 @@ class MemRegionManager { llvm::BumpPtrAllocator& A; llvm::FoldingSet<MemRegion> Regions; - GlobalInternalSpaceRegion *InternalGlobals; - GlobalSystemSpaceRegion *SystemGlobals; - GlobalImmutableSpaceRegion *ImmutableGlobals; + GlobalInternalSpaceRegion *InternalGlobals = nullptr; + GlobalSystemSpaceRegion *SystemGlobals = nullptr; + GlobalImmutableSpaceRegion *ImmutableGlobals = nullptr; - llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *> StackLocalsSpaceRegions; llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *> @@ -1199,16 +1204,12 @@ class MemRegionManager { llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *> StaticsGlobalSpaceRegions; - HeapSpaceRegion *heap; - UnknownSpaceRegion *unknown; - CodeSpaceRegion *code; + HeapSpaceRegion *heap = nullptr; + UnknownSpaceRegion *unknown = nullptr; + CodeSpaceRegion *code = nullptr; public: - MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) - : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr), - ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr), - code(nullptr) {} - + MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : C(c), A(a) {} ~MemRegionManager(); ASTContext &getContext() { return C; } @@ -1256,13 +1257,13 @@ public: const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy, const LocationContext *LC); - /// \brief Retrieve or create a "symbolic" memory region. + /// Retrieve or create a "symbolic" memory region. const SymbolicRegion* getSymbolicRegion(SymbolRef Sym); - /// \brief Return a unique symbolic region belonging to heap memory space. + /// Return a unique symbolic region belonging to heap memory space. const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym); - const StringRegion *getStringRegion(const StringLiteral* Str); + const StringRegion *getStringRegion(const StringLiteral *Str); const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str); @@ -1381,24 +1382,28 @@ inline ASTContext &MemRegion::getContext() const { /// Information about invalidation for a particular region/symbol. class RegionAndSymbolInvalidationTraits { - typedef unsigned char StorageTypeForKinds; + using StorageTypeForKinds = unsigned char; + llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap; llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap; - typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator - const_region_iterator; - typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator - const_symbol_iterator; + using const_region_iterator = + llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator; + using const_symbol_iterator = + llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator; public: - /// \brief Describes different invalidation traits. + /// Describes different invalidation traits. enum InvalidationKinds { /// Tells that a region's contents is not changed. TK_PreserveContents = 0x1, + /// Suppress pointer-escaping of a region. TK_SuppressEscape = 0x2, + // Do not invalidate super region. TK_DoNotInvalidateSuperRegion = 0x4, + /// When applied to a MemSpaceRegion, indicates the entire memory space /// should be invalidated. TK_EntireMemSpace = 0x8 @@ -1416,8 +1421,7 @@ public: //===----------------------------------------------------------------------===// // Pretty-printing regions. //===----------------------------------------------------------------------===// -inline raw_ostream &operator<<(raw_ostream &os, - const clang::ento::MemRegion *R) { +inline raw_ostream &operator<<(raw_ostream &os, const MemRegion *R) { R->dumpToStream(os); return os; } @@ -1426,4 +1430,4 @@ inline raw_ostream &operator<<(raw_ostream &os, } // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h index dd2564b0a3c3e..17ab7379fdba9 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h @@ -177,20 +177,20 @@ public: /// /// This returns a new state with the added constraint on \p cond. /// If no new state is feasible, NULL is returned. - ProgramStateRef assume(DefinedOrUnknownSVal cond, bool assumption) const; + LLVM_NODISCARD ProgramStateRef assume(DefinedOrUnknownSVal cond, + bool assumption) const; /// Assumes both "true" and "false" for \p cond, and returns both /// corresponding states (respectively). /// /// This is more efficient than calling assume() twice. Note that one (but not /// both) of the returned states may be NULL. - std::pair<ProgramStateRef, ProgramStateRef> + LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef> assume(DefinedOrUnknownSVal cond) const; - ProgramStateRef assumeInBound(DefinedOrUnknownSVal idx, - DefinedOrUnknownSVal upperBound, - bool assumption, - QualType IndexType = QualType()) const; + LLVM_NODISCARD ProgramStateRef + assumeInBound(DefinedOrUnknownSVal idx, DefinedOrUnknownSVal upperBound, + bool assumption, QualType IndexType = QualType()) const; /// Assumes that the value of \p Val is bounded with [\p From; \p To] /// (if \p assumption is "true") or it is fully out of this range @@ -198,24 +198,31 @@ public: /// /// This returns a new state with the added constraint on \p cond. /// If no new state is feasible, NULL is returned. - ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, - const llvm::APSInt &From, - const llvm::APSInt &To, - bool assumption) const; + LLVM_NODISCARD ProgramStateRef assumeInclusiveRange(DefinedOrUnknownSVal Val, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool assumption) const; /// Assumes given range both "true" and "false" for \p Val, and returns both /// corresponding states (respectively). /// /// This is more efficient than calling assume() twice. Note that one (but not /// both) of the returned states may be NULL. - std::pair<ProgramStateRef, ProgramStateRef> + LLVM_NODISCARD std::pair<ProgramStateRef, ProgramStateRef> assumeInclusiveRange(DefinedOrUnknownSVal Val, const llvm::APSInt &From, const llvm::APSInt &To) const; - /// \brief Check if the given SVal is constrained to zero or is a zero + /// Check if the given SVal is not constrained to zero and is not + /// a zero constant. + ConditionTruthVal isNonNull(SVal V) const; + + /// Check if the given SVal is constrained to zero or is a zero /// constant. ConditionTruthVal isNull(SVal V) const; + /// \return Whether values \p Lhs and \p Rhs are equal. + ConditionTruthVal areEqual(SVal Lhs, SVal Rhs) const; + /// Utility method for getting regions. const VarRegion* getRegion(const VarDecl *D, const LocationContext *LC) const; @@ -225,21 +232,34 @@ public: /// Create a new state by binding the value 'V' to the statement 'S' in the /// state's environment. - ProgramStateRef BindExpr(const Stmt *S, const LocationContext *LCtx, - SVal V, bool Invalidate = true) const; - - ProgramStateRef bindLoc(Loc location, - SVal V, - const LocationContext *LCtx, - bool notifyChanges = true) const; - - ProgramStateRef bindLoc(SVal location, SVal V, const LocationContext *LCtx) const; - - ProgramStateRef bindDefault(SVal loc, SVal V, const LocationContext *LCtx) const; - - ProgramStateRef killBinding(Loc LV) const; - - /// \brief Returns the state with bindings for the given regions + LLVM_NODISCARD ProgramStateRef BindExpr(const Stmt *S, + const LocationContext *LCtx, SVal V, + bool Invalidate = true) const; + + LLVM_NODISCARD ProgramStateRef bindLoc(Loc location, SVal V, + const LocationContext *LCtx, + bool notifyChanges = true) const; + + LLVM_NODISCARD ProgramStateRef bindLoc(SVal location, SVal V, + const LocationContext *LCtx) const; + + /// Initializes the region of memory represented by \p loc with an initial + /// value. Once initialized, all values loaded from any sub-regions of that + /// region will be equal to \p V, unless overwritten later by the program. + /// This method should not be used on regions that are already initialized. + /// If you need to indicate that memory contents have suddenly become unknown + /// within a certain region of memory, consider invalidateRegions(). + LLVM_NODISCARD ProgramStateRef + bindDefaultInitial(SVal loc, SVal V, const LocationContext *LCtx) const; + + /// Performs C++ zero-initialization procedure on the region of memory + /// represented by \p loc. + LLVM_NODISCARD ProgramStateRef + bindDefaultZero(SVal loc, const LocationContext *LCtx) const; + + LLVM_NODISCARD ProgramStateRef killBinding(Loc LV) const; + + /// Returns the state with bindings for the given regions /// cleared from the store. /// /// Optionally invalidates global regions as well. @@ -257,14 +277,14 @@ public: /// the call and should be considered directly invalidated. /// \param ITraits information about special handling for a particular /// region/symbol. - ProgramStateRef + LLVM_NODISCARD ProgramStateRef invalidateRegions(ArrayRef<const MemRegion *> Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, const CallEvent *Call = nullptr, RegionAndSymbolInvalidationTraits *ITraits = nullptr) const; - ProgramStateRef + LLVM_NODISCARD ProgramStateRef invalidateRegions(ArrayRef<SVal> Regions, const Expr *E, unsigned BlockCount, const LocationContext *LCtx, bool CausesPointerEscape, InvalidatedSymbols *IS = nullptr, @@ -273,8 +293,15 @@ public: /// enterStackFrame - Returns the state for entry to the given stack frame, /// preserving the current state. - ProgramStateRef enterStackFrame(const CallEvent &Call, - const StackFrameContext *CalleeCtx) const; + LLVM_NODISCARD ProgramStateRef enterStackFrame( + const CallEvent &Call, const StackFrameContext *CalleeCtx) const; + + /// Get the lvalue for a base class object reference. + Loc getLValue(const CXXBaseSpecifier &BaseSpec, const SubRegion *Super) const; + + /// Get the lvalue for a base class object reference. + Loc getLValue(const CXXRecordDecl *BaseClass, const SubRegion *Super, + bool IsVirtual) const; /// Get the lvalue for a variable reference. Loc getLValue(const VarDecl *D, const LocationContext *LC) const; @@ -299,24 +326,24 @@ public: SVal getSValAsScalarOrLoc(const Stmt *Ex, const LocationContext *LCtx) const; - /// \brief Return the value bound to the specified location. + /// Return the value bound to the specified location. /// Returns UnknownVal() if none found. SVal getSVal(Loc LV, QualType T = QualType()) const; /// Returns the "raw" SVal bound to LV before any value simplfication. SVal getRawSVal(Loc LV, QualType T= QualType()) const; - /// \brief Return the value bound to the specified location. + /// Return the value bound to the specified location. /// Returns UnknownVal() if none found. SVal getSVal(const MemRegion* R, QualType T = QualType()) const; - /// \brief Return the value bound to the specified location, assuming + /// Return the value bound to the specified location, assuming /// that the value is a scalar integer or an enumeration or a pointer. /// Returns UnknownVal() if none found or the region is not known to hold /// a value of such type. SVal getSValAsScalarOrLoc(const MemRegion *R) const; - /// \brief Visits the symbols reachable from the given SVal using the provided + /// Visits the symbols reachable from the given SVal using the provided /// SymbolVisitor. /// /// This is a convenience API. Consider using ScanReachableSymbols class @@ -325,12 +352,12 @@ public: /// \sa ScanReachableSymbols bool scanReachableSymbols(SVal val, SymbolVisitor& visitor) const; - /// \brief Visits the symbols reachable from the SVals in the given range + /// Visits the symbols reachable from the SVals in the given range /// using the provided SymbolVisitor. bool scanReachableSymbols(const SVal *I, const SVal *E, SymbolVisitor &visitor) const; - /// \brief Visits the symbols reachable from the regions in the given + /// Visits the symbols reachable from the regions in the given /// MemRegions range using the provided SymbolVisitor. bool scanReachableSymbols(const MemRegion * const *I, const MemRegion * const *E, @@ -345,27 +372,29 @@ public: const MemRegion * const *end) const; /// Create a new state in which the statement is marked as tainted. - ProgramStateRef addTaint(const Stmt *S, const LocationContext *LCtx, - TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addTaint(const Stmt *S, const LocationContext *LCtx, + TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in which the value is marked as tainted. - ProgramStateRef addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addTaint(SVal V, TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in which the symbol is marked as tainted. - ProgramStateRef addTaint(SymbolRef S, + LLVM_NODISCARD ProgramStateRef addTaint(SymbolRef S, TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in which the region symbol is marked as tainted. - ProgramStateRef addTaint(const MemRegion *R, - TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addTaint(const MemRegion *R, TaintTagType Kind = TaintTagGeneric) const; /// Create a new state in a which a sub-region of a given symbol is tainted. /// This might be necessary when referring to regions that can not have an /// individual symbol, e.g. if they are represented by the default binding of /// a LazyCompoundVal. - ProgramStateRef addPartialTaint(SymbolRef ParentSym, - const SubRegion *SubRegion, - TaintTagType Kind = TaintTagGeneric) const; + LLVM_NODISCARD ProgramStateRef + addPartialTaint(SymbolRef ParentSym, const SubRegion *SubRegion, + TaintTagType Kind = TaintTagGeneric) const; /// Check if the statement is tainted in the current state. bool isTainted(const Stmt *S, const LocationContext *LCtx, @@ -380,8 +409,9 @@ public: void *const* FindGDM(void *K) const; - template<typename T> - ProgramStateRef add(typename ProgramStateTrait<T>::key_type K) const; + template <typename T> + LLVM_NODISCARD ProgramStateRef + add(typename ProgramStateTrait<T>::key_type K) const; template <typename T> typename ProgramStateTrait<T>::data_type @@ -399,27 +429,31 @@ public: template <typename T> typename ProgramStateTrait<T>::context_type get_context() const; + template <typename T> + LLVM_NODISCARD ProgramStateRef + remove(typename ProgramStateTrait<T>::key_type K) const; - template<typename T> - ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K) const; - - template<typename T> - ProgramStateRef remove(typename ProgramStateTrait<T>::key_type K, - typename ProgramStateTrait<T>::context_type C) const; template <typename T> - ProgramStateRef remove() const; + LLVM_NODISCARD ProgramStateRef + remove(typename ProgramStateTrait<T>::key_type K, + typename ProgramStateTrait<T>::context_type C) const; - template<typename T> - ProgramStateRef set(typename ProgramStateTrait<T>::data_type D) const; + template <typename T> LLVM_NODISCARD ProgramStateRef remove() const; - template<typename T> - ProgramStateRef set(typename ProgramStateTrait<T>::key_type K, - typename ProgramStateTrait<T>::value_type E) const; + template <typename T> + LLVM_NODISCARD ProgramStateRef + set(typename ProgramStateTrait<T>::data_type D) const; - template<typename T> - ProgramStateRef set(typename ProgramStateTrait<T>::key_type K, - typename ProgramStateTrait<T>::value_type E, - typename ProgramStateTrait<T>::context_type C) const; + template <typename T> + LLVM_NODISCARD ProgramStateRef + set(typename ProgramStateTrait<T>::key_type K, + typename ProgramStateTrait<T>::value_type E) const; + + template <typename T> + LLVM_NODISCARD ProgramStateRef + set(typename ProgramStateTrait<T>::key_type K, + typename ProgramStateTrait<T>::value_type E, + typename ProgramStateTrait<T>::context_type C) const; template<typename T> bool contains(typename ProgramStateTrait<T>::key_type key) const { @@ -428,9 +462,10 @@ public: } // Pretty-printing. - void print(raw_ostream &Out, const char *nl = "\n", - const char *sep = "") const; - void printDOT(raw_ostream &Out) const; + void print(raw_ostream &Out, const char *nl = "\n", const char *sep = "", + const LocationContext *CurrentLC = nullptr) const; + void printDOT(raw_ostream &Out, + const LocationContext *CurrentLC = nullptr) const; void printTaint(raw_ostream &Out, const char *nl = "\n", const char *sep = "") const; @@ -705,6 +740,22 @@ inline ProgramStateRef ProgramState::bindLoc(SVal LV, SVal V, const LocationCont return this; } +inline Loc ProgramState::getLValue(const CXXBaseSpecifier &BaseSpec, + const SubRegion *Super) const { + const auto *Base = BaseSpec.getType()->getAsCXXRecordDecl(); + return loc::MemRegionVal( + getStateManager().getRegionManager().getCXXBaseObjectRegion( + Base, Super, BaseSpec.isVirtual())); +} + +inline Loc ProgramState::getLValue(const CXXRecordDecl *BaseClass, + const SubRegion *Super, + bool IsVirtual) const { + return loc::MemRegionVal( + getStateManager().getRegionManager().getCXXBaseObjectRegion( + BaseClass, Super, IsVirtual)); +} + inline Loc ProgramState::getLValue(const VarDecl *VD, const LocationContext *LC) const { return getStateManager().StoreMgr->getLValueVar(VD, LC); diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h index a04fa90059555..5555b292534c5 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h @@ -14,33 +14,28 @@ // //===----------------------------------------------------------------------===// - #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H +#include "llvm/ADT/ImmutableList.h" +#include "llvm/ADT/ImmutableMap.h" +#include "llvm/ADT/ImmutableSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" - -namespace llvm { - template <typename K, typename D, typename I> class ImmutableMap; - template <typename K, typename I> class ImmutableSet; - template <typename T> class ImmutableList; - template <typename T> class ImmutableListImpl; -} +#include <cstdint> namespace clang { - namespace ento { + template <typename T> struct ProgramStatePartialTrait; /// Declares a program state trait for type \p Type called \p Name, and - /// introduce a typedef named \c NameTy. + /// introduce a type named \c NameTy. /// The macro should not be used inside namespaces, or for traits that must /// be accessible from more than one translation unit. #define REGISTER_TRAIT_WITH_PROGRAMSTATE(Name, Type) \ namespace { \ class Name {}; \ - typedef Type Name ## Ty; \ + using Name ## Ty = Type; \ } \ namespace clang { \ namespace ento { \ @@ -52,28 +47,30 @@ namespace ento { } \ } - // Partial-specialization for ImmutableMap. - template <typename Key, typename Data, typename Info> - struct ProgramStatePartialTrait< llvm::ImmutableMap<Key,Data,Info> > { - typedef llvm::ImmutableMap<Key,Data,Info> data_type; - typedef typename data_type::Factory& context_type; - typedef Key key_type; - typedef Data value_type; - typedef const value_type* lookup_type; - - static inline data_type MakeData(void *const* p) { - return p ? data_type((typename data_type::TreeTy*) *p) + struct ProgramStatePartialTrait<llvm::ImmutableMap<Key, Data, Info>> { + using data_type = llvm::ImmutableMap<Key, Data, Info>; + using context_type = typename data_type::Factory &; + using key_type = Key; + using value_type = Data; + using lookup_type = const value_type *; + + static data_type MakeData(void *const *p) { + return p ? data_type((typename data_type::TreeTy *) *p) : data_type(nullptr); } - static inline void *MakeVoidPtr(data_type B) { + + static void *MakeVoidPtr(data_type B) { return B.getRoot(); } + static lookup_type Lookup(data_type B, key_type K) { return B.lookup(K); } - static data_type Set(data_type B, key_type K, value_type E,context_type F){ + + static data_type Set(data_type B, key_type K, value_type E, + context_type F) { return F.add(B, K, E); } @@ -85,8 +82,8 @@ namespace ento { return B.contains(K); } - static inline context_type MakeContext(void *p) { - return *((typename data_type::Factory*) p); + static context_type MakeContext(void *p) { + return *((typename data_type::Factory *) p); } static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { @@ -94,7 +91,7 @@ namespace ento { } static void DeleteContext(void *Ctx) { - delete (typename data_type::Factory*) Ctx; + delete (typename data_type::Factory *) Ctx; } }; @@ -107,21 +104,19 @@ namespace ento { /// can deal with. #define CLANG_ENTO_PROGRAMSTATE_MAP(Key, Value) llvm::ImmutableMap<Key, Value> - // Partial-specialization for ImmutableSet. - template <typename Key, typename Info> - struct ProgramStatePartialTrait< llvm::ImmutableSet<Key,Info> > { - typedef llvm::ImmutableSet<Key,Info> data_type; - typedef typename data_type::Factory& context_type; - typedef Key key_type; + struct ProgramStatePartialTrait<llvm::ImmutableSet<Key, Info>> { + using data_type = llvm::ImmutableSet<Key, Info>; + using context_type = typename data_type::Factory &; + using key_type = Key; - static inline data_type MakeData(void *const* p) { - return p ? data_type((typename data_type::TreeTy*) *p) + static data_type MakeData(void *const *p) { + return p ? data_type((typename data_type::TreeTy *) *p) : data_type(nullptr); } - static inline void *MakeVoidPtr(data_type B) { + static void *MakeVoidPtr(data_type B) { return B.getRoot(); } @@ -137,27 +132,25 @@ namespace ento { return B.contains(K); } - static inline context_type MakeContext(void *p) { - return *((typename data_type::Factory*) p); + static context_type MakeContext(void *p) { + return *((typename data_type::Factory *) p); } - static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { + static void *CreateContext(llvm::BumpPtrAllocator &Alloc) { return new typename data_type::Factory(Alloc); } static void DeleteContext(void *Ctx) { - delete (typename data_type::Factory*) Ctx; + delete (typename data_type::Factory *) Ctx; } }; - // Partial-specialization for ImmutableList. - template <typename T> - struct ProgramStatePartialTrait< llvm::ImmutableList<T> > { - typedef llvm::ImmutableList<T> data_type; - typedef T key_type; - typedef typename data_type::Factory& context_type; + struct ProgramStatePartialTrait<llvm::ImmutableList<T>> { + using data_type = llvm::ImmutableList<T>; + using key_type = T; + using context_type = typename data_type::Factory &; static data_type Add(data_type L, key_type K, context_type F) { return F.add(K, L); @@ -167,83 +160,84 @@ namespace ento { return L.contains(K); } - static inline data_type MakeData(void *const* p) { - return p ? data_type((const llvm::ImmutableListImpl<T>*) *p) + static data_type MakeData(void *const *p) { + return p ? data_type((const llvm::ImmutableListImpl<T> *) *p) : data_type(nullptr); } - static inline void *MakeVoidPtr(data_type D) { + static void *MakeVoidPtr(data_type D) { return const_cast<llvm::ImmutableListImpl<T> *>(D.getInternalPointer()); } - static inline context_type MakeContext(void *p) { - return *((typename data_type::Factory*) p); + static context_type MakeContext(void *p) { + return *((typename data_type::Factory *) p); } - static void *CreateContext(llvm::BumpPtrAllocator& Alloc) { + static void *CreateContext(llvm::BumpPtrAllocator &Alloc) { return new typename data_type::Factory(Alloc); } static void DeleteContext(void *Ctx) { - delete (typename data_type::Factory*) Ctx; + delete (typename data_type::Factory *) Ctx; } }; - // Partial specialization for bool. template <> struct ProgramStatePartialTrait<bool> { - typedef bool data_type; + using data_type = bool; - static inline data_type MakeData(void *const* p) { + static data_type MakeData(void *const *p) { return p ? (data_type) (uintptr_t) *p : data_type(); } - static inline void *MakeVoidPtr(data_type d) { - return (void*) (uintptr_t) d; + + static void *MakeVoidPtr(data_type d) { + return (void *) (uintptr_t) d; } }; // Partial specialization for unsigned. template <> struct ProgramStatePartialTrait<unsigned> { - typedef unsigned data_type; + using data_type = unsigned; - static inline data_type MakeData(void *const* p) { + static data_type MakeData(void *const *p) { return p ? (data_type) (uintptr_t) *p : data_type(); } - static inline void *MakeVoidPtr(data_type d) { - return (void*) (uintptr_t) d; + + static void *MakeVoidPtr(data_type d) { + return (void *) (uintptr_t) d; } }; // Partial specialization for void*. - template <> struct ProgramStatePartialTrait<void*> { - typedef void *data_type; + template <> struct ProgramStatePartialTrait<void *> { + using data_type = void *; - static inline data_type MakeData(void *const* p) { + static data_type MakeData(void *const *p) { return p ? *p : data_type(); } - static inline void *MakeVoidPtr(data_type d) { + + static void *MakeVoidPtr(data_type d) { return d; } }; // Partial specialization for const void *. template <> struct ProgramStatePartialTrait<const void *> { - typedef const void *data_type; + using data_type = const void *; - static inline data_type MakeData(void * const *p) { + static data_type MakeData(void *const *p) { return p ? *p : data_type(); } - static inline void *MakeVoidPtr(data_type d) { + static void *MakeVoidPtr(data_type d) { return const_cast<void *>(d); } }; -} // end ento namespace - -} // end clang namespace +} // namespace ento +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_PROGRAMSTATETRAIT_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h new file mode 100644 index 0000000000000..d2ba1f7c9529a --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h @@ -0,0 +1,216 @@ +//== RangedConstraintManager.h ----------------------------------*- C++ -*--==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Ranged constraint manager, built on SimpleConstraintManager. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_STATICANALYZER_CORE_RANGEDCONSTRAINTMANAGER_H +#define LLVM_CLANG_LIB_STATICANALYZER_CORE_RANGEDCONSTRAINTMANAGER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h" + +namespace clang { + +namespace ento { + +/// A Range represents the closed range [from, to]. The caller must +/// guarantee that from <= to. Note that Range is immutable, so as not +/// to subvert RangeSet's immutability. +class Range : public std::pair<const llvm::APSInt *, const llvm::APSInt *> { +public: + Range(const llvm::APSInt &from, const llvm::APSInt &to) + : std::pair<const llvm::APSInt *, const llvm::APSInt *>(&from, &to) { + assert(from <= to); + } + bool Includes(const llvm::APSInt &v) const { + return *first <= v && v <= *second; + } + const llvm::APSInt &From() const { return *first; } + const llvm::APSInt &To() const { return *second; } + const llvm::APSInt *getConcreteValue() const { + return &From() == &To() ? &From() : nullptr; + } + + void Profile(llvm::FoldingSetNodeID &ID) const { + ID.AddPointer(&From()); + ID.AddPointer(&To()); + } +}; + +class RangeTrait : public llvm::ImutContainerInfo<Range> { +public: + // When comparing if one Range is less than another, we should compare + // the actual APSInt values instead of their pointers. This keeps the order + // consistent (instead of comparing by pointer values) and can potentially + // be used to speed up some of the operations in RangeSet. + static inline bool isLess(key_type_ref lhs, key_type_ref rhs) { + return *lhs.first < *rhs.first || + (!(*rhs.first < *lhs.first) && *lhs.second < *rhs.second); + } +}; + +/// RangeSet contains a set of ranges. If the set is empty, then +/// there the value of a symbol is overly constrained and there are no +/// possible values for that symbol. +class RangeSet { + typedef llvm::ImmutableSet<Range, RangeTrait> PrimRangeSet; + PrimRangeSet ranges; // no need to make const, since it is an + // ImmutableSet - this allows default operator= + // to work. +public: + typedef PrimRangeSet::Factory Factory; + typedef PrimRangeSet::iterator iterator; + + RangeSet(PrimRangeSet RS) : ranges(RS) {} + + /// Create a new set with all ranges of this set and RS. + /// Possible intersections are not checked here. + RangeSet addRange(Factory &F, const RangeSet &RS) { + PrimRangeSet Ranges(RS.ranges); + for (const auto &range : ranges) + Ranges = F.add(Ranges, range); + return RangeSet(Ranges); + } + + iterator begin() const { return ranges.begin(); } + iterator end() const { return ranges.end(); } + + bool isEmpty() const { return ranges.isEmpty(); } + + /// Construct a new RangeSet representing '{ [from, to] }'. + RangeSet(Factory &F, const llvm::APSInt &from, const llvm::APSInt &to) + : ranges(F.add(F.getEmptySet(), Range(from, to))) {} + + /// Profile - Generates a hash profile of this RangeSet for use + /// by FoldingSet. + void Profile(llvm::FoldingSetNodeID &ID) const { ranges.Profile(ID); } + + /// getConcreteValue - If a symbol is contrained to equal a specific integer + /// constant then this method returns that value. Otherwise, it returns + /// NULL. + const llvm::APSInt *getConcreteValue() const { + return ranges.isSingleton() ? ranges.begin()->getConcreteValue() : nullptr; + } + +private: + void IntersectInRange(BasicValueFactory &BV, Factory &F, + const llvm::APSInt &Lower, const llvm::APSInt &Upper, + PrimRangeSet &newRanges, PrimRangeSet::iterator &i, + PrimRangeSet::iterator &e) const; + + const llvm::APSInt &getMinValue() const; + + bool pin(llvm::APSInt &Lower, llvm::APSInt &Upper) const; + +public: + RangeSet Intersect(BasicValueFactory &BV, Factory &F, llvm::APSInt Lower, + llvm::APSInt Upper) const; + + RangeSet Negate(BasicValueFactory &BV, Factory &F) const; + + void print(raw_ostream &os) const; + + bool operator==(const RangeSet &other) const { + return ranges == other.ranges; + } +}; + + +class ConstraintRange {}; +using ConstraintRangeTy = llvm::ImmutableMap<SymbolRef, RangeSet>; + +template <> +struct ProgramStateTrait<ConstraintRange> + : public ProgramStatePartialTrait<ConstraintRangeTy> { + static void *GDMIndex() { static int Index; return &Index; } +}; + + +class RangedConstraintManager : public SimpleConstraintManager { +public: + RangedConstraintManager(SubEngine *SE, SValBuilder &SB) + : SimpleConstraintManager(SE, SB) {} + + ~RangedConstraintManager() override; + + //===------------------------------------------------------------------===// + // Implementation for interface from SimpleConstraintManager. + //===------------------------------------------------------------------===// + + ProgramStateRef assumeSym(ProgramStateRef State, SymbolRef Sym, + bool Assumption) override; + + ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) override; + + ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, + bool Assumption) override; + +protected: + /// Assume a constraint between a symbolic expression and a concrete integer. + virtual ProgramStateRef assumeSymRel(ProgramStateRef State, SymbolRef Sym, + BinaryOperator::Opcode op, + const llvm::APSInt &Int); + + //===------------------------------------------------------------------===// + // Interface that subclasses must implement. + //===------------------------------------------------------------------===// + + // Each of these is of the form "$Sym+Adj <> V", where "<>" is the comparison + // operation for the method being invoked. + + virtual ProgramStateRef assumeSymNE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymEQ(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymLT(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymGT(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymLE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymGE(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &V, + const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymWithinInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0; + + virtual ProgramStateRef assumeSymOutsideInclusiveRange( + ProgramStateRef State, SymbolRef Sym, const llvm::APSInt &From, + const llvm::APSInt &To, const llvm::APSInt &Adjustment) = 0; + + //===------------------------------------------------------------------===// + // Internal implementation. + //===------------------------------------------------------------------===// +private: + static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment); +}; + +} // end GR namespace + +} // end clang namespace + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h new file mode 100644 index 0000000000000..19d3d5973e0fd --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTConstraintManager.h @@ -0,0 +1,77 @@ +//== SMTConstraintManager.h -------------------------------------*- 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 a SMT generic API, which will be the base class for +// every SMT solver specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONSTRAINTMANAGER_H + +#include "clang/StaticAnalyzer/Core/PathSensitive/RangedConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h" + +namespace clang { +namespace ento { + +class SMTConstraintManager : public clang::ento::SimpleConstraintManager { + SMTSolverRef &Solver; + +public: + SMTConstraintManager(clang::ento::SubEngine *SE, clang::ento::SValBuilder &SB, + SMTSolverRef &S) + : SimpleConstraintManager(SE, SB), Solver(S) {} + virtual ~SMTConstraintManager() = default; + + //===------------------------------------------------------------------===// + // Implementation for interface from SimpleConstraintManager. + //===------------------------------------------------------------------===// + + ProgramStateRef assumeSym(ProgramStateRef state, SymbolRef Sym, + bool Assumption) override; + + ProgramStateRef assumeSymInclusiveRange(ProgramStateRef State, SymbolRef Sym, + const llvm::APSInt &From, + const llvm::APSInt &To, + bool InRange) override; + + ProgramStateRef assumeSymUnsupported(ProgramStateRef State, SymbolRef Sym, + bool Assumption) override; + + //===------------------------------------------------------------------===// + // Implementation for interface from ConstraintManager. + //===------------------------------------------------------------------===// + + ConditionTruthVal checkNull(ProgramStateRef State, SymbolRef Sym) override; + + const llvm::APSInt *getSymVal(ProgramStateRef State, + SymbolRef Sym) const override; + + /// Dumps SMT formula + LLVM_DUMP_METHOD void dump() const { Solver->dump(); } + +protected: + // Check whether a new model is satisfiable, and update the program state. + virtual ProgramStateRef assumeExpr(ProgramStateRef State, SymbolRef Sym, + const SMTExprRef &Exp) = 0; + + /// Given a program state, construct the logical conjunction and add it to + /// the solver + virtual void addStateConstraints(ProgramStateRef State) const = 0; + + // Generate and check a Z3 model, using the given constraint. + ConditionTruthVal checkModel(ProgramStateRef State, + const SMTExprRef &Exp) const; +}; // end class SMTConstraintManager + +} // namespace ento +} // namespace clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h new file mode 100644 index 0000000000000..45c9df4ef4019 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTContext.h @@ -0,0 +1,31 @@ +//== SMTContext.h -----------------------------------------------*- 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 a SMT generic Context API, which will be the base class +// for every SMT solver context specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTCONTEXT_H + +namespace clang { +namespace ento { + +/// Generic base class for SMT contexts +class SMTContext { +public: + SMTContext() = default; + virtual ~SMTContext() = default; +}; + +} // namespace ento +} // namespace clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h new file mode 100644 index 0000000000000..9dedf96cfaf83 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h @@ -0,0 +1,62 @@ +//== SMTExpr.h --------------------------------------------------*- 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 a SMT generic Expr API, which will be the base class +// for every SMT solver expr specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTEXPR_H + +#include "clang/Basic/TargetInfo.h" +#include "llvm/ADT/FoldingSet.h" + +namespace clang { +namespace ento { + +/// Generic base class for SMT exprs +class SMTExpr { +public: + SMTExpr() = default; + virtual ~SMTExpr() = default; + + bool operator<(const SMTExpr &Other) const { + llvm::FoldingSetNodeID ID1, ID2; + Profile(ID1); + Other.Profile(ID2); + return ID1 < ID2; + } + + virtual void Profile(llvm::FoldingSetNodeID &ID) const { + static int Tag = 0; + ID.AddPointer(&Tag); + } + + friend bool operator==(SMTExpr const &LHS, SMTExpr const &RHS) { + return LHS.equal_to(RHS); + } + + virtual void print(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + +protected: + /// Query the SMT solver and returns true if two sorts are equal (same kind + /// and bit width). This does not check if the two sorts are the same objects. + virtual bool equal_to(SMTExpr const &other) const = 0; +}; + +/// Shared pointer for SMTExprs, used by SMTSolver API. +using SMTExprRef = std::shared_ptr<SMTExpr>; + +} // namespace ento +} // namespace clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h new file mode 100644 index 0000000000000..a43ca486901bc --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSolver.h @@ -0,0 +1,996 @@ +//== SMTSolver.h ------------------------------------------------*- 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 a SMT generic Solver API, which will be the base class +// for every SMT solver specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSOLVER_H + +#include "clang/AST/Expr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ConstraintManager.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTExpr.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" + +namespace clang { +namespace ento { + +/// Generic base class for SMT Solvers +/// +/// This class is responsible for wrapping all sorts and expression generation, +/// through the mk* methods. It also provides methods to create SMT expressions +/// straight from clang's AST, through the from* methods. +class SMTSolver { +public: + SMTSolver() = default; + virtual ~SMTSolver() = default; + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + + // Returns an appropriate floating-point sort for the given bitwidth. + SMTSortRef getFloatSort(unsigned BitWidth) { + switch (BitWidth) { + case 16: + return getFloat16Sort(); + case 32: + return getFloat32Sort(); + case 64: + return getFloat64Sort(); + case 128: + return getFloat128Sort(); + default:; + } + llvm_unreachable("Unsupported floating-point bitwidth!"); + } + + // Returns an appropriate sort, given a QualType and it's bit width. + SMTSortRef mkSort(const QualType &Ty, unsigned BitWidth) { + if (Ty->isBooleanType()) + return getBoolSort(); + + if (Ty->isRealFloatingType()) + return getFloatSort(BitWidth); + + return getBitvectorSort(BitWidth); + } + + /// Constructs an SMTExprRef from an unary operator. + SMTExprRef fromUnOp(const UnaryOperator::Opcode Op, const SMTExprRef &Exp) { + switch (Op) { + case UO_Minus: + return mkBVNeg(Exp); + + case UO_Not: + return mkBVNot(Exp); + + case UO_LNot: + return mkNot(Exp); + + default:; + } + llvm_unreachable("Unimplemented opcode"); + } + + /// Constructs an SMTExprRef from a floating-point unary operator. + SMTExprRef fromFloatUnOp(const UnaryOperator::Opcode Op, + const SMTExprRef &Exp) { + switch (Op) { + case UO_Minus: + return mkFPNeg(Exp); + + case UO_LNot: + return fromUnOp(Op, Exp); + + default:; + } + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct an SMTExprRef from a n-ary binary operator. + SMTExprRef fromNBinOp(const BinaryOperator::Opcode Op, + const std::vector<SMTExprRef> &ASTs) { + assert(!ASTs.empty()); + + if (Op != BO_LAnd && Op != BO_LOr) + llvm_unreachable("Unimplemented opcode"); + + SMTExprRef res = ASTs.front(); + for (std::size_t i = 1; i < ASTs.size(); ++i) + res = (Op == BO_LAnd) ? mkAnd(res, ASTs[i]) : mkOr(res, ASTs[i]); + return res; + } + + /// Construct an SMTExprRef from a binary operator. + SMTExprRef fromBinOp(const SMTExprRef &LHS, const BinaryOperator::Opcode Op, + const SMTExprRef &RHS, bool isSigned) { + assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!"); + + switch (Op) { + // Multiplicative operators + case BO_Mul: + return mkBVMul(LHS, RHS); + + case BO_Div: + return isSigned ? mkBVSDiv(LHS, RHS) : mkBVUDiv(LHS, RHS); + + case BO_Rem: + return isSigned ? mkBVSRem(LHS, RHS) : mkBVURem(LHS, RHS); + + // Additive operators + case BO_Add: + return mkBVAdd(LHS, RHS); + + case BO_Sub: + return mkBVSub(LHS, RHS); + + // Bitwise shift operators + case BO_Shl: + return mkBVShl(LHS, RHS); + + case BO_Shr: + return isSigned ? mkBVAshr(LHS, RHS) : mkBVLshr(LHS, RHS); + + // Relational operators + case BO_LT: + return isSigned ? mkBVSlt(LHS, RHS) : mkBVUlt(LHS, RHS); + + case BO_GT: + return isSigned ? mkBVSgt(LHS, RHS) : mkBVUgt(LHS, RHS); + + case BO_LE: + return isSigned ? mkBVSle(LHS, RHS) : mkBVUle(LHS, RHS); + + case BO_GE: + return isSigned ? mkBVSge(LHS, RHS) : mkBVUge(LHS, RHS); + + // Equality operators + case BO_EQ: + return mkEqual(LHS, RHS); + + case BO_NE: + return fromUnOp(UO_LNot, fromBinOp(LHS, BO_EQ, RHS, isSigned)); + + // Bitwise operators + case BO_And: + return mkBVAnd(LHS, RHS); + + case BO_Xor: + return mkBVXor(LHS, RHS); + + case BO_Or: + return mkBVOr(LHS, RHS); + + // Logical operators + case BO_LAnd: + return mkAnd(LHS, RHS); + + case BO_LOr: + return mkOr(LHS, RHS); + + default:; + } + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct an SMTExprRef from a special floating-point binary operator. + SMTExprRef fromFloatSpecialBinOp(const SMTExprRef &LHS, + const BinaryOperator::Opcode Op, + const llvm::APFloat::fltCategory &RHS) { + switch (Op) { + // Equality operators + case BO_EQ: + switch (RHS) { + case llvm::APFloat::fcInfinity: + return mkFPIsInfinite(LHS); + + case llvm::APFloat::fcNaN: + return mkFPIsNaN(LHS); + + case llvm::APFloat::fcNormal: + return mkFPIsNormal(LHS); + + case llvm::APFloat::fcZero: + return mkFPIsZero(LHS); + } + break; + + case BO_NE: + return fromFloatUnOp(UO_LNot, fromFloatSpecialBinOp(LHS, BO_EQ, RHS)); + + default:; + } + + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct an SMTExprRef from a floating-point binary operator. + SMTExprRef fromFloatBinOp(const SMTExprRef &LHS, + const BinaryOperator::Opcode Op, + const SMTExprRef &RHS) { + assert(*getSort(LHS) == *getSort(RHS) && "AST's must have the same sort!"); + + switch (Op) { + // Multiplicative operators + case BO_Mul: + return mkFPMul(LHS, RHS); + + case BO_Div: + return mkFPDiv(LHS, RHS); + + case BO_Rem: + return mkFPRem(LHS, RHS); + + // Additive operators + case BO_Add: + return mkFPAdd(LHS, RHS); + + case BO_Sub: + return mkFPSub(LHS, RHS); + + // Relational operators + case BO_LT: + return mkFPLt(LHS, RHS); + + case BO_GT: + return mkFPGt(LHS, RHS); + + case BO_LE: + return mkFPLe(LHS, RHS); + + case BO_GE: + return mkFPGe(LHS, RHS); + + // Equality operators + case BO_EQ: + return mkFPEqual(LHS, RHS); + + case BO_NE: + return fromFloatUnOp(UO_LNot, fromFloatBinOp(LHS, BO_EQ, RHS)); + + // Logical operators + case BO_LAnd: + case BO_LOr: + return fromBinOp(LHS, Op, RHS, false); + + default:; + } + + llvm_unreachable("Unimplemented opcode"); + } + + /// Construct an SMTExprRef from a QualType FromTy to a QualType ToTy, and + /// their bit widths. + SMTExprRef fromCast(const SMTExprRef &Exp, QualType ToTy, uint64_t ToBitWidth, + QualType FromTy, uint64_t FromBitWidth) { + if ((FromTy->isIntegralOrEnumerationType() && + ToTy->isIntegralOrEnumerationType()) || + (FromTy->isAnyPointerType() ^ ToTy->isAnyPointerType()) || + (FromTy->isBlockPointerType() ^ ToTy->isBlockPointerType()) || + (FromTy->isReferenceType() ^ ToTy->isReferenceType())) { + + if (FromTy->isBooleanType()) { + assert(ToBitWidth > 0 && "BitWidth must be positive!"); + return mkIte(Exp, mkBitvector(llvm::APSInt("1"), ToBitWidth), + mkBitvector(llvm::APSInt("0"), ToBitWidth)); + } + + if (ToBitWidth > FromBitWidth) + return FromTy->isSignedIntegerOrEnumerationType() + ? mkBVSignExt(ToBitWidth - FromBitWidth, Exp) + : mkBVZeroExt(ToBitWidth - FromBitWidth, Exp); + + if (ToBitWidth < FromBitWidth) + return mkBVExtract(ToBitWidth - 1, 0, Exp); + + // Both are bitvectors with the same width, ignore the type cast + return Exp; + } + + if (FromTy->isRealFloatingType() && ToTy->isRealFloatingType()) { + if (ToBitWidth != FromBitWidth) + return mkFPtoFP(Exp, getFloatSort(ToBitWidth)); + + return Exp; + } + + if (FromTy->isIntegralOrEnumerationType() && ToTy->isRealFloatingType()) { + SMTSortRef Sort = getFloatSort(ToBitWidth); + return FromTy->isSignedIntegerOrEnumerationType() ? mkFPtoSBV(Exp, Sort) + : mkFPtoUBV(Exp, Sort); + } + + if (FromTy->isRealFloatingType() && ToTy->isIntegralOrEnumerationType()) + return ToTy->isSignedIntegerOrEnumerationType() + ? mkSBVtoFP(Exp, ToBitWidth) + : mkUBVtoFP(Exp, ToBitWidth); + + llvm_unreachable("Unsupported explicit type cast!"); + } + + // Callback function for doCast parameter on APSInt type. + llvm::APSInt castAPSInt(const llvm::APSInt &V, QualType ToTy, + uint64_t ToWidth, QualType FromTy, + uint64_t FromWidth) { + APSIntType TargetType(ToWidth, !ToTy->isSignedIntegerOrEnumerationType()); + return TargetType.convert(V); + } + + // Generate an SMTExprRef that represents the given symbolic expression. + // Sets the hasComparison parameter if the expression has a comparison + // operator. + // Sets the RetTy parameter to the final return type after promotions and + // casts. + SMTExprRef getExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy = nullptr, + bool *hasComparison = nullptr) { + if (hasComparison) { + *hasComparison = false; + } + + return getSymExpr(Ctx, Sym, RetTy, hasComparison); + } + + // Generate an SMTExprRef that compares the expression to zero. + SMTExprRef getZeroExpr(ASTContext &Ctx, const SMTExprRef &Exp, QualType Ty, + bool Assumption) { + + if (Ty->isRealFloatingType()) { + llvm::APFloat Zero = + llvm::APFloat::getZero(Ctx.getFloatTypeSemantics(Ty)); + return fromFloatBinOp(Exp, Assumption ? BO_EQ : BO_NE, fromAPFloat(Zero)); + } + + if (Ty->isIntegralOrEnumerationType() || Ty->isAnyPointerType() || + Ty->isBlockPointerType() || Ty->isReferenceType()) { + + // Skip explicit comparison for boolean types + bool isSigned = Ty->isSignedIntegerOrEnumerationType(); + if (Ty->isBooleanType()) + return Assumption ? fromUnOp(UO_LNot, Exp) : Exp; + + return fromBinOp(Exp, Assumption ? BO_EQ : BO_NE, + fromInt("0", Ctx.getTypeSize(Ty)), isSigned); + } + + llvm_unreachable("Unsupported type for zero value!"); + } + + // Recursive implementation to unpack and generate symbolic expression. + // Sets the hasComparison and RetTy parameters. See getExpr(). + SMTExprRef getSymExpr(ASTContext &Ctx, SymbolRef Sym, QualType *RetTy, + bool *hasComparison) { + if (const SymbolData *SD = dyn_cast<SymbolData>(Sym)) { + if (RetTy) + *RetTy = Sym->getType(); + + return fromData(SD->getSymbolID(), Sym->getType(), + Ctx.getTypeSize(Sym->getType())); + } + + if (const SymbolCast *SC = dyn_cast<SymbolCast>(Sym)) { + if (RetTy) + *RetTy = Sym->getType(); + + QualType FromTy; + SMTExprRef Exp = + getSymExpr(Ctx, SC->getOperand(), &FromTy, hasComparison); + // Casting an expression with a comparison invalidates it. Note that this + // must occur after the recursive call above. + // e.g. (signed char) (x > 0) + if (hasComparison) + *hasComparison = false; + return getCastExpr(Ctx, Exp, FromTy, Sym->getType()); + } + + if (const BinarySymExpr *BSE = dyn_cast<BinarySymExpr>(Sym)) { + SMTExprRef Exp = getSymBinExpr(Ctx, BSE, hasComparison, RetTy); + // Set the hasComparison parameter, in post-order traversal order. + if (hasComparison) + *hasComparison = BinaryOperator::isComparisonOp(BSE->getOpcode()); + return Exp; + } + + llvm_unreachable("Unsupported SymbolRef type!"); + } + + // Wrapper to generate SMTExprRef from SymbolCast data. + SMTExprRef getCastExpr(ASTContext &Ctx, const SMTExprRef &Exp, + QualType FromTy, QualType ToTy) { + return fromCast(Exp, ToTy, Ctx.getTypeSize(ToTy), FromTy, + Ctx.getTypeSize(FromTy)); + } + + // Wrapper to generate SMTExprRef from BinarySymExpr. + // Sets the hasComparison and RetTy parameters. See getSMTExprRef(). + SMTExprRef getSymBinExpr(ASTContext &Ctx, const BinarySymExpr *BSE, + bool *hasComparison, QualType *RetTy) { + QualType LTy, RTy; + BinaryOperator::Opcode Op = BSE->getOpcode(); + + if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(BSE)) { + SMTExprRef LHS = getSymExpr(Ctx, SIE->getLHS(), <y, hasComparison); + llvm::APSInt NewRInt; + std::tie(NewRInt, RTy) = fixAPSInt(Ctx, SIE->getRHS()); + SMTExprRef RHS = fromAPSInt(NewRInt); + return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy); + } + + if (const IntSymExpr *ISE = dyn_cast<IntSymExpr>(BSE)) { + llvm::APSInt NewLInt; + std::tie(NewLInt, LTy) = fixAPSInt(Ctx, ISE->getLHS()); + SMTExprRef LHS = fromAPSInt(NewLInt); + SMTExprRef RHS = getSymExpr(Ctx, ISE->getRHS(), &RTy, hasComparison); + return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy); + } + + if (const SymSymExpr *SSM = dyn_cast<SymSymExpr>(BSE)) { + SMTExprRef LHS = getSymExpr(Ctx, SSM->getLHS(), <y, hasComparison); + SMTExprRef RHS = getSymExpr(Ctx, SSM->getRHS(), &RTy, hasComparison); + return getBinExpr(Ctx, LHS, LTy, Op, RHS, RTy, RetTy); + } + + llvm_unreachable("Unsupported BinarySymExpr type!"); + } + + // Wrapper to generate SMTExprRef from unpacked binary symbolic expression. + // Sets the RetTy parameter. See getSMTExprRef(). + SMTExprRef getBinExpr(ASTContext &Ctx, const SMTExprRef &LHS, QualType LTy, + BinaryOperator::Opcode Op, const SMTExprRef &RHS, + QualType RTy, QualType *RetTy) { + SMTExprRef NewLHS = LHS; + SMTExprRef NewRHS = RHS; + doTypeConversion(Ctx, NewLHS, NewRHS, LTy, RTy); + + // Update the return type parameter if the output type has changed. + if (RetTy) { + // A boolean result can be represented as an integer type in C/C++, but at + // this point we only care about the SMT sorts. Set it as a boolean type + // to avoid subsequent SMT errors. + if (BinaryOperator::isComparisonOp(Op) || + BinaryOperator::isLogicalOp(Op)) { + *RetTy = Ctx.BoolTy; + } else { + *RetTy = LTy; + } + + // If the two operands are pointers and the operation is a subtraction, + // the result is of type ptrdiff_t, which is signed + if (LTy->isAnyPointerType() && RTy->isAnyPointerType() && Op == BO_Sub) { + *RetTy = Ctx.getPointerDiffType(); + } + } + + return LTy->isRealFloatingType() + ? fromFloatBinOp(NewLHS, Op, NewRHS) + : fromBinOp(NewLHS, Op, NewRHS, + LTy->isSignedIntegerOrEnumerationType()); + } + + // Wrapper to generate SMTExprRef from a range. If From == To, an equality + // will be created instead. + SMTExprRef getRangeExpr(ASTContext &Ctx, SymbolRef Sym, + const llvm::APSInt &From, const llvm::APSInt &To, + bool InRange) { + // Convert lower bound + QualType FromTy; + llvm::APSInt NewFromInt; + std::tie(NewFromInt, FromTy) = fixAPSInt(Ctx, From); + SMTExprRef FromExp = fromAPSInt(NewFromInt); + + // Convert symbol + QualType SymTy; + SMTExprRef Exp = getExpr(Ctx, Sym, &SymTy); + + // Construct single (in)equality + if (From == To) + return getBinExpr(Ctx, Exp, SymTy, InRange ? BO_EQ : BO_NE, FromExp, + FromTy, /*RetTy=*/nullptr); + + QualType ToTy; + llvm::APSInt NewToInt; + std::tie(NewToInt, ToTy) = fixAPSInt(Ctx, To); + SMTExprRef ToExp = fromAPSInt(NewToInt); + assert(FromTy == ToTy && "Range values have different types!"); + + // Construct two (in)equalities, and a logical and/or + SMTExprRef LHS = getBinExpr(Ctx, Exp, SymTy, InRange ? BO_GE : BO_LT, + FromExp, FromTy, /*RetTy=*/nullptr); + SMTExprRef RHS = + getBinExpr(Ctx, Exp, SymTy, InRange ? BO_LE : BO_GT, ToExp, ToTy, + /*RetTy=*/nullptr); + + return fromBinOp(LHS, InRange ? BO_LAnd : BO_LOr, RHS, + SymTy->isSignedIntegerOrEnumerationType()); + } + + // Recover the QualType of an APSInt. + // TODO: Refactor to put elsewhere + QualType getAPSIntType(ASTContext &Ctx, const llvm::APSInt &Int) { + return Ctx.getIntTypeForBitwidth(Int.getBitWidth(), Int.isSigned()); + } + + // Get the QualTy for the input APSInt, and fix it if it has a bitwidth of 1. + std::pair<llvm::APSInt, QualType> fixAPSInt(ASTContext &Ctx, + const llvm::APSInt &Int) { + llvm::APSInt NewInt; + + // FIXME: This should be a cast from a 1-bit integer type to a boolean type, + // but the former is not available in Clang. Instead, extend the APSInt + // directly. + if (Int.getBitWidth() == 1 && getAPSIntType(Ctx, Int).isNull()) { + NewInt = Int.extend(Ctx.getTypeSize(Ctx.BoolTy)); + } else + NewInt = Int; + + return std::make_pair(NewInt, getAPSIntType(Ctx, NewInt)); + } + + // Perform implicit type conversion on binary symbolic expressions. + // May modify all input parameters. + // TODO: Refactor to use built-in conversion functions + void doTypeConversion(ASTContext &Ctx, SMTExprRef &LHS, SMTExprRef &RHS, + QualType <y, QualType &RTy) { + assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); + + // Perform type conversion + if ((LTy->isIntegralOrEnumerationType() && + RTy->isIntegralOrEnumerationType()) && + (LTy->isArithmeticType() && RTy->isArithmeticType())) { + doIntTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy, RHS, + RTy); + return; + } + + if (LTy->isRealFloatingType() || RTy->isRealFloatingType()) { + doFloatTypeConversion<SMTExprRef, &SMTSolver::fromCast>(Ctx, LHS, LTy, + RHS, RTy); + return; + } + + if ((LTy->isAnyPointerType() || RTy->isAnyPointerType()) || + (LTy->isBlockPointerType() || RTy->isBlockPointerType()) || + (LTy->isReferenceType() || RTy->isReferenceType())) { + // TODO: Refactor to Sema::FindCompositePointerType(), and + // Sema::CheckCompareOperands(). + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + // Cast the non-pointer type to the pointer type. + // TODO: Be more strict about this. + if ((LTy->isAnyPointerType() ^ RTy->isAnyPointerType()) || + (LTy->isBlockPointerType() ^ RTy->isBlockPointerType()) || + (LTy->isReferenceType() ^ RTy->isReferenceType())) { + if (LTy->isNullPtrType() || LTy->isBlockPointerType() || + LTy->isReferenceType()) { + LHS = fromCast(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } else { + RHS = fromCast(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } + } + + // Cast the void pointer type to the non-void pointer type. + // For void types, this assumes that the casted value is equal to the + // value of the original pointer, and does not account for alignment + // requirements. + if (LTy->isVoidPointerType() ^ RTy->isVoidPointerType()) { + assert((Ctx.getTypeSize(LTy) == Ctx.getTypeSize(RTy)) && + "Pointer types have different bitwidths!"); + if (RTy->isVoidPointerType()) + RTy = LTy; + else + LTy = RTy; + } + + if (LTy == RTy) + return; + } + + // Fallback: for the solver, assume that these types don't really matter + if ((LTy.getCanonicalType() == RTy.getCanonicalType()) || + (LTy->isObjCObjectPointerType() && RTy->isObjCObjectPointerType())) { + LTy = RTy; + return; + } + + // TODO: Refine behavior for invalid type casts + } + + // Perform implicit integer type conversion. + // May modify all input parameters. + // TODO: Refactor to use Sema::handleIntegerConversion() + template <typename T, T (SMTSolver::*doCast)(const T &, QualType, uint64_t, + QualType, uint64_t)> + void doIntTypeConversion(ASTContext &Ctx, T &LHS, QualType <y, T &RHS, + QualType &RTy) { + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + assert(!LTy.isNull() && !RTy.isNull() && "Input type is null!"); + // Always perform integer promotion before checking type equality. + // Otherwise, e.g. (bool) a + (bool) b could trigger a backend assertion + if (LTy->isPromotableIntegerType()) { + QualType NewTy = Ctx.getPromotedIntegerType(LTy); + uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); + LHS = (this->*doCast)(LHS, NewTy, NewBitWidth, LTy, LBitWidth); + LTy = NewTy; + LBitWidth = NewBitWidth; + } + if (RTy->isPromotableIntegerType()) { + QualType NewTy = Ctx.getPromotedIntegerType(RTy); + uint64_t NewBitWidth = Ctx.getTypeSize(NewTy); + RHS = (this->*doCast)(RHS, NewTy, NewBitWidth, RTy, RBitWidth); + RTy = NewTy; + RBitWidth = NewBitWidth; + } + + if (LTy == RTy) + return; + + // Perform integer type conversion + // Note: Safe to skip updating bitwidth because this must terminate + bool isLSignedTy = LTy->isSignedIntegerOrEnumerationType(); + bool isRSignedTy = RTy->isSignedIntegerOrEnumerationType(); + + int order = Ctx.getIntegerTypeOrder(LTy, RTy); + if (isLSignedTy == isRSignedTy) { + // Same signedness; use the higher-ranked type + if (order == 1) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else if (order != (isLSignedTy ? 1 : -1)) { + // The unsigned type has greater than or equal rank to the + // signed type, so use the unsigned type + if (isRSignedTy) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else if (LBitWidth != RBitWidth) { + // The two types are different widths; if we are here, that + // means the signed type is larger than the unsigned type, so + // use the signed type. + if (isLSignedTy) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } + } else { + // The signed type is higher-ranked than the unsigned type, + // but isn't actually any bigger (like unsigned int and long + // on most 32-bit systems). Use the unsigned type corresponding + // to the signed type. + QualType NewTy = + Ctx.getCorrespondingUnsignedType(isLSignedTy ? LTy : RTy); + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = NewTy; + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = NewTy; + } + } + + // Perform implicit floating-point type conversion. + // May modify all input parameters. + // TODO: Refactor to use Sema::handleFloatConversion() + template <typename T, T (SMTSolver::*doCast)(const T &, QualType, uint64_t, + QualType, uint64_t)> + void doFloatTypeConversion(ASTContext &Ctx, T &LHS, QualType <y, T &RHS, + QualType &RTy) { + + uint64_t LBitWidth = Ctx.getTypeSize(LTy); + uint64_t RBitWidth = Ctx.getTypeSize(RTy); + + // Perform float-point type promotion + if (!LTy->isRealFloatingType()) { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + LBitWidth = RBitWidth; + } + if (!RTy->isRealFloatingType()) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + RBitWidth = LBitWidth; + } + + if (LTy == RTy) + return; + + // If we have two real floating types, convert the smaller operand to the + // bigger result + // Note: Safe to skip updating bitwidth because this must terminate + int order = Ctx.getFloatingTypeOrder(LTy, RTy); + if (order > 0) { + RHS = (this->*doCast)(RHS, LTy, LBitWidth, RTy, RBitWidth); + RTy = LTy; + } else if (order == 0) { + LHS = (this->*doCast)(LHS, RTy, RBitWidth, LTy, LBitWidth); + LTy = RTy; + } else { + llvm_unreachable("Unsupported floating-point type cast!"); + } + } + + // Returns a boolean sort. + virtual SMTSortRef getBoolSort() = 0; + + // Returns an appropriate bitvector sort for the given bitwidth. + virtual SMTSortRef getBitvectorSort(const unsigned BitWidth) = 0; + + // Returns a floating-point sort of width 16 + virtual SMTSortRef getFloat16Sort() = 0; + + // Returns a floating-point sort of width 32 + virtual SMTSortRef getFloat32Sort() = 0; + + // Returns a floating-point sort of width 64 + virtual SMTSortRef getFloat64Sort() = 0; + + // Returns a floating-point sort of width 128 + virtual SMTSortRef getFloat128Sort() = 0; + + // Returns an appropriate sort for the given AST. + virtual SMTSortRef getSort(const SMTExprRef &AST) = 0; + + // Returns a new SMTExprRef from an SMTExpr + virtual SMTExprRef newExprRef(const SMTExpr &E) const = 0; + + /// Given a constraint, adds it to the solver + virtual void addConstraint(const SMTExprRef &Exp) const = 0; + + /// Creates a bitvector addition operation + virtual SMTExprRef mkBVAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector subtraction operation + virtual SMTExprRef mkBVSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector multiplication operation + virtual SMTExprRef mkBVMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed modulus operation + virtual SMTExprRef mkBVSRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned modulus operation + virtual SMTExprRef mkBVURem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed division operation + virtual SMTExprRef mkBVSDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned division operation + virtual SMTExprRef mkBVUDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector logical shift left operation + virtual SMTExprRef mkBVShl(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector arithmetic shift right operation + virtual SMTExprRef mkBVAshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector logical shift right operation + virtual SMTExprRef mkBVLshr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector negation operation + virtual SMTExprRef mkBVNeg(const SMTExprRef &Exp) = 0; + + /// Creates a bitvector not operation + virtual SMTExprRef mkBVNot(const SMTExprRef &Exp) = 0; + + /// Creates a bitvector xor operation + virtual SMTExprRef mkBVXor(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector or operation + virtual SMTExprRef mkBVOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector and operation + virtual SMTExprRef mkBVAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned less-than operation + virtual SMTExprRef mkBVUlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed less-than operation + virtual SMTExprRef mkBVSlt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned greater-than operation + virtual SMTExprRef mkBVUgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed greater-than operation + virtual SMTExprRef mkBVSgt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned less-equal-than operation + virtual SMTExprRef mkBVUle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed less-equal-than operation + virtual SMTExprRef mkBVSle(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector unsigned greater-equal-than operation + virtual SMTExprRef mkBVUge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a bitvector signed greater-equal-than operation + virtual SMTExprRef mkBVSge(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean not operation + virtual SMTExprRef mkNot(const SMTExprRef &Exp) = 0; + + /// Creates a boolean equality operation + virtual SMTExprRef mkEqual(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean and operation + virtual SMTExprRef mkAnd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean or operation + virtual SMTExprRef mkOr(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a boolean ite operation + virtual SMTExprRef mkIte(const SMTExprRef &Cond, const SMTExprRef &T, + const SMTExprRef &F) = 0; + + /// Creates a bitvector sign extension operation + virtual SMTExprRef mkBVSignExt(unsigned i, const SMTExprRef &Exp) = 0; + + /// Creates a bitvector zero extension operation + virtual SMTExprRef mkBVZeroExt(unsigned i, const SMTExprRef &Exp) = 0; + + /// Creates a bitvector extract operation + virtual SMTExprRef mkBVExtract(unsigned High, unsigned Low, + const SMTExprRef &Exp) = 0; + + /// Creates a bitvector concat operation + virtual SMTExprRef mkBVConcat(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a floating-point negation operation + virtual SMTExprRef mkFPNeg(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isInfinite operation + virtual SMTExprRef mkFPIsInfinite(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isNaN operation + virtual SMTExprRef mkFPIsNaN(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isNormal operation + virtual SMTExprRef mkFPIsNormal(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point isZero operation + virtual SMTExprRef mkFPIsZero(const SMTExprRef &Exp) = 0; + + /// Creates a floating-point multiplication operation + virtual SMTExprRef mkFPMul(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point division operation + virtual SMTExprRef mkFPDiv(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point remainder operation + virtual SMTExprRef mkFPRem(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point addition operation + virtual SMTExprRef mkFPAdd(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point subtraction operation + virtual SMTExprRef mkFPSub(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point less-than operation + virtual SMTExprRef mkFPLt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point greater-than operation + virtual SMTExprRef mkFPGt(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point less-than-or-equal operation + virtual SMTExprRef mkFPLe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point greater-than-or-equal operation + virtual SMTExprRef mkFPGe(const SMTExprRef &LHS, const SMTExprRef &RHS) = 0; + + /// Creates a floating-point equality operation + virtual SMTExprRef mkFPEqual(const SMTExprRef &LHS, + const SMTExprRef &RHS) = 0; + + /// Creates a floating-point conversion from floatint-point to floating-point + /// operation + virtual SMTExprRef mkFPtoFP(const SMTExprRef &From, const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from floatint-point to signed + /// bitvector operation + virtual SMTExprRef mkFPtoSBV(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from floatint-point to unsigned + /// bitvector operation + virtual SMTExprRef mkFPtoUBV(const SMTExprRef &From, + const SMTSortRef &To) = 0; + + /// Creates a floating-point conversion from signed bitvector to + /// floatint-point operation + virtual SMTExprRef mkSBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + + /// Creates a floating-point conversion from unsigned bitvector to + /// floatint-point operation + virtual SMTExprRef mkUBVtoFP(const SMTExprRef &From, unsigned ToWidth) = 0; + + /// Creates a new symbol, given a name and a sort + virtual SMTExprRef mkSymbol(const char *Name, SMTSortRef Sort) = 0; + + // Returns an appropriate floating-point rounding mode. + virtual SMTExprRef getFloatRoundingMode() = 0; + + // If the a model is available, returns the value of a given bitvector symbol + virtual llvm::APSInt getBitvector(const SMTExprRef &Exp, unsigned BitWidth, + bool isUnsigned) = 0; + + // If the a model is available, returns the value of a given boolean symbol + virtual bool getBoolean(const SMTExprRef &Exp) = 0; + + /// Constructs an SMTExprRef from a boolean. + virtual SMTExprRef mkBoolean(const bool b) = 0; + + /// Constructs an SMTExprRef from a finite APFloat. + virtual SMTExprRef mkFloat(const llvm::APFloat Float) = 0; + + /// Constructs an SMTExprRef from an APSInt and its bit width + virtual SMTExprRef mkBitvector(const llvm::APSInt Int, unsigned BitWidth) = 0; + + /// Given an expression, extract the value of this operand in the model. + virtual bool getInterpretation(const SMTExprRef &Exp, llvm::APSInt &Int) = 0; + + /// Given an expression extract the value of this operand in the model. + virtual bool getInterpretation(const SMTExprRef &Exp, + llvm::APFloat &Float) = 0; + + /// Construct an SMTExprRef value from a boolean. + virtual SMTExprRef fromBoolean(const bool Bool) = 0; + + /// Construct an SMTExprRef value from a finite APFloat. + virtual SMTExprRef fromAPFloat(const llvm::APFloat &Float) = 0; + + /// Construct an SMTExprRef value from an APSInt. + virtual SMTExprRef fromAPSInt(const llvm::APSInt &Int) = 0; + + /// Construct an SMTExprRef value from an integer. + virtual SMTExprRef fromInt(const char *Int, uint64_t BitWidth) = 0; + + /// Construct an SMTExprRef from a SymbolData. + virtual SMTExprRef fromData(const SymbolID ID, const QualType &Ty, + uint64_t BitWidth) = 0; + + /// Check if the constraints are satisfiable + virtual ConditionTruthVal check() const = 0; + + /// Push the current solver state + virtual void push() = 0; + + /// Pop the previous solver state + virtual void pop(unsigned NumStates = 1) = 0; + + /// Reset the solver and remove all constraints. + virtual void reset() const = 0; + + virtual void print(raw_ostream &OS) const = 0; +}; + +/// Shared pointer for SMTSolvers. +using SMTSolverRef = std::shared_ptr<SMTSolver>; + +/// Convenience method to create and Z3Solver object +std::unique_ptr<SMTSolver> CreateZ3Solver(); + +} // namespace ento +} // namespace clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h new file mode 100644 index 0000000000000..41ef573f0c713 --- /dev/null +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SMTSort.h @@ -0,0 +1,91 @@ +//== SMTSort.h --------------------------------------------------*- 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 a SMT generic Sort API, which will be the base class +// for every SMT solver sort specific class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H +#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SMTSORT_H + +#include "clang/Basic/TargetInfo.h" + +namespace clang { +namespace ento { + +/// Generic base class for SMT sorts +class SMTSort { +public: + SMTSort() = default; + virtual ~SMTSort() = default; + + /// Returns true if the sort is a bitvector, calls isBitvectorSortImpl(). + virtual bool isBitvectorSort() const { return isBitvectorSortImpl(); } + + /// Returns true if the sort is a floating-point, calls isFloatSortImpl(). + virtual bool isFloatSort() const { return isFloatSortImpl(); } + + /// Returns true if the sort is a boolean, calls isBooleanSortImpl(). + virtual bool isBooleanSort() const { return isBooleanSortImpl(); } + + /// Returns the bitvector size, fails if the sort is not a bitvector + /// Calls getBitvectorSortSizeImpl(). + virtual unsigned getBitvectorSortSize() const { + assert(isBitvectorSort() && "Not a bitvector sort!"); + unsigned Size = getBitvectorSortSizeImpl(); + assert(Size && "Size is zero!"); + return Size; + }; + + /// Returns the floating-point size, fails if the sort is not a floating-point + /// Calls getFloatSortSizeImpl(). + virtual unsigned getFloatSortSize() const { + assert(isFloatSort() && "Not a floating-point sort!"); + unsigned Size = getFloatSortSizeImpl(); + assert(Size && "Size is zero!"); + return Size; + }; + + friend bool operator==(SMTSort const &LHS, SMTSort const &RHS) { + return LHS.equal_to(RHS); + } + + virtual void print(raw_ostream &OS) const = 0; + + LLVM_DUMP_METHOD void dump() const { print(llvm::errs()); } + +protected: + /// Query the SMT solver and returns true if two sorts are equal (same kind + /// and bit width). This does not check if the two sorts are the same objects. + virtual bool equal_to(SMTSort const &other) const = 0; + + /// Query the SMT solver and checks if a sort is bitvector. + virtual bool isBitvectorSortImpl() const = 0; + + /// Query the SMT solver and checks if a sort is floating-point. + virtual bool isFloatSortImpl() const = 0; + + /// Query the SMT solver and checks if a sort is boolean. + virtual bool isBooleanSortImpl() const = 0; + + /// Query the SMT solver and returns the sort bit width. + virtual unsigned getBitvectorSortSizeImpl() const = 0; + + /// Query the SMT solver and returns the sort bit width. + virtual unsigned getFloatSortSizeImpl() const = 0; +}; + +/// Shared pointer for SMTSorts, used by SMTSolver API. +using SMTSortRef = std::shared_ptr<SMTSort>; + +} // namespace ento +} // namespace clang + +#endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h index d58d0a690c88e..31300d69f2ff7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h @@ -16,21 +16,43 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H #include "clang/AST/ASTContext.h" +#include "clang/AST/DeclarationName.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprObjC.h" +#include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" +#include "clang/Basic/LangOptions.h" #include "clang/StaticAnalyzer/Core/PathSensitive/BasicValueFactory.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h" +#include "llvm/ADT/ImmutableList.h" +#include "llvm/ADT/Optional.h" +#include <cstdint> namespace clang { +class BlockDecl; class CXXBoolLiteralExpr; +class CXXMethodDecl; +class CXXRecordDecl; +class DeclaratorDecl; +class FunctionDecl; +class LocationContext; +class StackFrameContext; +class Stmt; namespace ento { +class ConditionTruthVal; +class ProgramStateManager; +class StoreRef; + class SValBuilder { virtual void anchor(); + protected: ASTContext &Context; @@ -62,14 +84,12 @@ public: public: SValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr) - : Context(context), BasicVals(context, alloc), - SymMgr(context, BasicVals, alloc), - MemMgr(context, alloc), - StateMgr(stateMgr), - ArrayIndexTy(context.LongLongTy), - ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {} + : Context(context), BasicVals(context, alloc), + SymMgr(context, BasicVals, alloc), MemMgr(context, alloc), + StateMgr(stateMgr), ArrayIndexTy(context.LongLongTy), + ArrayIndexWidth(context.getTypeSize(ArrayIndexTy)) {} - virtual ~SValBuilder() {} + virtual ~SValBuilder() = default; bool haveSameType(const SymExpr *Sym1, const SymExpr *Sym2) { return haveSameType(Sym1->getType(), Sym2->getType()); @@ -124,7 +144,12 @@ public: SVal evalBinOp(ProgramStateRef state, BinaryOperator::Opcode op, SVal lhs, SVal rhs, QualType type); - + + /// \return Whether values in \p lhs and \p rhs are equal at \p state. + ConditionTruthVal areEqual(ProgramStateRef state, SVal lhs, SVal rhs); + + SVal evalEQ(ProgramStateRef state, SVal lhs, SVal rhs); + DefinedOrUnknownSVal evalEQ(ProgramStateRef state, DefinedOrUnknownSVal lhs, DefinedOrUnknownSVal rhs); @@ -173,7 +198,7 @@ public: /// Make a unique symbol for value of region. DefinedOrUnknownSVal getRegionValueSymbolVal(const TypedValueRegion *region); - /// \brief Create a new symbol with a unique 'name'. + /// Create a new symbol with a unique 'name'. /// /// We resort to conjured symbols when we cannot construct a derived symbol. /// The advantage of symbols derived/built from other symbols is that we @@ -188,12 +213,12 @@ public: const LocationContext *LCtx, QualType type, unsigned count); - DefinedOrUnknownSVal conjureSymbolVal(const Stmt *stmt, const LocationContext *LCtx, QualType type, unsigned visitCount); - /// \brief Conjure a symbol representing heap allocated memory region. + + /// Conjure a symbol representing heap allocated memory region. /// /// Note, the expression should represent a location. DefinedOrUnknownSVal getConjuredHeapSymbolVal(const Expr *E, @@ -304,7 +329,7 @@ public: NonLoc makeNonLoc(const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType type); - /// \brief Create a NonLoc value for cast. + /// Create a NonLoc value for cast. NonLoc makeNonLoc(const SymExpr *operand, QualType fromTy, QualType toTy); nonloc::ConcreteInt makeTruthVal(bool b, QualType type) { @@ -342,6 +367,15 @@ public: return loc::ConcreteInt(BasicVals.getValue(integer)); } + /// Make an SVal that represents the given symbol. This follows the convention + /// of representing Loc-type symbols (symbolic pointers and references) + /// as Loc values wrapping the symbol rather than as plain symbol values. + SVal makeSymbolVal(SymbolRef Sym) { + if (Loc::isLocType(Sym->getType())) + return makeLoc(Sym); + return nonloc::SymbolVal(Sym); + } + /// Return a memory region for the 'this' object reference. loc::MemRegionVal getCXXThis(const CXXMethodDecl *D, const StackFrameContext *SFC); @@ -355,8 +389,8 @@ SValBuilder* createSimpleSValBuilder(llvm::BumpPtrAllocator &alloc, ASTContext &context, ProgramStateManager &stateMgr); -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALBUILDER_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h index 06132587b4aaf..0fde63e9eb09b 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h @@ -1,4 +1,4 @@ -//== SVals.h - Abstract Values for Static Analysis ---------*- C++ -*--==// +//===- SVals.h - Abstract Values for Static Analysis ------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,11 +16,18 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H #include "clang/AST/Expr.h" +#include "clang/AST/Type.h" #include "clang/Basic/LLVM.h" -#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/ImmutableList.h" +#include "llvm/ADT/None.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/PointerUnion.h" +#include "llvm/Support/Casting.h" +#include <cassert> +#include <cstdint> +#include <utility> //==------------------------------------------------------------------------==// // Base SVal types. @@ -28,34 +35,40 @@ namespace clang { +class CXXBaseSpecifier; +class DeclaratorDecl; +class FunctionDecl; +class LabelDecl; + namespace ento { +class BasicValueFactory; class CompoundValData; class LazyCompoundValData; -class PointerToMemberData; -class ProgramState; -class BasicValueFactory; class MemRegion; -class TypedValueRegion; -class MemRegionManager; -class ProgramStateManager; +class PointerToMemberData; class SValBuilder; +class TypedValueRegion; namespace nonloc { + /// Sub-kinds for NonLoc values. enum Kind { #define NONLOC_SVAL(Id, Parent) Id ## Kind, #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" }; -} + +} // namespace nonloc namespace loc { + /// Sub-kinds for Loc values. enum Kind { #define LOC_SVAL(Id, Parent) Id ## Kind, #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.def" }; -} + +} // namespace loc /// SVal - This represents a symbolic expression, which can be either /// an L-value or an R-value. @@ -71,22 +84,21 @@ public: enum { BaseBits = 2, BaseMask = 0x3 }; protected: - const void *Data; + const void *Data = nullptr; /// The lowest 2 bits are a BaseKind (0 -- 3). /// The higher bits are an unsigned "kind" value. - unsigned Kind; + unsigned Kind = 0; explicit SVal(const void *d, bool isLoc, unsigned ValKind) - : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} + : Data(d), Kind((isLoc ? LocKind : NonLocKind) | (ValKind << BaseBits)) {} - explicit SVal(BaseKind k, const void *D = nullptr) - : Data(D), Kind(k) {} + explicit SVal(BaseKind k, const void *D = nullptr) : Data(D), Kind(k) {} public: - explicit SVal() : Data(nullptr), Kind(0) {} + explicit SVal() = default; - /// \brief Convert to the specified SVal type, asserting that this SVal is of + /// Convert to the specified SVal type, asserting that this SVal is of /// the desired type. template<typename T> T castAs() const { @@ -94,7 +106,7 @@ public: return *static_cast<const T *>(this); } - /// \brief Convert to the specified SVal type, returning None if this SVal is + /// Convert to the specified SVal type, returning None if this SVal is /// not of the desired type. template<typename T> Optional<T> getAs() const { @@ -103,38 +115,38 @@ public: return *static_cast<const T *>(this); } - inline unsigned getRawKind() const { return Kind; } - inline BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } - inline unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } + unsigned getRawKind() const { return Kind; } + BaseKind getBaseKind() const { return (BaseKind) (Kind & BaseMask); } + unsigned getSubKind() const { return (Kind & ~BaseMask) >> BaseBits; } // This method is required for using SVal in a FoldingSetNode. It // extracts a unique signature for this SVal object. - inline void Profile(llvm::FoldingSetNodeID& ID) const { + void Profile(llvm::FoldingSetNodeID &ID) const { ID.AddInteger((unsigned) getRawKind()); ID.AddPointer(Data); } - inline bool operator==(const SVal& R) const { + bool operator==(const SVal &R) const { return getRawKind() == R.getRawKind() && Data == R.Data; } - inline bool operator!=(const SVal& R) const { + bool operator!=(const SVal &R) const { return !(*this == R); } - inline bool isUnknown() const { + bool isUnknown() const { return getRawKind() == UnknownValKind; } - inline bool isUndef() const { + bool isUndef() const { return getRawKind() == UndefinedValKind; } - inline bool isUnknownOrUndef() const { + bool isUnknownOrUndef() const { return getRawKind() <= UnknownValKind; } - inline bool isValid() const { + bool isValid() const { return getRawKind() > UnknownValKind; } @@ -152,7 +164,7 @@ public: /// Otherwise return 0. const FunctionDecl *getAsFunctionDecl() const; - /// \brief If this SVal is a location and wraps a symbol, return that + /// If this SVal is a location and wraps a symbol, return that /// SymbolRef. Otherwise return 0. /// /// Casts are ignored during lookup. @@ -163,7 +175,7 @@ public: /// Get the symbol in the SVal or its base region. SymbolRef getLocSymbolInBase() const; - /// \brief If this SVal wraps a symbol return that SymbolRef. + /// If this SVal wraps a symbol return that SymbolRef. /// Otherwise, return 0. /// /// Casts are ignored during lookup. @@ -175,7 +187,7 @@ public: /// return that expression. Otherwise return NULL. const SymExpr *getAsSymbolicExpression() const; - const SymExpr* getAsSymExpr() const; + const SymExpr *getAsSymExpr() const; const MemRegion *getAsRegion() const; @@ -183,7 +195,7 @@ public: void dump() const; SymExpr::symbol_iterator symbol_begin() const { - const SymExpr *SE = getAsSymbolicExpression(); + const SymExpr *SE = getAsSymbol(/*IncludeBaseRegions=*/true); if (SE) return SE->symbol_begin(); else @@ -206,28 +218,28 @@ public: private: friend class SVal; + static bool isKind(const SVal& V) { return V.getBaseKind() == UndefinedValKind; } }; class DefinedOrUnknownSVal : public SVal { -private: +public: // We want calling these methods to be a compiler error since they are // tautologically false. bool isUndef() const = delete; bool isValid() const = delete; protected: - DefinedOrUnknownSVal() {} + DefinedOrUnknownSVal() = default; explicit DefinedOrUnknownSVal(const void *d, bool isLoc, unsigned ValKind) - : SVal(d, isLoc, ValKind) {} - - explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) - : SVal(k, D) {} + : SVal(d, isLoc, ValKind) {} + explicit DefinedOrUnknownSVal(BaseKind k, void *D = nullptr) : SVal(k, D) {} private: friend class SVal; + static bool isKind(const SVal& V) { return !V.isUndef(); } @@ -239,37 +251,43 @@ public: private: friend class SVal; + static bool isKind(const SVal &V) { return V.getBaseKind() == UnknownValKind; } }; class DefinedSVal : public DefinedOrUnknownSVal { -private: +public: // We want calling these methods to be a compiler error since they are // tautologically true/false. bool isUnknown() const = delete; bool isUnknownOrUndef() const = delete; bool isValid() const = delete; + protected: - DefinedSVal() {} + DefinedSVal() = default; explicit DefinedSVal(const void *d, bool isLoc, unsigned ValKind) - : DefinedOrUnknownSVal(d, isLoc, ValKind) {} + : DefinedOrUnknownSVal(d, isLoc, ValKind) {} + private: friend class SVal; + static bool isKind(const SVal& V) { return !V.isUnknownOrUndef(); } }; - -/// \brief Represents an SVal that is guaranteed to not be UnknownVal. +/// Represents an SVal that is guaranteed to not be UnknownVal. class KnownSVal : public SVal { - KnownSVal() {} friend class SVal; + + KnownSVal() = default; + static bool isKind(const SVal &V) { return !V.isUnknown(); } + public: KnownSVal(const DefinedSVal &V) : SVal(V) {} KnownSVal(const UndefinedVal &V) : SVal(V) {} @@ -277,20 +295,21 @@ public: class NonLoc : public DefinedSVal { protected: - NonLoc() {} + NonLoc() = default; explicit NonLoc(unsigned SubKind, const void *d) - : DefinedSVal(d, false, SubKind) {} + : DefinedSVal(d, false, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - static inline bool isCompoundType(QualType T) { + static bool isCompoundType(QualType T) { return T->isArrayType() || T->isRecordType() || T->isComplexType() || T->isVectorType(); } private: friend class SVal; + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind; } @@ -298,20 +317,21 @@ private: class Loc : public DefinedSVal { protected: - Loc() {} + Loc() = default; explicit Loc(unsigned SubKind, const void *D) - : DefinedSVal(const_cast<void*>(D), true, SubKind) {} + : DefinedSVal(const_cast<void *>(D), true, SubKind) {} public: void dumpToStream(raw_ostream &Out) const; - static inline bool isLocType(QualType T) { + static bool isLocType(QualType T) { return T->isAnyPointerType() || T->isBlockPointerType() || T->isReferenceType() || T->isNullPtrType(); } private: friend class SVal; + static bool isKind(const SVal& V) { return V.getBaseKind() == LocKind; } @@ -323,14 +343,17 @@ private: namespace nonloc { -/// \brief Represents symbolic expression. +/// Represents symbolic expression that isn't a location. class SymbolVal : public NonLoc { public: SymbolVal() = delete; - SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { assert(sym); } + SymbolVal(SymbolRef sym) : NonLoc(SymbolValKind, sym) { + assert(sym); + assert(!Loc::isLocType(sym->getType())); + } SymbolRef getSymbol() const { - return (const SymExpr*) Data; + return (const SymExpr *) Data; } bool isExpression() const { @@ -339,6 +362,7 @@ public: private: friend class SVal; + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == SymbolValKind; @@ -349,13 +373,13 @@ private: } }; -/// \brief Value representing integer constant. +/// Value representing integer constant. class ConcreteInt : public NonLoc { public: explicit ConcreteInt(const llvm::APSInt& V) : NonLoc(ConcreteIntKind, &V) {} const llvm::APSInt& getValue() const { - return *static_cast<const llvm::APSInt*>(Data); + return *static_cast<const llvm::APSInt *>(Data); } // Transfer functions for binary/unary operations on ConcreteInts. @@ -368,7 +392,9 @@ public: private: friend class SVal; - ConcreteInt() {} + + ConcreteInt() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == ConcreteIntKind; @@ -392,7 +418,6 @@ class LocAsInteger : public NonLoc { } public: - Loc getLoc() const { const std::pair<SVal, uintptr_t> *D = static_cast<const std::pair<SVal, uintptr_t> *>(Data); @@ -414,7 +439,9 @@ public: private: friend class SVal; - LocAsInteger() {} + + LocAsInteger() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == LocAsIntegerKind; @@ -432,16 +459,19 @@ class CompoundVal : public NonLoc { public: const CompoundValData* getValue() const { - return static_cast<const CompoundValData*>(Data); + return static_cast<const CompoundValData *>(Data); } - typedef llvm::ImmutableList<SVal>::iterator iterator; + using iterator = llvm::ImmutableList<SVal>::iterator; + iterator begin() const; iterator end() const; private: friend class SVal; - CompoundVal() {} + + CompoundVal() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == CompoundValKind; } @@ -455,30 +485,35 @@ class LazyCompoundVal : public NonLoc { friend class ento::SValBuilder; explicit LazyCompoundVal(const LazyCompoundValData *D) - : NonLoc(LazyCompoundValKind, D) {} + : NonLoc(LazyCompoundValKind, D) {} + public: const LazyCompoundValData *getCVData() const { - return static_cast<const LazyCompoundValData*>(Data); + return static_cast<const LazyCompoundValData *>(Data); } + const void *getStore() const; const TypedValueRegion *getRegion() const; private: friend class SVal; - LazyCompoundVal() {} + + LazyCompoundVal() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == LazyCompoundValKind; } + static bool isKind(const NonLoc& V) { return V.getSubKind() == LazyCompoundValKind; } }; -/// \brief Value representing pointer-to-member. +/// Value representing pointer-to-member. /// /// This value is qualified as NonLoc because neither loading nor storing -/// operations are aplied to it. Instead, the analyzer uses the L-value coming +/// operations are applied to it. Instead, the analyzer uses the L-value coming /// from pointer-to-member applied to an object. /// This SVal is represented by a DeclaratorDecl which can be a member function /// pointer or a member data pointer and a list of CXXBaseSpecifiers. This list @@ -488,28 +523,36 @@ class PointerToMember : public NonLoc { friend class ento::SValBuilder; public: - typedef llvm::PointerUnion<const DeclaratorDecl *, - const PointerToMemberData *> PTMDataType; + using PTMDataType = + llvm::PointerUnion<const DeclaratorDecl *, const PointerToMemberData *>; + const PTMDataType getPTMData() const { return PTMDataType::getFromOpaqueValue(const_cast<void *>(Data)); } + bool isNullMemberPointer() const { return getPTMData().isNull(); } + const DeclaratorDecl *getDecl() const; + template<typename AdjustedDecl> - const AdjustedDecl* getDeclAs() const { + const AdjustedDecl *getDeclAs() const { return dyn_cast_or_null<AdjustedDecl>(getDecl()); } - typedef llvm::ImmutableList<const CXXBaseSpecifier *>::iterator iterator; + + using iterator = llvm::ImmutableList<const CXXBaseSpecifier *>::iterator; + iterator begin() const; iterator end() const; private: - explicit PointerToMember(const PTMDataType D) - : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {} friend class SVal; - PointerToMember() {} + + PointerToMember() = default; + explicit PointerToMember(const PTMDataType D) + : NonLoc(PointerToMemberKind, D.getOpaqueValue()) {} + static bool isKind(const SVal& V) { return V.getBaseKind() == NonLocKind && V.getSubKind() == PointerToMemberKind; @@ -520,7 +563,7 @@ private: } }; -} // end namespace ento::nonloc +} // namespace nonloc //==------------------------------------------------------------------------==// // Subclasses of Loc. @@ -535,12 +578,14 @@ public: } const LabelDecl *getLabel() const { - return static_cast<const LabelDecl*>(Data); + return static_cast<const LabelDecl *>(Data); } private: friend class SVal; - GotoLabel() {} + + GotoLabel() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == LocKind && V.getSubKind() == GotoLabelKind; } @@ -550,19 +595,18 @@ private: } }; - class MemRegionVal : public Loc { public: explicit MemRegionVal(const MemRegion* r) : Loc(MemRegionValKind, r) { assert(r); } - /// \brief Get the underlining region. - const MemRegion* getRegion() const { - return static_cast<const MemRegion*>(Data); + /// Get the underlining region. + const MemRegion *getRegion() const { + return static_cast<const MemRegion *>(Data); } - /// \brief Get the underlining region and strip casts. + /// Get the underlining region and strip casts. const MemRegion* stripCasts(bool StripBaseCasts = true) const; template <typename REGION> @@ -570,17 +614,19 @@ public: return dyn_cast<REGION>(getRegion()); } - inline bool operator==(const MemRegionVal& R) const { + bool operator==(const MemRegionVal &R) const { return getRegion() == R.getRegion(); } - inline bool operator!=(const MemRegionVal& R) const { + bool operator!=(const MemRegionVal &R) const { return getRegion() != R.getRegion(); } private: friend class SVal; - MemRegionVal() {} + + MemRegionVal() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == LocKind && V.getSubKind() == MemRegionValKind; @@ -595,8 +641,8 @@ class ConcreteInt : public Loc { public: explicit ConcreteInt(const llvm::APSInt& V) : Loc(ConcreteIntKind, &V) {} - const llvm::APSInt& getValue() const { - return *static_cast<const llvm::APSInt*>(Data); + const llvm::APSInt &getValue() const { + return *static_cast<const llvm::APSInt *>(Data); } // Transfer functions for binary/unary operations on ConcreteInts. @@ -605,7 +651,9 @@ public: private: friend class SVal; - ConcreteInt() {} + + ConcreteInt() = default; + static bool isKind(const SVal& V) { return V.getBaseKind() == LocKind && V.getSubKind() == ConcreteIntKind; @@ -616,11 +664,11 @@ private: } }; -} // end ento::loc namespace +} // namespace loc -} // end ento namespace +} // namespace ento -} // end clang namespace +} // namespace clang namespace llvm { @@ -629,6 +677,6 @@ template <> struct isPodLike<clang::ento::SVal> { static const bool value = true; }; -} // end llvm namespace +} // namespace llvm -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SVALS_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h index 2c9802bbc5360..d64b90e2d380a 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SimpleConstraintManager.h @@ -75,6 +75,7 @@ protected: // Internal implementation. //===------------------------------------------------------------------===// + SValBuilder &getSValBuilder() const { return SVB; } BasicValueFactory &getBasicVals() const { return SVB.getBasicValueFactory(); } SymbolManager &getSymbolManager() const { return SVB.getSymbolManager(); } @@ -85,8 +86,8 @@ private: bool Assumption); }; -} // end GR namespace +} // end namespace ento -} // end clang namespace +} // end namespace clang #endif diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h index 25d20a17afaa7..dc0644df8aabe 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h @@ -1,4 +1,4 @@ -//== Store.h - Interface for maps from Locations to Values ------*- C++ -*--==// +//===- Store.h - Interface for maps from Locations to Values ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,27 +14,42 @@ #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H +#include "clang/AST/Type.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState_Fwd.h" #include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h" #include "clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" +#include "clang/Basic/LLVM.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include <cassert> +#include <cstdint> +#include <memory> namespace clang { -class Stmt; +class ASTContext; +class CastExpr; +class CompoundLiteralExpr; +class CXXBasePath; +class Decl; class Expr; +class LocationContext; class ObjCIvarDecl; -class CXXBasePath; class StackFrameContext; namespace ento { class CallEvent; -class ProgramState; class ProgramStateManager; class ScanReachableSymbols; +class SymbolReaper; -typedef llvm::DenseSet<SymbolRef> InvalidatedSymbols; +using InvalidatedSymbols = llvm::DenseSet<SymbolRef>; class StoreManager { protected: @@ -48,7 +63,7 @@ protected: StoreManager(ProgramStateManager &stateMgr); public: - virtual ~StoreManager() {} + virtual ~StoreManager() = default; /// Return the value bound to specified location in a given state. /// \param[in] store The store in which to make the lookup. @@ -92,9 +107,17 @@ public: /// by \c val bound to the location given for \c loc. virtual StoreRef Bind(Store store, Loc loc, SVal val) = 0; - virtual StoreRef BindDefault(Store store, const MemRegion *R, SVal V); + /// Return a store with the specified value bound to all sub-regions of the + /// region. The region must not have previous bindings. If you need to + /// invalidate existing bindings, consider invalidateRegions(). + virtual StoreRef BindDefaultInitial(Store store, const MemRegion *R, + SVal V) = 0; - /// \brief Create a new store with the specified binding removed. + /// Return a store with in which all values within the given region are + /// reset to zero. This method is allowed to overwrite previous bindings. + virtual StoreRef BindDefaultZero(Store store, const MemRegion *R) = 0; + + /// Create a new store with the specified binding removed. /// \param ST the original store, that is the basis for the new store. /// \param L the location whose binding should be removed. virtual StoreRef killBinding(Store ST, Loc L) = 0; @@ -147,7 +170,7 @@ public: SVal evalDerivedToBase(SVal Derived, QualType DerivedPtrType, bool IsVirtual); - /// \brief Attempts to do a down cast. Used to model BaseToDerived and C++ + /// Attempts to do a down cast. Used to model BaseToDerived and C++ /// dynamic_cast. /// The callback may result in the following 3 scenarios: /// - Successful cast (ex: derived is subclass of base). @@ -168,7 +191,7 @@ public: const MemRegion *castRegion(const MemRegion *region, QualType CastToTy); virtual StoreRef removeDeadBindings(Store store, const StackFrameContext *LCtx, - SymbolReaper& SymReaper) = 0; + SymbolReaper &SymReaper) = 0; virtual bool includedInBindings(Store store, const MemRegion *region) const = 0; @@ -182,7 +205,7 @@ public: /// associated with the object is recycled. virtual void decrementReferenceCount(Store store) {} - typedef SmallVector<const MemRegion *, 8> InvalidatedRegions; + using InvalidatedRegions = SmallVector<const MemRegion *, 8>; /// invalidateRegions - Clears out the specified regions from the store, /// marking their values as unknown. Depending on the store, this may also @@ -235,6 +258,7 @@ public: class BindingsHandler { public: virtual ~BindingsHandler(); + virtual bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion *region, SVal val) = 0; }; @@ -242,16 +266,16 @@ public: class FindUniqueBinding : public BindingsHandler { SymbolRef Sym; - const MemRegion* Binding; - bool First; + const MemRegion* Binding = nullptr; + bool First = true; public: - FindUniqueBinding(SymbolRef sym) - : Sym(sym), Binding(nullptr), First(true) {} + FindUniqueBinding(SymbolRef sym) : Sym(sym) {} + + explicit operator bool() { return First && Binding; } bool HandleBinding(StoreManager& SMgr, Store store, const MemRegion* R, SVal val) override; - explicit operator bool() { return First && Binding; } const MemRegion *getRegion() { return Binding; } }; @@ -266,22 +290,21 @@ protected: /// CastRetrievedVal - Used by subclasses of StoreManager to implement /// implicit casts that arise from loads from regions that are reinterpreted /// as another region. - SVal CastRetrievedVal(SVal val, const TypedValueRegion *region, - QualType castTy, bool performTestOnly = true); + SVal CastRetrievedVal(SVal val, const TypedValueRegion *region, + QualType castTy); private: SVal getLValueFieldOrIvar(const Decl *decl, SVal base); }; - inline StoreRef::StoreRef(Store store, StoreManager & smgr) - : store(store), mgr(smgr) { + : store(store), mgr(smgr) { if (store) mgr.incrementReferenceCount(store); } -inline StoreRef::StoreRef(const StoreRef &sr) - : store(sr.store), mgr(sr.mgr) +inline StoreRef::StoreRef(const StoreRef &sr) + : store(sr.store), mgr(sr.mgr) { if (store) mgr.incrementReferenceCount(store); @@ -308,8 +331,8 @@ CreateRegionStoreManager(ProgramStateManager &StMgr); std::unique_ptr<StoreManager> CreateFieldsOnlyRegionStoreManager(ProgramStateManager &StMgr); -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STORE_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h index 958c8c377ea2a..c5b4e5036bdf4 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/StoreRef.h @@ -1,4 +1,4 @@ -//== StoreRef.h - Smart pointer for store objects ---------------*- C++ -*--==// +//===- StoreRef.h - Smart pointer for store objects -------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,33 +19,36 @@ namespace clang { namespace ento { +class StoreManager; + /// Store - This opaque type encapsulates an immutable mapping from /// locations to values. At a high-level, it represents the symbolic /// memory model. Different subclasses of StoreManager may choose /// different types to represent the locations and values. -typedef const void *Store; - -class StoreManager; +using Store = const void *; class StoreRef { Store store; StoreManager &mgr; + public: - StoreRef(Store, StoreManager &); - StoreRef(const StoreRef &); - StoreRef &operator=(StoreRef const &); + StoreRef(Store store, StoreManager &smgr); + StoreRef(const StoreRef &sr); + StoreRef &operator=(StoreRef const &newStore); + ~StoreRef(); bool operator==(const StoreRef &x) const { assert(&mgr == &x.mgr); return x.store == store; } + bool operator!=(const StoreRef &x) const { return !operator==(x); } - ~StoreRef(); - Store getStore() const { return store; } const StoreManager &getStoreManager() const { return mgr; } }; -}} -#endif +} // namespace ento +} // namespace clang + +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_STOREREF_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h index 8ccd34751bbe1..e574ffdd6a159 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SubEngine.h @@ -24,6 +24,10 @@ class CFGElement; class LocationContext; class Stmt; +namespace cross_tu { +class CrossTranslationUnitContext; +} + namespace ento { struct NodeBuilderContext; @@ -49,6 +53,9 @@ public: virtual AnalysisManager &getAnalysisManager() = 0; + virtual cross_tu::CrossTranslationUnitContext * + getCrossTranslationUnitContext() = 0; + virtual ProgramStateManager &getStateManager() = 0; /// Called by CoreEngine. Used to generate new successor @@ -155,7 +162,8 @@ public: /// printState - Called by ProgramStateManager to print checker-specific data. virtual void printState(raw_ostream &Out, ProgramStateRef State, - const char *NL, const char *Sep) = 0; + const char *NL, const char *Sep, + const LocationContext *LCtx = nullptr) = 0; /// Called by CoreEngine when the analysis worklist is either empty or the // maximum number of analysis steps have been reached. diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h index 9780d0144746e..69b9858d3feb7 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h @@ -1,4 +1,4 @@ -//== SymExpr.h - Management of Symbolic Values ------------------*- C++ -*--==// +//===- SymExpr.h - Management of Symbolic Values ----------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,16 +15,17 @@ #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMEXPR_H #include "clang/AST/Type.h" +#include "clang/Basic/LLVM.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/ADT/SmallVector.h" -#include "llvm/Support/raw_ostream.h" +#include <cassert> namespace clang { namespace ento { class MemRegion; -/// \brief Symbolic value. These values used to capture symbolic execution of +/// Symbolic value. These values used to capture symbolic execution of /// the program. class SymExpr : public llvm::FoldingSetNode { virtual void anchor(); @@ -48,8 +49,10 @@ protected: return !T.isNull() && !T->isVoidType(); } + mutable unsigned Complexity = 0; + public: - virtual ~SymExpr() {} + virtual ~SymExpr() = default; Kind getKind() const { return K; } @@ -60,17 +63,18 @@ public: virtual QualType getType() const = 0; virtual void Profile(llvm::FoldingSetNodeID &profile) = 0; - /// \brief Iterator over symbols that the current symbol depends on. + /// Iterator over symbols that the current symbol depends on. /// /// For SymbolData, it's the symbol itself; for expressions, it's the /// expression symbol and all the operands in it. Note, SymbolDerived is /// treated as SymbolData - the iterator will NOT visit the parent region. class symbol_iterator { SmallVector<const SymExpr *, 5> itr; + void expand(); public: - symbol_iterator() {} + symbol_iterator() = default; symbol_iterator(const SymExpr *SE); symbol_iterator &operator++(); @@ -83,9 +87,9 @@ public: symbol_iterator symbol_begin() const { return symbol_iterator(this); } static symbol_iterator symbol_end() { return symbol_iterator(); } - unsigned computeComplexity() const; + virtual unsigned computeComplexity() const = 0; - /// \brief Find the region from which this symbol originates. + /// Find the region from which this symbol originates. /// /// Whenever the symbol was constructed to denote an unknown value of /// a certain memory region, return this region. This method @@ -104,26 +108,31 @@ inline raw_ostream &operator<<(raw_ostream &os, return os; } -typedef const SymExpr *SymbolRef; -typedef SmallVector<SymbolRef, 2> SymbolRefSmallVectorTy; +using SymbolRef = const SymExpr *; +using SymbolRefSmallVectorTy = SmallVector<SymbolRef, 2>; +using SymbolID = unsigned; -typedef unsigned SymbolID; -/// \brief A symbol representing data which can be stored in a memory location +/// A symbol representing data which can be stored in a memory location /// (region). class SymbolData : public SymExpr { - void anchor() override; const SymbolID Sym; + void anchor() override; + protected: SymbolData(Kind k, SymbolID sym) : SymExpr(k), Sym(sym) { assert(classof(this)); } public: - ~SymbolData() override {} + ~SymbolData() override = default; SymbolID getSymbolID() const { return Sym; } + unsigned computeComplexity() const override { + return 1; + }; + // Implement isa<T> support. static inline bool classof(const SymExpr *SE) { Kind k = SE->getKind(); @@ -134,4 +143,4 @@ public: } // namespace ento } // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMEXPR_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h index 7d2e5ad8ba915..cc3ce72f9e569 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h @@ -1,4 +1,4 @@ -//== SymbolManager.h - Management of Symbolic Values ------------*- C++ -*--==// +//===- SymbolManager.h - Management of Symbolic Values ----------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -15,8 +15,8 @@ #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" +#include "clang/AST/Type.h" #include "clang/Analysis/AnalysisDeclContext.h" #include "clang/Basic/LLVM.h" #include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h" @@ -26,19 +26,19 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/FoldingSet.h" #include "llvm/Support/Allocator.h" -#include "llvm/Support/DataTypes.h" +#include <cassert> namespace clang { - class ASTContext; - class StackFrameContext; + +class ASTContext; +class Stmt; namespace ento { - class BasicValueFactory; - class SubRegion; - class TypedValueRegion; - class VarRegion; -///\brief A symbol representing the value stored at a MemRegion. +class BasicValueFactory; +class StoreManager; + +///A symbol representing the value stored at a MemRegion. class SymbolRegionValue : public SymbolData { const TypedValueRegion *R; @@ -66,7 +66,7 @@ public: QualType getType() const override; // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymbolRegionValueKind; } }; @@ -118,7 +118,7 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymbolConjuredKind; } }; @@ -157,7 +157,7 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymbolDerivedKind; } }; @@ -190,7 +190,7 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymbolExtentKind; } }; @@ -206,11 +206,12 @@ class SymbolMetadata : public SymbolData { const LocationContext *LCtx; unsigned Count; const void *Tag; + public: SymbolMetadata(SymbolID sym, const MemRegion* r, const Stmt *s, QualType t, const LocationContext *LCtx, unsigned count, const void *tag) - : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), - Count(count), Tag(tag) { + : SymbolData(SymbolMetadataKind, sym), R(r), S(s), T(t), LCtx(LCtx), + Count(count), Tag(tag) { assert(r); assert(s); assert(isValidTypeForSymbol(t)); @@ -245,16 +246,18 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymbolMetadataKind; } }; -/// \brief Represents a cast expression. +/// Represents a cast expression. class SymbolCast : public SymExpr { const SymExpr *Operand; + /// Type of the operand. QualType FromTy; + /// The type of the result. QualType ToTy; @@ -267,6 +270,12 @@ public: // Otherwise, 'To' should also be a valid type. } + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = 1 + Operand->computeComplexity(); + return Complexity; + } + QualType getType() const override { return ToTy; } const SymExpr *getOperand() const { return Operand; } @@ -286,12 +295,12 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymbolCastKind; } }; -/// \brief Represents a symbolic expression involving a binary operator +/// Represents a symbolic expression involving a binary operator class BinarySymExpr : public SymExpr { BinaryOperator::Opcode Op; QualType T; @@ -311,13 +320,13 @@ public: BinaryOperator::Opcode getOpcode() const { return Op; } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { Kind k = SE->getKind(); return k >= BEGIN_BINARYSYMEXPRS && k <= END_BINARYSYMEXPRS; } }; -/// \brief Represents a symbolic expression like 'x' + 3. +/// Represents a symbolic expression like 'x' + 3. class SymIntExpr : public BinarySymExpr { const SymExpr *LHS; const llvm::APSInt& RHS; @@ -334,6 +343,12 @@ public: const SymExpr *getLHS() const { return LHS; } const llvm::APSInt &getRHS() const { return RHS; } + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = 1 + LHS->computeComplexity(); + return Complexity; + } + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const llvm::APSInt& rhs, QualType t) { @@ -349,12 +364,12 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymIntExprKind; } }; -/// \brief Represents a symbolic expression like 3 - 'x'. +/// Represents a symbolic expression like 3 - 'x'. class IntSymExpr : public BinarySymExpr { const llvm::APSInt& LHS; const SymExpr *RHS; @@ -371,6 +386,12 @@ public: const SymExpr *getRHS() const { return RHS; } const llvm::APSInt &getLHS() const { return LHS; } + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = 1 + RHS->computeComplexity(); + return Complexity; + } + static void Profile(llvm::FoldingSetNodeID& ID, const llvm::APSInt& lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { @@ -386,12 +407,12 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == IntSymExprKind; } }; -/// \brief Represents a symbolic expression like 'x' + 'y'. +/// Represents a symbolic expression like 'x' + 'y'. class SymSymExpr : public BinarySymExpr { const SymExpr *LHS; const SymExpr *RHS; @@ -409,6 +430,12 @@ public: void dumpToStream(raw_ostream &os) const override; + unsigned computeComplexity() const override { + if (Complexity == 0) + Complexity = RHS->computeComplexity() + LHS->computeComplexity(); + return Complexity; + } + static void Profile(llvm::FoldingSetNodeID& ID, const SymExpr *lhs, BinaryOperator::Opcode op, const SymExpr *rhs, QualType t) { ID.AddInteger((unsigned) SymSymExprKind); @@ -423,20 +450,22 @@ public: } // Implement isa<T> support. - static inline bool classof(const SymExpr *SE) { + static bool classof(const SymExpr *SE) { return SE->getKind() == SymSymExprKind; } }; class SymbolManager { - typedef llvm::FoldingSet<SymExpr> DataSetTy; - typedef llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy*> SymbolDependTy; + using DataSetTy = llvm::FoldingSet<SymExpr>; + using SymbolDependTy = llvm::DenseMap<SymbolRef, SymbolRefSmallVectorTy *>; DataSetTy DataSet; + /// Stores the extra dependencies between symbols: the data should be kept /// alive as long as the key is live. SymbolDependTy SymbolDependencies; - unsigned SymbolCounter; + + unsigned SymbolCounter = 0; llvm::BumpPtrAllocator& BPAlloc; BasicValueFactory &BV; ASTContext &Ctx; @@ -444,14 +473,12 @@ class SymbolManager { public: SymbolManager(ASTContext &ctx, BasicValueFactory &bv, llvm::BumpPtrAllocator& bpalloc) - : SymbolDependencies(16), SymbolCounter(0), - BPAlloc(bpalloc), BV(bv), Ctx(ctx) {} - + : SymbolDependencies(16), BPAlloc(bpalloc), BV(bv), Ctx(ctx) {} ~SymbolManager(); static bool canSymbolicate(QualType T); - /// \brief Make a unique symbol for MemRegion R according to its kind. + /// Make a unique symbol for MemRegion R according to its kind. const SymbolRegionValue* getRegionValueSymbol(const TypedValueRegion* R); const SymbolConjured* conjureSymbol(const Stmt *E, @@ -472,7 +499,7 @@ public: const SymbolExtent *getExtentSymbol(const SubRegion *R); - /// \brief Creates a metadata symbol associated with a specific region. + /// Creates a metadata symbol associated with a specific region. /// /// VisitCount can be used to differentiate regions corresponding to /// different loop iterations, thus, making the symbol path-dependent. @@ -504,7 +531,7 @@ public: return SE->getType(); } - /// \brief Add artificial symbol dependency. + /// Add artificial symbol dependency. /// /// The dependent symbol should stay alive as long as the primary is alive. void addSymbolDependency(const SymbolRef Primary, const SymbolRef Dependent); @@ -515,16 +542,16 @@ public: BasicValueFactory &getBasicVals() { return BV; } }; -/// \brief A class responsible for cleaning up unused symbols. +/// A class responsible for cleaning up unused symbols. class SymbolReaper { enum SymbolStatus { NotProcessed, HaveMarkedDependents }; - typedef llvm::DenseSet<SymbolRef> SymbolSetTy; - typedef llvm::DenseMap<SymbolRef, SymbolStatus> SymbolMapTy; - typedef llvm::DenseSet<const MemRegion *> RegionSetTy; + using SymbolSetTy = llvm::DenseSet<SymbolRef>; + using SymbolMapTy = llvm::DenseMap<SymbolRef, SymbolStatus>; + using RegionSetTy = llvm::DenseSet<const MemRegion *>; SymbolMapTy TheLiving; SymbolSetTy MetadataInUse; @@ -539,17 +566,16 @@ class SymbolReaper { llvm::DenseMap<const MemRegion *, unsigned> includedRegionCache; public: - /// \brief Construct a reaper object, which removes everything which is not + /// Construct a reaper object, which removes everything which is not /// live before we execute statement s in the given location context. /// /// If the statement is NULL, everything is this and parent contexts is /// considered live. /// If the stack frame context is NULL, everything on stack is considered /// dead. - SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, SymbolManager& symmgr, - StoreManager &storeMgr) - : LCtx(Ctx), Loc(s), SymMgr(symmgr), - reapedStore(nullptr, storeMgr) {} + SymbolReaper(const StackFrameContext *Ctx, const Stmt *s, + SymbolManager &symmgr, StoreManager &storeMgr) + : LCtx(Ctx), Loc(s), SymMgr(symmgr), reapedStore(nullptr, storeMgr) {} const LocationContext *getLocationContext() const { return LCtx; } @@ -558,14 +584,14 @@ public: bool isLive(const Stmt *ExprVal, const LocationContext *LCtx) const; bool isLive(const VarRegion *VR, bool includeStoreBindings = false) const; - /// \brief Unconditionally marks a symbol as live. + /// Unconditionally marks a symbol as live. /// /// This should never be /// used by checkers, only by the state infrastructure such as the store and /// environment. Checkers should instead use metadata symbols and markInUse. void markLive(SymbolRef sym); - /// \brief Marks a symbol as important to a checker. + /// Marks a symbol as important to a checker. /// /// For metadata symbols, /// this will keep the symbol alive as long as its associated region is also @@ -574,13 +600,14 @@ public: /// symbol marking has occurred, i.e. in the MarkLiveSymbols callback. void markInUse(SymbolRef sym); - /// \brief If a symbol is known to be live, marks the symbol as live. + /// If a symbol is known to be live, marks the symbol as live. /// /// Otherwise, if the symbol cannot be proven live, it is marked as dead. /// Returns true if the symbol is dead, false if live. bool maybeDead(SymbolRef sym); - typedef SymbolSetTy::const_iterator dead_iterator; + using dead_iterator = SymbolSetTy::const_iterator; + dead_iterator dead_begin() const { return TheDead.begin(); } dead_iterator dead_end() const { return TheDead.end(); } @@ -588,11 +615,12 @@ public: return !TheDead.empty(); } - typedef RegionSetTy::const_iterator region_iterator; + using region_iterator = RegionSetTy::const_iterator; + region_iterator region_begin() const { return RegionRoots.begin(); } region_iterator region_end() const { return RegionRoots.end(); } - /// \brief Returns whether or not a symbol has been confirmed dead. + /// Returns whether or not a symbol has been confirmed dead. /// /// This should only be called once all marking of dead symbols has completed. /// (For checkers, this means only in the evalDeadSymbols callback.) @@ -603,7 +631,7 @@ public: void markLive(const MemRegion *region); void markElementIndicesLive(const MemRegion *region); - /// \brief Set to the value of the symbolic store after + /// Set to the value of the symbolic store after /// StoreManager::removeDeadBindings has been called. void setReapedStore(StoreRef st) { reapedStore = st; } @@ -621,7 +649,7 @@ public: SymbolVisitor(const SymbolVisitor &) = default; SymbolVisitor(SymbolVisitor &&) {} - /// \brief A visitor method invoked by ProgramStateManager::scanReachableSymbols. + /// A visitor method invoked by ProgramStateManager::scanReachableSymbols. /// /// The method returns \c true if symbols should continue be scanned and \c /// false otherwise. @@ -629,8 +657,8 @@ public: virtual bool VisitMemRegion(const MemRegion *region) { return true; } }; -} // end GR namespace +} // namespace ento -} // end clang namespace +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_SYMBOLMANAGER_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h index 7b76263f040c9..ce19b7131d42d 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintManager.h @@ -1,4 +1,4 @@ -//== TaintManager.h - Managing taint --------------------------- -*- C++ -*--=// +//===- TaintManager.h - Managing taint --------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -14,9 +14,9 @@ #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" #include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h" +#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h" #include "clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h" #include "llvm/ADT/ImmutableMap.h" @@ -29,28 +29,37 @@ namespace ento { // FIXME: This does not use the nice trait macros because it must be accessible // from multiple translation units. struct TaintMap {}; -typedef llvm::ImmutableMap<SymbolRef, TaintTagType> TaintMapImpl; + +using TaintMapImpl = llvm::ImmutableMap<SymbolRef, TaintTagType>; + template<> struct ProgramStateTrait<TaintMap> : public ProgramStatePartialTrait<TaintMapImpl> { - static void *GDMIndex() { static int index = 0; return &index; } + static void *GDMIndex() { + static int index = 0; + return &index; + } }; /// The GDM component mapping derived symbols' parent symbols to their /// underlying regions. This is used to efficiently check whether a symbol is /// tainted when it represents a sub-region of a tainted symbol. struct DerivedSymTaint {}; -typedef llvm::ImmutableMap<SymbolRef, TaintedSubRegions> DerivedSymTaintImpl; + +using DerivedSymTaintImpl = llvm::ImmutableMap<SymbolRef, TaintedSubRegions>; + template<> struct ProgramStateTrait<DerivedSymTaint> : public ProgramStatePartialTrait<DerivedSymTaintImpl> { - static void *GDMIndex() { static int index; return &index; } + static void *GDMIndex() { + static int index; + return &index; + } }; class TaintManager { - - TaintManager() {} + TaintManager() = default; }; -} -} +} // namespace ento +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTMANAGER_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h index 0c56e7d8ea698..50c4b8194cff8 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/TaintTag.h @@ -1,4 +1,4 @@ -//== TaintTag.h - Path-sensitive "State" for tracking values -*- C++ -*--=// +//===- TaintTag.h - Path-sensitive "State" for tracking values --*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -11,6 +11,7 @@ // of taint. // //===----------------------------------------------------------------------===// + #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H @@ -19,9 +20,11 @@ namespace ento { /// The type of taint, which helps to differentiate between different types of /// taint. -typedef unsigned TaintTagType; +using TaintTagType = unsigned; + static const TaintTagType TaintTagGeneric = 0; -}} +} // namespace ento +} // namespace clang -#endif +#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_TAINTTAG_H diff --git a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h index 4f1a60e675569..7df8f373b3663 100644 --- a/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h +++ b/include/clang/StaticAnalyzer/Core/PathSensitive/WorkList.h @@ -80,20 +80,14 @@ public: void setBlockCounter(BlockCounter C) { CurrentCounter = C; } BlockCounter getBlockCounter() const { return CurrentCounter; } - class Visitor { - public: - Visitor() {} - virtual ~Visitor(); - virtual bool visit(const WorkListUnit &U) = 0; - }; - virtual bool visitItemsInWorkList(Visitor &V) = 0; - - static WorkList *makeDFS(); - static WorkList *makeBFS(); - static WorkList *makeBFSBlockDFSContents(); + static std::unique_ptr<WorkList> makeDFS(); + static std::unique_ptr<WorkList> makeBFS(); + static std::unique_ptr<WorkList> makeBFSBlockDFSContents(); + static std::unique_ptr<WorkList> makeUnexploredFirst(); + static std::unique_ptr<WorkList> makeUnexploredFirstPriorityQueue(); }; -} // end GR namespace +} // end ento namespace } // end clang namespace diff --git a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h index a9dad6c5e9a29..59fbbc3ca80f9 100644 --- a/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h +++ b/include/clang/StaticAnalyzer/Frontend/AnalysisConsumer.h @@ -17,6 +17,7 @@ #include "clang/AST/ASTConsumer.h" #include "clang/Basic/LLVM.h" +#include <functional> #include <memory> namespace clang { @@ -29,10 +30,24 @@ class CompilerInstance; namespace ento { class PathDiagnosticConsumer; class CheckerManager; +class CheckerRegistry; class AnalysisASTConsumer : public ASTConsumer { public: virtual void AddDiagnosticConsumer(PathDiagnosticConsumer *Consumer) = 0; + + /// This method allows registering statically linked custom checkers that are + /// not a part of the Clang tree. It employs the same mechanism that is used + /// by plugins. + /// + /// Example: + /// + /// Consumer->AddCheckerRegistrationFn([] (CheckerRegistry& Registry) { + /// Registry.addChecker<MyCustomChecker>("example.MyCustomChecker", + /// "Description"); + /// }); + virtual void + AddCheckerRegistrationFn(std::function<void(CheckerRegistry &)> Fn) = 0; }; /// CreateAnalysisConsumer - Creates an ASTConsumer to run various code diff --git a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h index 2985b7c117ef6..216a2359efba1 100644 --- a/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h +++ b/include/clang/StaticAnalyzer/Frontend/CheckerRegistration.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_STATICANALYZER_FRONTEND_CHECKERREGISTRATION_H #include "clang/Basic/LLVM.h" +#include <functional> #include <memory> #include <string> @@ -21,10 +22,13 @@ namespace clang { namespace ento { class CheckerManager; + class CheckerRegistry; - std::unique_ptr<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, + ArrayRef<std::function<void(CheckerRegistry &)>> checkerRegistrationFns, + DiagnosticsEngine &diags); } // end ento namespace diff --git a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h index e66d48b1be1dd..ba37b7f59a02d 100644 --- a/include/clang/StaticAnalyzer/Frontend/FrontendActions.h +++ b/include/clang/StaticAnalyzer/Frontend/FrontendActions.h @@ -31,7 +31,7 @@ protected: StringRef InFile) override; }; -/// \brief Frontend action to parse model files. +/// 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 diff --git a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h index 24f8042587f39..fa00ffd16553a 100644 --- a/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h +++ b/include/clang/StaticAnalyzer/Frontend/ModelConsumer.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file implements clang::ento::ModelConsumer which is an +/// This file implements clang::ento::ModelConsumer which is an /// ASTConsumer for model files. /// //===----------------------------------------------------------------------===// @@ -25,7 +25,7 @@ class Stmt; namespace ento { -/// \brief ASTConsumer to consume model files' AST. +/// ASTConsumer to consume model files' AST. /// /// This consumer collects the bodies of function definitions into a StringMap /// from a model file. diff --git a/include/clang/Tooling/AllTUsExecution.h b/include/clang/Tooling/AllTUsExecution.h new file mode 100644 index 0000000000000..f199365dc8153 --- /dev/null +++ b/include/clang/Tooling/AllTUsExecution.h @@ -0,0 +1,76 @@ +//===--- AllTUsExecution.h - Execute actions on all TUs. -*- 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 a tool executor that runs given actions on all TUs in the +// compilation database. Tool results are deuplicated by the result key. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H +#define LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H + +#include "clang/Tooling/ArgumentsAdjusters.h" +#include "clang/Tooling/Execution.h" + +namespace clang { +namespace tooling { + +/// Executes given frontend actions on all files/TUs in the compilation +/// database. +class AllTUsToolExecutor : public ToolExecutor { +public: + static const char *ExecutorName; + + /// Init with \p CompilationDatabase. + /// This uses \p ThreadCount threads to exececute the actions on all files in + /// parallel. If \p ThreadCount is 0, this uses `llvm::hardware_concurrency`. + AllTUsToolExecutor(const CompilationDatabase &Compilations, + unsigned ThreadCount, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + /// Init with \p CommonOptionsParser. This is expected to be used by + /// `createExecutorFromCommandLineArgs` based on commandline options. + /// + /// The executor takes ownership of \p Options. + AllTUsToolExecutor(CommonOptionsParser Options, unsigned ThreadCount, + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + + StringRef getExecutorName() const override { return ExecutorName; } + + using ToolExecutor::execute; + + llvm::Error + execute(llvm::ArrayRef< + std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> + Actions) override; + + ExecutionContext *getExecutionContext() override { return &Context; }; + + ToolResults *getToolResults() override { return Results.get(); } + + void mapVirtualFile(StringRef FilePath, StringRef Content) override { + OverlayFiles[FilePath] = Content; + } + +private: + // Used to store the parser when the executor is initialized with parser. + llvm::Optional<CommonOptionsParser> OptionsParser; + const CompilationDatabase &Compilations; + std::unique_ptr<ToolResults> Results; + ExecutionContext Context; + llvm::StringMap<std::string> OverlayFiles; + unsigned ThreadCount; +}; + +} // end namespace tooling +} // end namespace clang + +#endif // LLVM_CLANG_TOOLING_ALLTUSEXECUTION_H diff --git a/include/clang/Tooling/ArgumentsAdjusters.h b/include/clang/Tooling/ArgumentsAdjusters.h index 4eb02251a7758..94ccf1f34e576 100644 --- a/include/clang/Tooling/ArgumentsAdjusters.h +++ b/include/clang/Tooling/ArgumentsAdjusters.h @@ -1,4 +1,4 @@ -//===--- ArgumentsAdjusters.h - Command line arguments adjuster -*- C++ -*-===// +//===- ArgumentsAdjusters.h - Command line arguments adjuster ---*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file declares typedef ArgumentsAdjuster and functions to create several +// This file declares type 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. @@ -26,42 +26,42 @@ namespace clang { namespace tooling { -/// \brief A sequence of command line arguments. -typedef std::vector<std::string> CommandLineArguments; +/// A sequence of command line arguments. +using CommandLineArguments = std::vector<std::string>; -/// \brief A prototype of a command line adjuster. +/// A prototype of a command line adjuster. /// /// 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 &, StringRef Filename)> ArgumentsAdjuster; +using ArgumentsAdjuster = std::function<CommandLineArguments( + const CommandLineArguments &, StringRef Filename)>; -/// \brief Gets an argument adjuster that converts input command line arguments +/// Gets an argument adjuster that converts input command line arguments /// to the "syntax check only" variant. ArgumentsAdjuster getClangSyntaxOnlyAdjuster(); -/// \brief Gets an argument adjuster which removes output-related command line +/// Gets an argument adjuster which removes output-related command line /// arguments. ArgumentsAdjuster getClangStripOutputAdjuster(); -/// \brief Gets an argument adjuster which removes dependency-file +/// Gets an argument adjuster which removes dependency-file /// related command line arguments. ArgumentsAdjuster getClangStripDependencyFileAdjuster(); enum class ArgumentInsertPosition { BEGIN, END }; -/// \brief Gets an argument adjuster which inserts \p Extra arguments in the +/// 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 +/// 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 +/// 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); @@ -70,4 +70,3 @@ ArgumentsAdjuster combineAdjusters(ArgumentsAdjuster First, } // namespace clang #endif // LLVM_CLANG_TOOLING_ARGUMENTSADJUSTERS_H - diff --git a/include/clang/Tooling/CommonOptionsParser.h b/include/clang/Tooling/CommonOptionsParser.h index 15e8161dd76fb..7aaa712f9bafb 100644 --- a/include/clang/Tooling/CommonOptionsParser.h +++ b/include/clang/Tooling/CommonOptionsParser.h @@ -34,7 +34,7 @@ namespace clang { namespace tooling { -/// \brief A parser for options common to all command-line Clang tools. +/// A parser for options common to all command-line Clang tools. /// /// Parses a common subset of command-line arguments, locates and loads a /// compilation commands database and runs a tool with user-specified action. It @@ -52,7 +52,7 @@ namespace tooling { /// /// static cl::OptionCategory MyToolCategory("My tool options"); /// static cl::extrahelp CommonHelp(CommonOptionsParser::HelpMessage); -/// static cl::extrahelp MoreHelp("\nMore help text..."); +/// static cl::extrahelp MoreHelp("\nMore help text...\n"); /// static cl::opt<bool> YourOwnOption(...); /// ... /// @@ -65,7 +65,7 @@ namespace tooling { /// \endcode class CommonOptionsParser { public: - /// \brief Parses command-line, initializes a compilation database. + /// Parses command-line, initializes a compilation database. /// /// This constructor can change argc and argv contents, e.g. consume /// command-line options used for creating FixedCompilationDatabase. @@ -79,7 +79,7 @@ public: : CommonOptionsParser(argc, argv, Category, llvm::cl::OneOrMore, Overview) {} - /// \brief Parses command-line, initializes a compilation database. + /// Parses command-line, initializes a compilation database. /// /// This constructor can change argc and argv contents, e.g. consume /// command-line options used for creating FixedCompilationDatabase. @@ -92,7 +92,7 @@ public: llvm::cl::NumOccurrencesFlag OccurrencesFlag, const char *Overview = nullptr); - /// \brief A factory method that is similar to the above constructor, except + /// A factory method that is similar to the above constructor, except /// this returns an error instead exiting the program on error. static llvm::Expected<CommonOptionsParser> create(int &argc, const char **argv, llvm::cl::OptionCategory &Category, diff --git a/include/clang/Tooling/CompilationDatabase.h b/include/clang/Tooling/CompilationDatabase.h index bc3e67b77de25..37e515fdc09e4 100644 --- a/include/clang/Tooling/CompilationDatabase.h +++ b/include/clang/Tooling/CompilationDatabase.h @@ -1,4 +1,4 @@ -//===--- CompilationDatabase.h - --------------------------------*- C++ -*-===// +//===- CompilationDatabase.h ------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -34,35 +34,43 @@ #include "llvm/ADT/Twine.h" #include <memory> #include <string> +#include <utility> #include <vector> namespace clang { namespace tooling { -/// \brief Specifies the working directory and command of a compilation. +/// Specifies the working directory and command of a compilation. struct CompileCommand { - CompileCommand() {} + CompileCommand() = default; CompileCommand(Twine Directory, Twine Filename, std::vector<std::string> CommandLine, Twine Output) - : Directory(Directory.str()), - Filename(Filename.str()), - CommandLine(std::move(CommandLine)), - Output(Output.str()){} + : Directory(Directory.str()), Filename(Filename.str()), + CommandLine(std::move(CommandLine)), Output(Output.str()){} - /// \brief The working directory the command was executed from. + /// The working directory the command was executed from. std::string Directory; /// The source file associated with the command. std::string Filename; - /// \brief The command line that was executed. + /// The command line that was executed. std::vector<std::string> CommandLine; /// The output file associated with the command. std::string Output; + + friend bool operator==(const CompileCommand &LHS, const CompileCommand &RHS) { + return LHS.Directory == RHS.Directory && LHS.Filename == RHS.Filename && + LHS.CommandLine == RHS.CommandLine && LHS.Output == RHS.Output; + } + + friend bool operator!=(const CompileCommand &LHS, const CompileCommand &RHS) { + return !(LHS == RHS); + } }; -/// \brief Interface for compilation databases. +/// Interface for compilation databases. /// /// A compilation database allows the user to retrieve compile command lines /// for the files in a project. @@ -74,7 +82,7 @@ class CompilationDatabase { public: virtual ~CompilationDatabase(); - /// \brief Loads a compilation database from a build directory. + /// Loads a compilation database from a build directory. /// /// Looks at the specified 'BuildDirectory' and creates a compilation database /// that allows to query compile commands for source files in the @@ -89,21 +97,21 @@ public: static std::unique_ptr<CompilationDatabase> loadFromDirectory(StringRef BuildDirectory, std::string &ErrorMessage); - /// \brief Tries to detect a compilation database location and load it. + /// 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 std::unique_ptr<CompilationDatabase> autoDetectFromSource(StringRef SourceFile, std::string &ErrorMessage); - /// \brief Tries to detect a compilation database location and load it. + /// 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 std::unique_ptr<CompilationDatabase> autoDetectFromDirectory(StringRef SourceDir, std::string &ErrorMessage); - /// \brief Returns all compile commands in which the specified file was + /// Returns all compile commands in which the specified file was /// compiled. /// /// This includes compile commands that span multiple source files. @@ -113,15 +121,15 @@ public: /// A compilation database representing the project would return both command /// lines for a.cc and b.cc and only the first command line for t.cc. virtual std::vector<CompileCommand> getCompileCommands( - StringRef FilePath) const = 0; + StringRef FilePath) const = 0; - /// \brief Returns the list of all files available in the compilation database. + /// Returns the list of all files available in the compilation database. /// /// By default, returns nothing. Implementations should override this if they /// can enumerate their source files. virtual std::vector<std::string> getAllFiles() const { return {}; } - /// \brief Returns all compile commands for all the files in the compilation + /// Returns all compile commands for all the files in the compilation /// database. /// /// FIXME: Add a layer in Tooling that provides an interface to run a tool @@ -133,7 +141,7 @@ public: virtual std::vector<CompileCommand> getAllCompileCommands() const; }; -/// \brief Interface for compilation database plugins. +/// Interface for compilation database plugins. /// /// A compilation database plugin allows the user to register custom compilation /// databases that are picked up as compilation database if the corresponding @@ -147,20 +155,20 @@ class CompilationDatabasePlugin { public: virtual ~CompilationDatabasePlugin(); - /// \brief Loads a compilation database from a build directory. + /// Loads a compilation database from a build directory. /// /// \see CompilationDatabase::loadFromDirectory(). virtual std::unique_ptr<CompilationDatabase> loadFromDirectory(StringRef Directory, std::string &ErrorMessage) = 0; }; -/// \brief A compilation database that returns a single compile command line. +/// A compilation database that returns a single compile command line. /// /// Useful when we want a tool to behave more like a compiler invocation. /// This compilation database is not enumerable: getAllFiles() returns {}. class FixedCompilationDatabase : public CompilationDatabase { public: - /// \brief Creates a FixedCompilationDatabase from the arguments after "--". + /// Creates a FixedCompilationDatabase from the arguments after "--". /// /// Parses the given command line for "--". If "--" is found, the rest of /// the arguments will make up the command line in the returned @@ -196,11 +204,11 @@ public: static std::unique_ptr<FixedCompilationDatabase> loadFromFile(StringRef Path, std::string &ErrorMsg); - /// \brief Constructs a compilation data base from a specified directory + /// Constructs a compilation data base from a specified directory /// and command line. FixedCompilationDatabase(Twine Directory, ArrayRef<std::string> CommandLine); - /// \brief Returns the given compile command. + /// Returns the given compile command. /// /// Will always return a vector with one entry that contains the directory /// and command line specified at construction with "clang-tool" as argv[0] @@ -214,7 +222,14 @@ private: std::vector<CompileCommand> CompileCommands; }; -} // end namespace tooling -} // end namespace clang +/// Returns a wrapped CompilationDatabase that defers to the provided one, +/// but getCompileCommands() will infer commands for unknown files. +/// The return value of getAllFiles() or getAllCompileCommands() is unchanged. +/// See InterpolatingCompilationDatabase.cpp for details on heuristics. +std::unique_ptr<CompilationDatabase> + inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>); + +} // namespace tooling +} // namespace clang -#endif +#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASE_H diff --git a/include/clang/Tooling/CompilationDatabasePluginRegistry.h b/include/clang/Tooling/CompilationDatabasePluginRegistry.h index 7323ec8974036..051a08e2a91e8 100644 --- a/include/clang/Tooling/CompilationDatabasePluginRegistry.h +++ b/include/clang/Tooling/CompilationDatabasePluginRegistry.h @@ -1,4 +1,4 @@ -//===--- CompilationDatabasePluginRegistry.h - ------------------*- C++ -*-===// +//===- CompilationDatabasePluginRegistry.h ----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,12 +16,10 @@ namespace clang { namespace tooling { -class CompilationDatabasePlugin; +using CompilationDatabasePluginRegistry = + llvm::Registry<CompilationDatabasePlugin>; -typedef llvm::Registry<CompilationDatabasePlugin> - CompilationDatabasePluginRegistry; +} // namespace tooling +} // namespace clang -} // end namespace tooling -} // end namespace clang - -#endif +#endif // LLVM_CLANG_TOOLING_COMPILATIONDATABASEPLUGINREGISTRY_H diff --git a/include/clang/Tooling/Core/Diagnostic.h b/include/clang/Tooling/Core/Diagnostic.h index b4920d4fe456d..ddb40103e2119 100644 --- a/include/clang/Tooling/Core/Diagnostic.h +++ b/include/clang/Tooling/Core/Diagnostic.h @@ -27,13 +27,13 @@ namespace clang { namespace tooling { -/// \brief Represents the diagnostic message with the error message associated +/// Represents the diagnostic message with the error message associated /// and the information on the location of the problem. struct DiagnosticMessage { DiagnosticMessage(llvm::StringRef Message = ""); - /// \brief Constructs a diagnostic message with anoffset to the diagnostic - /// within the file where the problem occured. + /// Constructs a diagnostic message with anoffset to the diagnostic + /// within the file where the problem occurred. /// /// \param Loc Should be a file location, it is not meaningful for a macro /// location. @@ -45,7 +45,7 @@ struct DiagnosticMessage { unsigned FileOffset; }; -/// \brief Represents the diagnostic with the level of severity and possible +/// Represents the diagnostic with the level of severity and possible /// fixes to be applied. struct Diagnostic { enum Level { @@ -63,22 +63,22 @@ struct Diagnostic { const SmallVector<DiagnosticMessage, 1> &Notes, Level DiagLevel, llvm::StringRef BuildDirectory); - /// \brief Name identifying the Diagnostic. + /// Name identifying the Diagnostic. std::string DiagnosticName; - /// \brief Message associated to the diagnostic. + /// Message associated to the diagnostic. DiagnosticMessage Message; - /// \brief Fixes to apply, grouped by file path. + /// Fixes to apply, grouped by file path. llvm::StringMap<Replacements> Fix; - /// \brief Potential notes about the diagnostic. + /// Potential notes about the diagnostic. SmallVector<DiagnosticMessage, 1> Notes; - /// \brief Diagnostic level. Can indicate either an error or a warning. + /// Diagnostic level. Can indicate either an error or a warning. Level DiagLevel; - /// \brief A build directory of the diagnostic source file. + /// A build directory of the diagnostic source file. /// /// It's an absolute path which is `directory` field of the source file in /// compilation database. If users don't specify the compilation database @@ -88,7 +88,7 @@ struct Diagnostic { std::string BuildDirectory; }; -/// \brief Collection of Diagnostics generated from a single translation unit. +/// Collection of Diagnostics generated from a single translation unit. struct TranslationUnitDiagnostics { /// Name of the main source for the translation unit. std::string MainSourceFile; diff --git a/include/clang/Tooling/Core/Replacement.h b/include/clang/Tooling/Core/Replacement.h index 3fea9aee604ca..ba11ca4a7fee2 100644 --- a/include/clang/Tooling/Core/Replacement.h +++ b/include/clang/Tooling/Core/Replacement.h @@ -1,4 +1,4 @@ -//===--- Replacement.h - Framework for clang refactoring tools --*- C++ -*-===// +//===- Replacement.h - Framework for clang refactoring tools ----*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -19,32 +19,35 @@ #ifndef LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H #define LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H -#include "clang/Basic/FileManager.h" #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compiler.h" #include "llvm/Support/Error.h" #include "llvm/Support/raw_ostream.h" #include <map> #include <set> #include <string> #include <system_error> +#include <utility> #include <vector> namespace clang { +class FileManager; class Rewriter; +class SourceManager; namespace tooling { -/// \brief A source range independent of the \c SourceManager. +/// A source range independent of the \c SourceManager. class Range { public: - Range() : Offset(0), Length(0) {} + Range() = default; Range(unsigned Offset, unsigned Length) : Offset(Offset), Length(Length) {} - /// \brief Accessors. + /// Accessors. /// @{ unsigned getOffset() const { return Offset; } unsigned getLength() const { return Length; } @@ -52,38 +55,38 @@ public: /// \name Range Predicates /// @{ - /// \brief Whether this range overlaps with \p RHS or not. + /// 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. + /// Whether this range contains \p RHS or not. bool contains(Range RHS) const { return RHS.Offset >= Offset && (RHS.Offset + RHS.Length) <= (Offset + Length); } - /// \brief Whether this range equals to \p RHS or not. + /// Whether this range equals to \p RHS or not. bool operator==(const Range &RHS) const { return Offset == RHS.getOffset() && Length == RHS.getLength(); } /// @} private: - unsigned Offset; - unsigned Length; + unsigned Offset = 0; + unsigned Length = 0; }; -/// \brief A text replacement. +/// 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. + /// Creates an invalid (not applicable) replacement. Replacement(); - /// \brief Creates a replacement of the range [Offset, Offset+Length) in + /// Creates a replacement of the range [Offset, Offset+Length) in /// FilePath with ReplacementText. /// /// \param FilePath A source file accessible via a SourceManager. @@ -92,28 +95,28 @@ public: Replacement(StringRef FilePath, unsigned Offset, unsigned Length, StringRef ReplacementText); - /// \brief Creates a Replacement of the range [Start, Start+Length) with + /// 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. + /// Creates a Replacement of the given range with ReplacementText. Replacement(const SourceManager &Sources, const CharSourceRange &Range, StringRef ReplacementText, const LangOptions &LangOpts = LangOptions()); - /// \brief Creates a Replacement of the node with ReplacementText. + /// Creates a Replacement of the node with ReplacementText. template <typename Node> Replacement(const SourceManager &Sources, const Node &NodeToReplace, StringRef ReplacementText, const LangOptions &LangOpts = LangOptions()); - /// \brief Returns whether this replacement can be applied to a file. + /// 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. + /// Accessors. /// @{ StringRef getFilePath() const { return FilePath; } unsigned getOffset() const { return ReplacementRange.getOffset(); } @@ -121,10 +124,10 @@ public: StringRef getReplacementText() const { return ReplacementText; } /// @} - /// \brief Applies the replacement on the Rewriter. + /// Applies the replacement on the Rewriter. bool apply(Rewriter &Rewrite) const; - /// \brief Returns a human readable string representation. + /// Returns a human readable string representation. std::string toString() const; private: @@ -147,17 +150,17 @@ enum class replacement_error { insert_conflict, }; -/// \brief Carries extra error information in replacement-related llvm::Error, +/// Carries extra error information in replacement-related llvm::Error, /// e.g. fail applying replacements and replacements conflict. class ReplacementError : public llvm::ErrorInfo<ReplacementError> { public: ReplacementError(replacement_error Err) : Err(Err) {} - /// \brief Constructs an error related to an existing replacement. + /// Constructs an error related to an existing replacement. ReplacementError(replacement_error Err, Replacement Existing) : Err(Err), ExistingReplacement(std::move(Existing)) {} - /// \brief Constructs an error related to a new replacement and an existing + /// Constructs an error related to a new replacement and an existing /// replacement in a set of replacements. ReplacementError(replacement_error Err, Replacement New, Replacement Existing) : Err(Err), NewReplacement(std::move(New)), @@ -186,35 +189,37 @@ private: } replacement_error Err; + // A new replacement, which is to expected be added into a set of // replacements, that is causing problem. llvm::Optional<Replacement> NewReplacement; + // An existing replacement in a replacements set that is causing problem. llvm::Optional<Replacement> ExistingReplacement; }; -/// \brief Less-than operator between two Replacements. +/// Less-than operator between two Replacements. bool operator<(const Replacement &LHS, const Replacement &RHS); -/// \brief Equal-to operator between two Replacements. +/// Equal-to operator between two Replacements. bool operator==(const Replacement &LHS, const Replacement &RHS); -/// \brief Maintains a set of replacements that are conflict-free. +/// Maintains a set of replacements that are conflict-free. /// Two replacements are considered conflicts if they overlap or have the same /// offset (i.e. order-dependent). class Replacements { - private: - typedef std::set<Replacement> ReplacementsImpl; +private: + using ReplacementsImpl = std::set<Replacement>; - public: - typedef ReplacementsImpl::const_iterator const_iterator; - typedef ReplacementsImpl::const_reverse_iterator const_reverse_iterator; +public: + using const_iterator = ReplacementsImpl::const_iterator; + using const_reverse_iterator = ReplacementsImpl::const_reverse_iterator; Replacements() = default; explicit Replacements(const Replacement &R) { Replaces.insert(R); } - /// \brief Adds a new replacement \p R to the current set of replacements. + /// Adds a new replacement \p R to the current set of replacements. /// \p R must have the same file path as all existing replacements. /// Returns `success` if the replacement is successfully inserted; otherwise, /// it returns an llvm::Error, i.e. there is a conflict between R and the @@ -253,7 +258,7 @@ class Replacements { /// category of replacements. llvm::Error add(const Replacement &R); - /// \brief Merges \p Replaces into the current replacements. \p Replaces + /// Merges \p Replaces into the current replacements. \p Replaces /// refers to code after applying the current replacements. LLVM_NODISCARD Replacements merge(const Replacements &Replaces) const; @@ -283,7 +288,6 @@ class Replacements { return Replaces == RHS.Replaces; } - private: Replacements(const_iterator Begin, const_iterator End) : Replaces(Begin, End) {} @@ -307,7 +311,7 @@ private: ReplacementsImpl Replaces; }; -/// \brief Apply all replacements in \p Replaces to the Rewriter \p Rewrite. +/// Apply all replacements in \p Replaces to the Rewriter \p Rewrite. /// /// Replacement applications happen independently of the success of /// other applications. @@ -315,7 +319,7 @@ private: /// \returns true if all replacements apply. false otherwise. bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); -/// \brief Applies all replacements in \p Replaces to \p Code. +/// Applies all replacements in \p Replaces to \p Code. /// /// This completely ignores the path stored in each replacement. If all /// replacements are applied successfully, this returns the code with @@ -325,14 +329,15 @@ bool applyAllReplacements(const Replacements &Replaces, Rewriter &Rewrite); llvm::Expected<std::string> applyAllReplacements(StringRef Code, const Replacements &Replaces); -/// \brief Collection of Replacements generated from a single translation unit. +/// Collection of Replacements generated from a single translation unit. struct TranslationUnitReplacements { /// Name of the main source for the translation unit. std::string MainSourceFile; + std::vector<Replacement> Replacements; }; -/// \brief Calculates the new ranges after \p Replaces are applied. These +/// Calculates the new ranges after \p Replaces are applied. These /// include both the original \p Ranges and the affected ranges of \p Replaces /// in the new code. /// @@ -344,7 +349,7 @@ std::vector<Range> calculateRangesAfterReplacements(const Replacements &Replaces, const std::vector<Range> &Ranges); -/// \brief If there are multiple <File, Replacements> pairs with the same file +/// If there are multiple <File, Replacements> pairs with the same file /// entry, we only keep one pair and discard the rest. /// If a file does not exist, its corresponding replacements will be ignored. std::map<std::string, Replacements> groupReplacementsByFile( @@ -360,7 +365,8 @@ Replacement::Replacement(const SourceManager &Sources, setFromSourceRange(Sources, Range, ReplacementText, LangOpts); } -} // end namespace tooling -} // end namespace clang +} // namespace tooling + +} // namespace clang #endif // LLVM_CLANG_TOOLING_CORE_REPLACEMENT_H diff --git a/include/clang/Tooling/DiagnosticsYaml.h b/include/clang/Tooling/DiagnosticsYaml.h index 4d6ff063641b9..bf0732bf0042e 100644 --- a/include/clang/Tooling/DiagnosticsYaml.h +++ b/include/clang/Tooling/DiagnosticsYaml.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines the structure of a YAML document for serializing +/// This file defines the structure of a YAML document for serializing /// diagnostics. /// //===----------------------------------------------------------------------===// @@ -27,7 +27,7 @@ namespace llvm { namespace yaml { template <> struct MappingTraits<clang::tooling::Diagnostic> { - /// \brief Helper to (de)serialize a Diagnostic since we don't have direct + /// Helper to (de)serialize a Diagnostic since we don't have direct /// access to its data members. class NormalizedDiagnostic { public: @@ -80,7 +80,7 @@ template <> struct MappingTraits<clang::tooling::Diagnostic> { } }; -/// \brief Specialized MappingTraits to describe how a +/// Specialized MappingTraits to describe how a /// TranslationUnitDiagnostics is (de)serialized. template <> struct MappingTraits<clang::tooling::TranslationUnitDiagnostics> { static void mapping(IO &Io, clang::tooling::TranslationUnitDiagnostics &Doc) { diff --git a/include/clang/Tooling/Execution.h b/include/clang/Tooling/Execution.h index 1a44c4788c492..68aef53cb58f3 100644 --- a/include/clang/Tooling/Execution.h +++ b/include/clang/Tooling/Execution.h @@ -32,11 +32,12 @@ #include "clang/Tooling/Tooling.h" #include "llvm/Support/Error.h" #include "llvm/Support/Registry.h" +#include "llvm/Support/StringSaver.h" namespace clang { namespace tooling { -/// \brief An abstraction for the result of a tool execution. For example, the +/// An abstraction for the result of a tool execution. For example, the /// underlying result can be in-memory or on-disk. /// /// Results should be string key-value pairs. For example, a refactoring tool @@ -45,32 +46,41 @@ class ToolResults { public: virtual ~ToolResults() = default; virtual void addResult(StringRef Key, StringRef Value) = 0; - virtual std::vector<std::pair<std::string, std::string>> AllKVResults() = 0; + virtual std::vector<std::pair<llvm::StringRef, llvm::StringRef>> + AllKVResults() = 0; virtual void forEachResult( llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) = 0; }; +/// Stores the key-value results in memory. It maintains the lifetime of +/// the result. Clang tools using this class are expected to generate a small +/// set of different results, or a large set of duplicated results. class InMemoryToolResults : public ToolResults { public: + InMemoryToolResults() : Strings(Arena) {} void addResult(StringRef Key, StringRef Value) override; - std::vector<std::pair<std::string, std::string>> AllKVResults() override; + std::vector<std::pair<llvm::StringRef, llvm::StringRef>> + AllKVResults() override; void forEachResult(llvm::function_ref<void(StringRef Key, StringRef Value)> Callback) override; private: - std::vector<std::pair<std::string, std::string>> KVResults; + llvm::BumpPtrAllocator Arena; + llvm::UniqueStringSaver Strings; + + std::vector<std::pair<llvm::StringRef, llvm::StringRef>> KVResults; }; -/// \brief The context of an execution, including the information about +/// The context of an execution, including the information about /// compilation and results. class ExecutionContext { public: virtual ~ExecutionContext() {} - /// \brief Initializes a context. This does not take ownership of `Results`. + /// Initializes a context. This does not take ownership of `Results`. explicit ExecutionContext(ToolResults *Results) : Results(Results) {} - /// \brief Adds a KV pair to the result container of this execution. + /// Adds a KV pair to the result container of this execution. void reportResult(StringRef Key, StringRef Value); // Returns the source control system's revision number if applicable. @@ -88,7 +98,7 @@ private: ToolResults *Results; }; -/// \brief Interface for executing clang frontend actions. +/// Interface for executing clang frontend actions. /// /// This can be extended to support running tool actions in different /// execution mode, e.g. on a specific set of TUs or many TUs in parallel. @@ -101,54 +111,54 @@ class ToolExecutor { public: virtual ~ToolExecutor() {} - /// \brief Returns the name of a specific executor. + /// Returns the name of a specific executor. virtual StringRef getExecutorName() const = 0; - /// \brief Executes each action with a corresponding arguments adjuster. + /// Executes each action with a corresponding arguments adjuster. virtual llvm::Error execute(llvm::ArrayRef< std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> Actions) = 0; - /// \brief Convenient functions for the above `execute`. + /// Convenient functions for the above `execute`. llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action); /// Executes an action with an argument adjuster. llvm::Error execute(std::unique_ptr<FrontendActionFactory> Action, ArgumentsAdjuster Adjuster); - /// \brief Returns a reference to the execution context. + /// Returns a reference to the execution context. /// /// This should be passed to tool callbacks, and tool callbacks should report /// results via the returned context. virtual ExecutionContext *getExecutionContext() = 0; - /// \brief Returns a reference to the result container. + /// Returns a reference to the result container. /// /// NOTE: This should only be used after the execution finishes. Tool /// callbacks should report results via `ExecutionContext` instead. virtual ToolResults *getToolResults() = 0; - /// \brief Map a virtual file to be used while running the tool. + /// Map a virtual file to be used while running the tool. /// /// \param FilePath The path at which the content will be mapped. /// \param Content A buffer of the file's content. virtual void mapVirtualFile(StringRef FilePath, StringRef Content) = 0; }; -/// \brief Interface for factories that create specific executors. This is also +/// Interface for factories that create specific executors. This is also /// used as a plugin to be registered into ToolExecutorPluginRegistry. class ToolExecutorPlugin { public: virtual ~ToolExecutorPlugin() {} - /// \brief Create an `ToolExecutor`. + /// Create an `ToolExecutor`. /// /// `OptionsParser` can be consumed (e.g. moved) if the creation succeeds. virtual llvm::Expected<std::unique_ptr<ToolExecutor>> create(CommonOptionsParser &OptionsParser) = 0; }; -/// \brief This creates a ToolExecutor that is in the global registry based on +/// This creates a ToolExecutor that is in the global registry based on /// commandline arguments. /// /// This picks the right executor based on the `--executor` option. This parses diff --git a/include/clang/Tooling/FileMatchTrie.h b/include/clang/Tooling/FileMatchTrie.h index 882979ef8ff64..11d12f3d30ce0 100644 --- a/include/clang/Tooling/FileMatchTrie.h +++ b/include/clang/Tooling/FileMatchTrie.h @@ -1,4 +1,4 @@ -//===--- FileMatchTrie.h - --------------------------------------*- C++ -*-===// +//===- FileMatchTrie.h ------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,22 +16,21 @@ #define LLVM_CLANG_TOOLING_FILEMATCHTRIE_H #include "clang/Basic/LLVM.h" +#include "llvm/ADT/StringRef.h" #include <memory> -namespace llvm { -class StringRef; -} - namespace clang { namespace tooling { +class FileMatchTrieNode; + struct PathComparator { - virtual ~PathComparator() {} + virtual ~PathComparator() = default; + virtual bool equivalent(StringRef FileA, StringRef FileB) const = 0; }; -class FileMatchTrieNode; -/// \brief A trie to efficiently match against the entries of the compilation +/// A trie to efficiently match against the entries of the compilation /// database in order of matching suffix length. /// /// When a clang tool is supposed to operate on a specific file, we have to @@ -59,32 +58,32 @@ class FileMatchTrie { public: FileMatchTrie(); - /// \brief Construct a new \c FileMatchTrie with the given \c PathComparator. + /// Construct a new \c FileMatchTrie with the given \c PathComparator. /// /// The \c FileMatchTrie takes ownership of 'Comparator'. Used for testing. FileMatchTrie(PathComparator* Comparator); ~FileMatchTrie(); - /// \brief Insert a new absolute path. Relative paths are ignored. + /// Insert a new absolute path. Relative paths are ignored. void insert(StringRef NewPath); - /// \brief Finds the corresponding file in this trie. + /// Finds the corresponding file in this trie. /// /// Returns file name stored in this trie that is equivalent to 'FileName' /// according to 'Comparator', if it can be uniquely identified. If there - /// are no matches an empty \c StringRef is returned. If there are ambigious + /// are no matches an empty \c StringRef is returned. If there are ambiguous /// matches, an empty \c StringRef is returned and a corresponding message /// written to 'Error'. StringRef findEquivalent(StringRef FileName, raw_ostream &Error) const; + private: FileMatchTrieNode *Root; std::unique_ptr<PathComparator> Comparator; }; +} // namespace tooling +} // namespace clang -} // end namespace tooling -} // end namespace clang - -#endif +#endif // LLVM_CLANG_TOOLING_FILEMATCHTRIE_H diff --git a/include/clang/Tooling/FixIt.h b/include/clang/Tooling/FixIt.h index c1e508849280b..b36f378d6361c 100644 --- a/include/clang/Tooling/FixIt.h +++ b/include/clang/Tooling/FixIt.h @@ -29,35 +29,35 @@ namespace fixit { namespace internal { StringRef getText(SourceRange Range, const ASTContext &Context); -/// \brief Returns the SourceRange of a SourceRange. This identity function is +/// Returns the SourceRange of a SourceRange. This identity function is /// used by the following template abstractions. inline SourceRange getSourceRange(const SourceRange &Range) { return Range; } -/// \brief Returns the SourceRange of the token at Location \p Loc. +/// Returns the SourceRange of the token at Location \p Loc. inline SourceRange getSourceRange(const SourceLocation &Loc) { return SourceRange(Loc); } -/// \brief Returns the SourceRange of an given Node. \p Node is typically a +/// Returns the SourceRange of an given Node. \p Node is typically a /// 'Stmt', 'Expr' or a 'Decl'. template <typename T> SourceRange getSourceRange(const T &Node) { return Node.getSourceRange(); } } // end namespace internal -// \brief Returns a textual representation of \p Node. +// Returns a textual representation of \p Node. template <typename T> StringRef getText(const T &Node, const ASTContext &Context) { return internal::getText(internal::getSourceRange(Node), Context); } -// \brief Returns a FixItHint to remove \p Node. +// Returns a FixItHint to remove \p Node. // TODO: Add support for related syntactical elements (i.e. comments, ...). template <typename T> FixItHint createRemoval(const T &Node) { return FixItHint::CreateRemoval(internal::getSourceRange(Node)); } -// \brief Returns a FixItHint to replace \p Destination by \p Source. +// Returns a FixItHint to replace \p Destination by \p Source. template <typename D, typename S> FixItHint createReplacement(const D &Destination, const S &Source, const ASTContext &Context) { @@ -65,7 +65,7 @@ FixItHint createReplacement(const D &Destination, const S &Source, getText(Source, Context)); } -// \brief Returns a FixItHint to replace \p Destination by \p Source. +// Returns a FixItHint to replace \p Destination by \p Source. template <typename D> FixItHint createReplacement(const D &Destination, StringRef Source) { return FixItHint::CreateReplacement(internal::getSourceRange(Destination), diff --git a/include/clang/Tooling/Inclusions/HeaderIncludes.h b/include/clang/Tooling/Inclusions/HeaderIncludes.h new file mode 100644 index 0000000000000..d99a3283168ce --- /dev/null +++ b/include/clang/Tooling/Inclusions/HeaderIncludes.h @@ -0,0 +1,137 @@ +//===--- HeaderIncludes.h - Insert/Delete #includes for C++ code--*- 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_TOOLING_INCLUSIONS_HEADERINCLUDES_H +#define LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H + +#include "clang/Basic/SourceManager.h" +#include "clang/Tooling/Core/Replacement.h" +#include "clang/Tooling/Inclusions/IncludeStyle.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/Regex.h" +#include <unordered_map> + +namespace clang { +namespace tooling { + +/// This class manages priorities of C++ #include categories and calculates +/// priorities for headers. +/// FIXME(ioeric): move this class into implementation file when clang-format's +/// include sorting functions are also moved here. +class IncludeCategoryManager { +public: + IncludeCategoryManager(const IncludeStyle &Style, StringRef FileName); + + /// Returns the priority of the category which \p IncludeName belongs to. + /// If \p CheckMainHeader is true and \p IncludeName is a main header, returns + /// 0. Otherwise, returns the priority of the matching category or INT_MAX. + /// NOTE: this API is not thread-safe! + int getIncludePriority(StringRef IncludeName, bool CheckMainHeader) const; + +private: + bool isMainHeader(StringRef IncludeName) const; + + const IncludeStyle Style; + bool IsMainFile; + std::string FileName; + // This refers to a substring in FileName. + StringRef FileStem; + // Regex is not thread-safe. + mutable SmallVector<llvm::Regex, 4> CategoryRegexs; +}; + +/// Generates replacements for inserting or deleting #include directives in a +/// file. +class HeaderIncludes { +public: + HeaderIncludes(llvm::StringRef FileName, llvm::StringRef Code, + const IncludeStyle &Style); + + /// Inserts an #include directive of \p Header into the code. If \p IsAngled + /// is true, \p Header will be quoted with <> in the directive; otherwise, it + /// will be quoted with "". + /// + /// When searching for points to insert new header, this ignores #include's + /// after the #include block(s) in the beginning of a file to avoid inserting + /// headers into code sections where new #include's should not be added by + /// default. These code sections include: + /// - raw string literals (containing #include). + /// - #if blocks. + /// - Special #include's among declarations (e.g. functions). + /// + /// Returns a replacement that inserts the new header into a suitable #include + /// block of the same category. This respects the order of the existing + /// #includes in the block; if the existing #includes are not already sorted, + /// this will simply insert the #include in front of the first #include of the + /// same category in the code that should be sorted after \p IncludeName. If + /// \p IncludeName already exists (with exactly the same spelling), this + /// returns None. + llvm::Optional<tooling::Replacement> insert(llvm::StringRef Header, + bool IsAngled) const; + + /// Removes all existing #includes of \p Header quoted with <> if \p IsAngled + /// is true or "" if \p IsAngled is false. + /// This doesn't resolve the header file path; it only deletes #includes with + /// exactly the same spelling. + tooling::Replacements remove(llvm::StringRef Header, bool IsAngled) const; + +private: + struct Include { + Include(StringRef Name, tooling::Range R) : Name(Name), R(R) {} + + // An include header quoted with either <> or "". + std::string Name; + // The range of the whole line of include directive including any eading + // whitespaces and trailing comment. + tooling::Range R; + }; + + void addExistingInclude(Include IncludeToAdd, unsigned NextLineOffset); + + std::string FileName; + std::string Code; + + // Map from include name (quotation trimmed) to a list of existing includes + // (in case there are more than one) with the name in the current file. <x> + // and "x" will be treated as the same header when deleting #includes. + llvm::StringMap<llvm::SmallVector<Include, 1>> ExistingIncludes; + + /// Map from priorities of #include categories to all #includes in the same + /// category. This is used to find #includes of the same category when + /// inserting new #includes. #includes in the same categories are sorted in + /// in the order they appear in the source file. + /// See comment for "FormatStyle::IncludeCategories" for details about include + /// priorities. + std::unordered_map<int, llvm::SmallVector<const Include *, 8>> + IncludesByPriority; + + int FirstIncludeOffset; + // All new headers should be inserted after this offset (e.g. after header + // guards, file comment). + unsigned MinInsertOffset; + // Max insertion offset in the original code. For example, we want to avoid + // inserting new #includes into the actual code section (e.g. after a + // declaration). + unsigned MaxInsertOffset; + IncludeCategoryManager Categories; + // Record the offset of the end of the last include in each category. + std::unordered_map<int, int> CategoryEndOffsets; + + // All possible priorities. + std::set<int> Priorities; + + // Matches a whole #include directive. + llvm::Regex IncludeRegex; +}; + + +} // namespace tooling +} // namespace clang + +#endif // LLVM_CLANG_TOOLING_INCLUSIONS_HEADERINCLUDES_H diff --git a/include/clang/Tooling/Inclusions/IncludeStyle.h b/include/clang/Tooling/Inclusions/IncludeStyle.h new file mode 100644 index 0000000000000..a093dff277288 --- /dev/null +++ b/include/clang/Tooling/Inclusions/IncludeStyle.h @@ -0,0 +1,139 @@ +//===--- IncludeStyle.h - Style of C++ #include directives -------*- 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_TOOLING_INCLUSIONS_INCLUDESTYLE_H +#define LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H + +#include "llvm/Support/YAMLTraits.h" +#include <string> +#include <vector> + +namespace clang { +namespace tooling { + +/// Style for sorting and grouping C++ #include directives. +struct IncludeStyle { + /// Styles for sorting multiple ``#include`` blocks. + enum IncludeBlocksStyle { + /// Sort each ``#include`` block separately. + /// \code + /// #include "b.h" into #include "b.h" + /// + /// #include <lib/main.h> #include "a.h" + /// #include "a.h" #include <lib/main.h> + /// \endcode + IBS_Preserve, + /// Merge multiple ``#include`` blocks together and sort as one. + /// \code + /// #include "b.h" into #include "a.h" + /// #include "b.h" + /// #include <lib/main.h> #include <lib/main.h> + /// #include "a.h" + /// \endcode + IBS_Merge, + /// Merge multiple ``#include`` blocks together and sort as one. + /// Then split into groups based on category priority. See + /// ``IncludeCategories``. + /// \code + /// #include "b.h" into #include "a.h" + /// #include "b.h" + /// #include <lib/main.h> + /// #include "a.h" #include <lib/main.h> + /// \endcode + IBS_Regroup, + }; + + /// Dependent on the value, multiple ``#include`` blocks can be sorted + /// as one and divided based on category. + IncludeBlocksStyle IncludeBlocks; + + /// See documentation of ``IncludeCategories``. + struct IncludeCategory { + /// The regular expression that this category matches. + std::string Regex; + /// The priority to assign to this category. + int Priority; + bool operator==(const IncludeCategory &Other) const { + return Regex == Other.Regex && Priority == Other.Priority; + } + }; + + /// Regular expressions denoting the different ``#include`` categories + /// used for ordering ``#includes``. + /// + /// `POSIX extended + /// <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html>`_ + /// regular expressions are supported. + /// + /// These regular expressions are matched against the filename of an include + /// (including the <> or "") in order. The value belonging to the first + /// matching regular expression is assigned and ``#includes`` are sorted first + /// according to increasing category number and then alphabetically within + /// each category. + /// + /// If none of the regular expressions match, INT_MAX is assigned as + /// category. The main header for a source file automatically gets category 0. + /// so that it is generally kept at the beginning of the ``#includes`` + /// (http://llvm.org/docs/CodingStandards.html#include-style). However, you + /// can also assign negative priorities if you have certain headers that + /// always need to be first. + /// + /// To configure this in the .clang-format file, use: + /// \code{.yaml} + /// IncludeCategories: + /// - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + /// Priority: 2 + /// - Regex: '^(<|"(gtest|gmock|isl|json)/)' + /// Priority: 3 + /// - Regex: '<[[:alnum:].]+>' + /// Priority: 4 + /// - Regex: '.*' + /// Priority: 1 + /// \endcode + std::vector<IncludeCategory> IncludeCategories; + + /// Specify a regular expression of suffixes that are allowed in the + /// file-to-main-include mapping. + /// + /// When guessing whether a #include is the "main" include (to assign + /// category 0, see above), use this regex of allowed suffixes to the header + /// stem. A partial match is done, so that: + /// - "" means "arbitrary suffix" + /// - "$" means "no suffix" + /// + /// For example, if configured to "(_test)?$", then a header a.h would be seen + /// as the "main" include in both a.cc and a_test.cc. + std::string IncludeIsMainRegex; +}; + +} // namespace tooling +} // namespace clang + +LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::IncludeStyle::IncludeCategory) + +namespace llvm { +namespace yaml { + +template <> +struct MappingTraits<clang::tooling::IncludeStyle::IncludeCategory> { + static void mapping(IO &IO, + clang::tooling::IncludeStyle::IncludeCategory &Category); +}; + +template <> +struct ScalarEnumerationTraits< + clang::tooling::IncludeStyle::IncludeBlocksStyle> { + static void + enumeration(IO &IO, clang::tooling::IncludeStyle::IncludeBlocksStyle &Value); +}; + +} // namespace yaml +} // namespace llvm + +#endif // LLVM_CLANG_TOOLING_INCLUSIONS_INCLUDESTYLE_H diff --git a/include/clang/Tooling/JSONCompilationDatabase.h b/include/clang/Tooling/JSONCompilationDatabase.h index 9a6866240b08c..882afc6d9ece2 100644 --- a/include/clang/Tooling/JSONCompilationDatabase.h +++ b/include/clang/Tooling/JSONCompilationDatabase.h @@ -1,4 +1,4 @@ -//===--- JSONCompilationDatabase.h - ----------------------------*- C++ -*-===// +//===- JSONCompilationDatabase.h --------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -18,6 +18,7 @@ #include "clang/Basic/LLVM.h" #include "clang/Tooling/CompilationDatabase.h" #include "clang/Tooling/FileMatchTrie.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/MemoryBuffer.h" @@ -25,12 +26,14 @@ #include "llvm/Support/YAMLParser.h" #include <memory> #include <string> +#include <tuple> +#include <utility> #include <vector> namespace clang { namespace tooling { -/// \brief A JSON based compilation database. +/// A JSON based compilation database. /// /// JSON compilation database files must contain a list of JSON objects which /// provide the command lines in the attributes 'directory', 'command', @@ -58,7 +61,7 @@ namespace tooling { enum class JSONCommandLineSyntax { Windows, Gnu, AutoDetect }; class JSONCompilationDatabase : public CompilationDatabase { public: - /// \brief Loads a JSON compilation database from the specified file. + /// Loads a JSON compilation database from the specified file. /// /// Returns NULL and sets ErrorMessage if the database could not be /// loaded from the given file. @@ -66,14 +69,14 @@ public: loadFromFile(StringRef FilePath, std::string &ErrorMessage, JSONCommandLineSyntax Syntax); - /// \brief Loads a JSON compilation database from a data buffer. + /// Loads a JSON compilation database from a data buffer. /// /// Returns NULL and sets ErrorMessage if the database could not be loaded. static std::unique_ptr<JSONCompilationDatabase> loadFromBuffer(StringRef DatabaseString, std::string &ErrorMessage, JSONCommandLineSyntax Syntax); - /// \brief Returns all compile commands in which the specified file was + /// Returns all compile commands in which the specified file was /// compiled. /// /// FIXME: Currently FilePath must be an absolute path inside the @@ -81,23 +84,23 @@ public: std::vector<CompileCommand> getCompileCommands(StringRef FilePath) const override; - /// \brief Returns the list of all files available in the compilation database. + /// Returns the list of all files available in the compilation database. /// /// These are the 'file' entries of the JSON objects. std::vector<std::string> getAllFiles() const override; - /// \brief Returns all compile commands for all the files in the compilation + /// Returns all compile commands for all the files in the compilation /// database. std::vector<CompileCommand> getAllCompileCommands() const override; private: - /// \brief Constructs a JSON compilation database on a memory buffer. + /// Constructs a JSON compilation database on a memory buffer. JSONCompilationDatabase(std::unique_ptr<llvm::MemoryBuffer> Database, JSONCommandLineSyntax Syntax) : Database(std::move(Database)), Syntax(Syntax), YAMLStream(this->Database->getBuffer(), SM) {} - /// \brief Parses the database file and creates the index. + /// Parses the database file and creates the index. /// /// Returns whether parsing succeeded. Sets ErrorMessage if parsing /// failed. @@ -110,12 +113,12 @@ private: // Otherwise, each entry in the command line vector is a literal // argument to the compiler. // The output field may be a nullptr. - typedef std::tuple<llvm::yaml::ScalarNode *, - llvm::yaml::ScalarNode *, - std::vector<llvm::yaml::ScalarNode *>, - llvm::yaml::ScalarNode *> CompileCommandRef; + using CompileCommandRef = + std::tuple<llvm::yaml::ScalarNode *, llvm::yaml::ScalarNode *, + std::vector<llvm::yaml::ScalarNode *>, + llvm::yaml::ScalarNode *>; - /// \brief Converts the given array of CompileCommandRefs to CompileCommands. + /// Converts the given array of CompileCommandRefs to CompileCommands. void getCommands(ArrayRef<CompileCommandRef> CommandsRef, std::vector<CompileCommand> &Commands) const; @@ -134,7 +137,7 @@ private: llvm::yaml::Stream YAMLStream; }; -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang -#endif +#endif // LLVM_CLANG_TOOLING_JSONCOMPILATIONDATABASE_H diff --git a/include/clang/Tooling/Refactoring.h b/include/clang/Tooling/Refactoring.h index bc95c3b09ec2d..64b018ea26c2c 100644 --- a/include/clang/Tooling/Refactoring.h +++ b/include/clang/Tooling/Refactoring.h @@ -30,7 +30,7 @@ class Rewriter; namespace tooling { -/// \brief A tool to run refactorings. +/// A tool to run refactorings. /// /// This is a refactoring specific version of \see ClangTool. FrontendActions /// passed to run() and runAndSave() should add replacements to @@ -43,17 +43,17 @@ public: std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>()); - /// \brief Returns the file path to replacements map to which replacements + /// Returns the file path to replacements map to which replacements /// should be added during the run of the tool. std::map<std::string, Replacements> &getReplacements(); - /// \brief Call run(), apply all generated replacements, and immediately save + /// Call run(), apply all generated replacements, and immediately save /// the results to disk. /// /// \returns 0 upon success. Non-zero upon failure. int runAndSave(FrontendActionFactory *ActionFactory); - /// \brief Apply all stored replacements to the given Rewriter. + /// Apply all stored replacements to the given Rewriter. /// /// FileToReplaces will be deduplicated with `groupReplacementsByFile` before /// application. @@ -65,14 +65,14 @@ public: bool applyAllReplacements(Rewriter &Rewrite); private: - /// \brief Write all refactored files to disk. + /// Write all refactored files to disk. int saveRewrittenFiles(Rewriter &Rewrite); private: std::map<std::string, Replacements> FileToReplaces; }; -/// \brief Groups \p Replaces by the file path and applies each group of +/// Groups \p Replaces by the file path and applies each group of /// Replacements on the related file in \p Rewriter. In addition to applying /// given Replacements, this function also formats the changed code. /// diff --git a/include/clang/Tooling/Refactoring/AtomicChange.h b/include/clang/Tooling/Refactoring/AtomicChange.h index 8a468a6de84ef..bfe042fc53c52 100644 --- a/include/clang/Tooling/Refactoring/AtomicChange.h +++ b/include/clang/Tooling/Refactoring/AtomicChange.h @@ -24,7 +24,7 @@ namespace clang { namespace tooling { -/// \brief An atomic change is used to create and group a set of source edits, +/// An atomic change is used to create and group a set of source edits, /// e.g. replacements or header insertions. Edits in an AtomicChange should be /// related, e.g. replacements for the same type reference and the corresponding /// header insertion/deletion. @@ -36,13 +36,13 @@ namespace tooling { /// bad, i.e. none of its source edits will be applied. class AtomicChange { public: - /// \brief Creates an atomic change around \p KeyPosition with the key being a + /// Creates an atomic change around \p KeyPosition with the key being a /// concatenation of the file name and the offset of \p KeyPosition. /// \p KeyPosition should be the location of the key syntactical element that /// is being changed, e.g. the call to a refactored method. AtomicChange(const SourceManager &SM, SourceLocation KeyPosition); - /// \brief Creates an atomic change for \p FilePath with a customized key. + /// Creates an atomic change for \p FilePath with a customized key. AtomicChange(llvm::StringRef FilePath, llvm::StringRef Key) : Key(Key), FilePath(FilePath) {} @@ -54,44 +54,44 @@ public: bool operator==(const AtomicChange &Other) const; - /// \brief Returns the atomic change as a YAML string. + /// Returns the atomic change as a YAML string. std::string toYAMLString(); - /// \brief Converts a YAML-encoded automic change to AtomicChange. + /// Converts a YAML-encoded automic change to AtomicChange. static AtomicChange convertFromYAML(llvm::StringRef YAMLContent); - /// \brief Returns the key of this change, which is a concatenation of the + /// Returns the key of this change, which is a concatenation of the /// file name and offset of the key position. const std::string &getKey() const { return Key; } - /// \brief Returns the path of the file containing this atomic change. + /// Returns the path of the file containing this atomic change. const std::string &getFilePath() const { return FilePath; } - /// \brief If this change could not be created successfully, e.g. because of + /// If this change could not be created successfully, e.g. because of /// conflicts among replacements, use this to set an error description. /// Thereby, places that cannot be fixed automatically can be gathered when /// applying changes. void setError(llvm::StringRef Error) { this->Error = Error; } - /// \brief Returns whether an error has been set on this list. + /// Returns whether an error has been set on this list. bool hasError() const { return !Error.empty(); } - /// \brief Returns the error message or an empty string if it does not exist. + /// Returns the error message or an empty string if it does not exist. const std::string &getError() const { return Error; } - /// \brief Adds a replacement that replaces the given Range with + /// Adds a replacement that replaces the given Range with /// ReplacementText. /// \returns An llvm::Error carrying ReplacementError on error. llvm::Error replace(const SourceManager &SM, const CharSourceRange &Range, llvm::StringRef ReplacementText); - /// \brief Adds a replacement that replaces range [Loc, Loc+Length) with + /// Adds a replacement that replaces range [Loc, Loc+Length) with /// \p Text. /// \returns An llvm::Error carrying ReplacementError on error. llvm::Error replace(const SourceManager &SM, SourceLocation Loc, unsigned Length, llvm::StringRef Text); - /// \brief Adds a replacement that inserts \p Text at \p Loc. If this + /// Adds a replacement that inserts \p Text at \p Loc. If this /// insertion conflicts with an existing insertion (at the same position), /// this will be inserted before/after the existing insertion depending on /// \p InsertAfter. Users should use `replace` with `Length=0` instead if they @@ -102,15 +102,15 @@ public: llvm::Error insert(const SourceManager &SM, SourceLocation Loc, llvm::StringRef Text, bool InsertAfter = true); - /// \brief Adds a header into the file that contains the key position. + /// Adds a header into the file that contains the key position. /// Header can be in angle brackets or double quotation marks. By default /// (header is not quoted), header will be surrounded with double quotes. void addHeader(llvm::StringRef Header); - /// \brief Removes a header from the file that contains the key position. + /// Removes a header from the file that contains the key position. void removeHeader(llvm::StringRef Header); - /// \brief Returns a const reference to existing replacements. + /// Returns a const reference to existing replacements. const Replacements &getReplacements() const { return Replaces; } llvm::ArrayRef<std::string> getInsertedHeaders() const { @@ -158,7 +158,7 @@ struct ApplyChangesSpec { FormatOption Format = kNone; }; -/// \brief Applies all AtomicChanges in \p Changes to the \p Code. +/// Applies all AtomicChanges in \p Changes to the \p Code. /// /// This completely ignores the file path in each change and replaces them with /// \p FilePath, i.e. callers are responsible for ensuring all changes are for diff --git a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h index d96ad78ad8768..d2d47ddc2c61c 100644 --- a/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h +++ b/include/clang/Tooling/Refactoring/RecursiveSymbolVisitor.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief A wrapper class around \c RecursiveASTVisitor that visits each +/// A wrapper class around \c RecursiveASTVisitor that visits each /// occurrences of a named symbol. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Tooling/Refactoring/RefactoringActionRule.h b/include/clang/Tooling/Refactoring/RefactoringActionRule.h index 4130e29d8dea5..ce4a91cbbadce 100644 --- a/include/clang/Tooling/Refactoring/RefactoringActionRule.h +++ b/include/clang/Tooling/Refactoring/RefactoringActionRule.h @@ -56,7 +56,7 @@ public: class RefactoringActionRule : public RefactoringActionRuleBase { public: /// Returns true when the rule has a source selection requirement that has - /// to be fullfilled before refactoring can be performed. + /// to be fulfilled before refactoring can be performed. virtual bool hasSelectionRequirement() = 0; /// Traverses each refactoring option used by the rule and invokes the diff --git a/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h index fe7738e734997..005eb877bf0fd 100644 --- a/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h +++ b/include/clang/Tooling/Refactoring/RefactoringResultConsumer.h @@ -26,8 +26,8 @@ class RefactoringResultConsumer { public: virtual ~RefactoringResultConsumer() {} - /// Handles an initation or an invication error. An initiation error typically - /// has a \c DiagnosticError payload that describes why initation failed. + /// Handles an initiation or an invication error. An initiation error typically + /// has a \c DiagnosticError payload that describes why initiation failed. virtual void handleError(llvm::Error Err) = 0; /// Handles the source replacements that are produced by a refactoring action. diff --git a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h index 734b624d777ba..5771a1c2d1328 100644 --- a/include/clang/Tooling/Refactoring/Rename/RenamingAction.h +++ b/include/clang/Tooling/Refactoring/Rename/RenamingAction.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Provides an action to rename every symbol at a point. +/// Provides an action to rename every symbol at a point. /// //===----------------------------------------------------------------------===// @@ -82,7 +82,7 @@ private: Expected<AtomicChanges> createSourceReplacements(RefactoringRuleContext &Context) override; - // A NamedDecl which indentifies the the symbol being renamed. + // A NamedDecl which identifies the symbol being renamed. const NamedDecl *ND; // The new qualified name to change the symbol to. std::string NewQualifiedName; diff --git a/include/clang/Tooling/Refactoring/Rename/SymbolName.h b/include/clang/Tooling/Refactoring/Rename/SymbolName.h index e69d2908b5d30..42e0a5cb6697d 100644 --- a/include/clang/Tooling/Refactoring/Rename/SymbolName.h +++ b/include/clang/Tooling/Refactoring/Rename/SymbolName.h @@ -21,7 +21,7 @@ namespace tooling { /// A name of a symbol. /// /// Symbol's name can be composed of multiple strings. For example, Objective-C -/// methods can contain multiple argument lables: +/// methods can contain multiple argument labels: /// /// \code /// - (void) myMethodNamePiece: (int)x anotherNamePieces:(int)y; diff --git a/include/clang/Tooling/Refactoring/Rename/USRFinder.h b/include/clang/Tooling/Refactoring/Rename/USRFinder.h index b74a5d7f70af3..3622bd0daf855 100644 --- a/include/clang/Tooling/Refactoring/Rename/USRFinder.h +++ b/include/clang/Tooling/Refactoring/Rename/USRFinder.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Methods for determining the USR of a symbol at a location in source +/// Methods for determining the USR of a symbol at a location in source /// code. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h index f1c5ae60f875c..ebc9790e9cb63 100644 --- a/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h +++ b/include/clang/Tooling/Refactoring/Rename/USRFindingAction.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Provides an action to find all relevant USRs at a point. +/// Provides an action to find all relevant USRs at a point. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h index 801a8ad9e99c6..e1228e9f39f76 100644 --- a/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h +++ b/include/clang/Tooling/Refactoring/Rename/USRLocFinder.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief Provides functionality for finding all instances of a USR in a given +/// Provides functionality for finding all instances of a USR in a given /// AST. /// //===----------------------------------------------------------------------===// diff --git a/include/clang/Tooling/RefactoringCallbacks.h b/include/clang/Tooling/RefactoringCallbacks.h index 9862951149a3a..2137e0035d629 100644 --- a/include/clang/Tooling/RefactoringCallbacks.h +++ b/include/clang/Tooling/RefactoringCallbacks.h @@ -35,7 +35,7 @@ namespace clang { namespace tooling { -/// \brief Base class for RefactoringCallbacks. +/// Base class for RefactoringCallbacks. /// /// Collects \c tooling::Replacements while running. class RefactoringCallback : public ast_matchers::MatchFinder::MatchCallback { @@ -47,7 +47,7 @@ protected: Replacements Replace; }; -/// \brief Adaptor between \c ast_matchers::MatchFinder and \c +/// Adaptor between \c ast_matchers::MatchFinder and \c /// tooling::RefactoringTool. /// /// Runs AST matchers and stores the \c tooling::Replacements in a map. @@ -74,7 +74,7 @@ private: std::map<std::string, Replacements> &FileToReplaces; }; -/// \brief Replace the text of the statement bound to \c FromId with the text in +/// Replace the text of the statement bound to \c FromId with the text in /// \c ToText. class ReplaceStmtWithText : public RefactoringCallback { public: @@ -86,7 +86,7 @@ private: std::string ToText; }; -/// \brief Replace the text of an AST node bound to \c FromId with the result of +/// Replace the text of an AST node bound to \c FromId with the result of /// evaluating the template in \c ToTemplate. /// /// Expressions of the form ${NodeName} in \c ToTemplate will be @@ -109,7 +109,7 @@ private: std::vector<TemplateElement> Template; }; -/// \brief Replace the text of the statement bound to \c FromId with the text of +/// Replace the text of the statement bound to \c FromId with the text of /// the statement bound to \c ToId. class ReplaceStmtWithStmt : public RefactoringCallback { public: @@ -121,7 +121,7 @@ private: std::string ToId; }; -/// \brief Replace an if-statement bound to \c Id with the outdented text of its +/// Replace an if-statement bound to \c Id with the outdented text of its /// body, choosing the consequent or the alternative based on whether /// \c PickTrueBranch is true. class ReplaceIfStmtWithItsBody : public RefactoringCallback { diff --git a/include/clang/Tooling/ReplacementsYaml.h b/include/clang/Tooling/ReplacementsYaml.h index 0b1dc4c774231..8e41525a9412a 100644 --- a/include/clang/Tooling/ReplacementsYaml.h +++ b/include/clang/Tooling/ReplacementsYaml.h @@ -8,7 +8,7 @@ //===----------------------------------------------------------------------===// /// /// \file -/// \brief This file defines the structure of a YAML document for serializing +/// This file defines the structure of a YAML document for serializing /// replacements. /// //===----------------------------------------------------------------------===// @@ -25,10 +25,10 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(clang::tooling::Replacement) namespace llvm { namespace yaml { -/// \brief Specialized MappingTraits to describe how a Replacement is +/// Specialized MappingTraits to describe how a Replacement is /// (de)serialized. template <> struct MappingTraits<clang::tooling::Replacement> { - /// \brief Helper to (de)serialize a Replacement since we don't have direct + /// Helper to (de)serialize a Replacement since we don't have direct /// access to its data members. struct NormalizedReplacement { NormalizedReplacement(const IO &) @@ -59,7 +59,7 @@ template <> struct MappingTraits<clang::tooling::Replacement> { } }; -/// \brief Specialized MappingTraits to describe how a +/// Specialized MappingTraits to describe how a /// TranslationUnitReplacements is (de)serialized. template <> struct MappingTraits<clang::tooling::TranslationUnitReplacements> { static void mapping(IO &Io, diff --git a/include/clang/Tooling/StandaloneExecution.h b/include/clang/Tooling/StandaloneExecution.h index f5f32d737a452..572330e4cc220 100644 --- a/include/clang/Tooling/StandaloneExecution.h +++ b/include/clang/Tooling/StandaloneExecution.h @@ -20,7 +20,7 @@ namespace clang { namespace tooling { -/// \brief A standalone executor that runs FrontendActions on a given set of +/// A standalone executor that runs FrontendActions on a given set of /// TUs in sequence. /// /// By default, this executor uses the following arguments adjusters (as defined @@ -32,15 +32,16 @@ class StandaloneToolExecutor : public ToolExecutor { public: static const char *ExecutorName; - /// \brief Init with \p CompilationDatabase and the paths of all files to be + /// Init with \p CompilationDatabase and the paths of all files to be /// proccessed. StandaloneToolExecutor( const CompilationDatabase &Compilations, llvm::ArrayRef<std::string> SourcePaths, + IntrusiveRefCntPtr<vfs::FileSystem> BaseFS = vfs::getRealFileSystem(), std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>()); - /// \brief Init with \p CommonOptionsParser. This is expected to be used by + /// Init with \p CommonOptionsParser. This is expected to be used by /// `createExecutorFromCommandLineArgs` based on commandline options. /// /// The executor takes ownership of \p Options. @@ -58,7 +59,7 @@ public: std::pair<std::unique_ptr<FrontendActionFactory>, ArgumentsAdjuster>> Actions) override; - /// \brief Set a \c DiagnosticConsumer to use during parsing. + /// Set a \c DiagnosticConsumer to use during parsing. void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { Tool.setDiagnosticConsumer(DiagConsumer); } @@ -75,7 +76,7 @@ public: Tool.mapVirtualFile(FilePath, Content); } - /// \brief Returns the file manager used in the tool. + /// Returns the file manager used in the tool. /// /// The file manager is shared between all translation units. FileManager &getFiles() { return Tool.getFiles(); } diff --git a/include/clang/Tooling/ToolExecutorPluginRegistry.h b/include/clang/Tooling/ToolExecutorPluginRegistry.h index 11ba89546e9ea..921689dff86f1 100644 --- a/include/clang/Tooling/ToolExecutorPluginRegistry.h +++ b/include/clang/Tooling/ToolExecutorPluginRegistry.h @@ -1,4 +1,4 @@ -//===--- ToolExecutorPluginRegistry.h - -------------------------*- C++ -*-===// +//===- ToolExecutorPluginRegistry.h -----------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -16,9 +16,9 @@ namespace clang { namespace tooling { -typedef llvm::Registry<ToolExecutorPlugin> ToolExecutorPluginRegistry; +using ToolExecutorPluginRegistry = llvm::Registry<ToolExecutorPlugin>; -} // end namespace tooling -} // end namespace clang +} // namespace tooling +} // namespace clang #endif // LLVM_CLANG_TOOLING_TOOLEXECUTORPLUGINREGISTRY_H diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index e64be07d9ab44..c056894b1a7af 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -1,4 +1,4 @@ -//===--- Tooling.h - Framework for standalone Clang tools -------*- C++ -*-===// +//===- Tooling.h - Framework for standalone Clang tools ---------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -31,35 +31,43 @@ #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" -#include "clang/Driver/Util.h" +#include "clang/Basic/VirtualFileSystem.h" #include "clang/Frontend/FrontendAction.h" #include "clang/Frontend/PCHContainerOperations.h" -#include "clang/Lex/ModuleLoader.h" #include "clang/Tooling/ArgumentsAdjusters.h" -#include "clang/Tooling/CompilationDatabase.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/IntrusiveRefCntPtr.h" #include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/StringSet.h" #include "llvm/ADT/Twine.h" #include "llvm/Option/Option.h" #include <memory> #include <string> +#include <utility> #include <vector> namespace clang { +class CompilerInstance; +class CompilerInvocation; +class DiagnosticConsumer; +class DiagnosticsEngine; +class SourceManager; + namespace driver { + class Compilation; -} // end namespace driver -class CompilerInvocation; -class SourceManager; -class FrontendAction; +} // namespace driver namespace tooling { -/// \brief Interface to process a clang::CompilerInvocation. +class CompilationDatabase; + +/// Interface to process a clang::CompilerInvocation. /// /// If your tool is based on FrontendAction, you should be deriving from /// FrontendActionFactory instead. @@ -67,15 +75,15 @@ class ToolAction { public: virtual ~ToolAction(); - /// \brief Perform an action for an invocation. + /// Perform an action for an invocation. virtual bool - runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation, + runInvocation(std::shared_ptr<CompilerInvocation> Invocation, FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticConsumer *DiagConsumer) = 0; }; -/// \brief Interface to generate clang::FrontendActions. +/// Interface to generate clang::FrontendActions. /// /// Having a factory interface allows, for example, a new FrontendAction to be /// created for each translation unit processed by ClangTool. This class is @@ -85,19 +93,19 @@ class FrontendActionFactory : public ToolAction { public: ~FrontendActionFactory() override; - /// \brief Invokes the compiler with a FrontendAction created by create(). - bool runInvocation(std::shared_ptr<clang::CompilerInvocation> Invocation, + /// Invokes the compiler with a FrontendAction created by create(). + bool runInvocation(std::shared_ptr<CompilerInvocation> Invocation, FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps, DiagnosticConsumer *DiagConsumer) override; - /// \brief Returns a new clang::FrontendAction. + /// Returns a new clang::FrontendAction. /// /// The caller takes ownership of the returned action. - virtual clang::FrontendAction *create() = 0; + virtual FrontendAction *create() = 0; }; -/// \brief Returns a new FrontendActionFactory for a given type. +/// Returns a new FrontendActionFactory for a given type. /// /// T must derive from clang::FrontendAction. /// @@ -107,25 +115,25 @@ public: template <typename T> std::unique_ptr<FrontendActionFactory> newFrontendActionFactory(); -/// \brief Callbacks called before and after each source file processed by a +/// Callbacks called before and after each source file processed by a /// FrontendAction created by the FrontedActionFactory returned by \c /// newFrontendActionFactory. class SourceFileCallbacks { public: - virtual ~SourceFileCallbacks() {} + virtual ~SourceFileCallbacks() = default; - /// \brief Called before a source file is processed by a FrontEndAction. + /// Called before a source file is processed by a FrontEndAction. /// \see clang::FrontendAction::BeginSourceFileAction virtual bool handleBeginSource(CompilerInstance &CI) { return true; } - /// \brief Called after a source file is processed by a FrontendAction. + /// Called after a source file is processed by a FrontendAction. /// \see clang::FrontendAction::EndSourceFileAction virtual void handleEndSource() {} }; -/// \brief Returns a new FrontendActionFactory for any type that provides an +/// Returns a new FrontendActionFactory for any type that provides an /// implementation of newASTConsumer(). /// /// FactoryT must implement: ASTConsumer *newASTConsumer(). @@ -140,7 +148,7 @@ template <typename FactoryT> inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks = nullptr); -/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. +/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. /// /// \param ToolAction The action to run over the code. /// \param Code C++ code. @@ -149,16 +157,16 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( /// clang modules. /// /// \return - True if 'ToolAction' was successfully executed. -bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, +bool runToolOnCode(FrontendAction *ToolAction, const Twine &Code, const Twine &FileName = "input.cc", std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>()); /// 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; +using FileContentMappings = std::vector<std::pair<std::string, std::string>>; -/// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and +/// Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag and /// with additional other flags. /// /// \param ToolAction The action to run over the code. @@ -172,14 +180,23 @@ typedef std::vector<std::pair<std::string, std::string>> FileContentMappings; /// /// \return - True if 'ToolAction' was successfully executed. bool runToolOnCodeWithArgs( - clang::FrontendAction *ToolAction, const Twine &Code, + FrontendAction *ToolAction, const Twine &Code, const std::vector<std::string> &Args, const Twine &FileName = "input.cc", const Twine &ToolName = "clang-tool", std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>(), const FileContentMappings &VirtualMappedFiles = FileContentMappings()); -/// \brief Builds an AST for 'Code'. +// Similar to the overload except this takes a VFS. +bool runToolOnCodeWithArgs( + FrontendAction *ToolAction, const Twine &Code, + llvm::IntrusiveRefCntPtr<vfs::FileSystem> VFS, + const std::vector<std::string> &Args, const Twine &FileName = "input.cc", + const Twine &ToolName = "clang-tool", + std::shared_ptr<PCHContainerOperations> PCHContainerOps = + std::make_shared<PCHContainerOperations>()); + +/// Builds an AST for 'Code'. /// /// \param Code C++ code. /// \param FileName The file name which 'Code' will be mapped as. @@ -192,7 +209,7 @@ buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc", std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>()); -/// \brief Builds an AST for 'Code' with additional flags. +/// Builds an AST for 'Code' with additional flags. /// /// \param Code C++ code. /// \param Args Additional flags to pass on. @@ -212,10 +229,10 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs( std::make_shared<PCHContainerOperations>(), ArgumentsAdjuster Adjuster = getClangStripDependencyFileAdjuster()); -/// \brief Utility to run a FrontendAction in a single clang invocation. +/// Utility to run a FrontendAction in a single clang invocation. class ToolInvocation { public: - /// \brief Create a tool invocation. + /// Create a tool invocation. /// /// \param CommandLine The command line arguments to clang. Note that clang /// uses its binary name (CommandLine[0]) to locate its builtin headers. @@ -231,7 +248,7 @@ public: std::shared_ptr<PCHContainerOperations> PCHContainerOps = std::make_shared<PCHContainerOperations>()); - /// \brief Create a tool invocation. + /// Create a tool invocation. /// /// \param CommandLine The command line arguments to clang. /// \param Action The action to be executed. @@ -244,19 +261,19 @@ public: ~ToolInvocation(); - /// \brief Set a \c DiagnosticConsumer to use during parsing. + /// Set a \c DiagnosticConsumer to use during parsing. void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { this->DiagConsumer = DiagConsumer; } - /// \brief Map a virtual file to be used while running the tool. + /// Map a virtual file to be used while running the tool. /// /// \param FilePath The path at which the content will be mapped. /// \param Content A null terminated buffer of the file's content. // FIXME: remove this when all users have migrated! void mapVirtualFile(StringRef FilePath, StringRef Content); - /// \brief Run the clang invocation. + /// Run the clang invocation. /// /// \returns True if there were no errors during execution. bool run(); @@ -265,8 +282,8 @@ public: void addFileMappingsTo(SourceManager &SourceManager); bool runInvocation(const char *BinaryName, - clang::driver::Compilation *Compilation, - std::shared_ptr<clang::CompilerInvocation> Invocation, + driver::Compilation *Compilation, + std::shared_ptr<CompilerInvocation> Invocation, std::shared_ptr<PCHContainerOperations> PCHContainerOps); std::vector<std::string> CommandLine; @@ -276,10 +293,10 @@ public: std::shared_ptr<PCHContainerOperations> PCHContainerOps; // Maps <file name> -> <file content>. llvm::StringMap<StringRef> MappedFileContents; - DiagnosticConsumer *DiagConsumer; + DiagnosticConsumer *DiagConsumer = nullptr; }; -/// \brief Utility to run a FrontendAction over a set of files. +/// Utility to run a FrontendAction over a set of files. /// /// This class is written to be usable for command line utilities. /// By default the class uses ClangSyntaxOnlyAdjuster to modify @@ -287,8 +304,8 @@ public: /// a frontend action. One could install an additional command line /// arguments adjuster by calling the appendArgumentsAdjuster() method. class ClangTool { - public: - /// \brief Constructs a clang tool to run over a list of files. +public: + /// Constructs a clang tool to run over a list of files. /// /// \param Compilations The CompilationDatabase which contains the compile /// command lines for the given source paths. @@ -296,43 +313,50 @@ class ClangTool { /// not found in Compilations, it is skipped. /// \param PCHContainerOps The PCHContainerOperations for loading and creating /// clang modules. + /// \param BaseFS VFS used for all underlying file accesses when running the + /// tool. ClangTool(const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths, std::shared_ptr<PCHContainerOperations> PCHContainerOps = - std::make_shared<PCHContainerOperations>()); + std::make_shared<PCHContainerOperations>(), + IntrusiveRefCntPtr<vfs::FileSystem> BaseFS = + vfs::getRealFileSystem()); ~ClangTool(); - /// \brief Set a \c DiagnosticConsumer to use during parsing. + /// Set a \c DiagnosticConsumer to use during parsing. void setDiagnosticConsumer(DiagnosticConsumer *DiagConsumer) { this->DiagConsumer = DiagConsumer; } - /// \brief Map a virtual file to be used while running the tool. + /// Map a virtual file to be used while running the tool. /// /// \param FilePath The path at which the content will be mapped. /// \param Content A null terminated buffer of the file's content. void mapVirtualFile(StringRef FilePath, StringRef Content); - /// \brief Append a command line arguments adjuster to the adjuster chain. + /// 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); - /// \brief Clear the command line arguments adjuster chain. + /// Clear the command line arguments adjuster chain. void clearArgumentsAdjusters(); /// Runs an action over all files specified in the command line. /// /// \param Action Tool action. + /// + /// \returns 0 on success; 1 if any error occurred; 2 if there is no error but + /// some files are skipped due to missing compile commands. int run(ToolAction *Action); - /// \brief Create an AST for each file specified in the command line and + /// Create an AST for each file specified in the command line and /// append them to ASTs. int buildASTs(std::vector<std::unique_ptr<ASTUnit>> &ASTs); - /// \brief Returns the file manager used in the tool. + /// Returns the file manager used in the tool. /// /// The file manager is shared between all translation units. FileManager &getFiles() { return *Files; } @@ -347,20 +371,22 @@ private: llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem; llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem; llvm::IntrusiveRefCntPtr<FileManager> Files; + // Contains a list of pairs (<file name>, <file content>). - std::vector< std::pair<StringRef, StringRef> > MappedFileContents; + std::vector<std::pair<StringRef, StringRef>> MappedFileContents; + llvm::StringSet<> SeenWorkingDirectories; ArgumentsAdjuster ArgsAdjuster; - DiagnosticConsumer *DiagConsumer; + DiagnosticConsumer *DiagConsumer = nullptr; }; template <typename T> std::unique_ptr<FrontendActionFactory> newFrontendActionFactory() { class SimpleFrontendActionFactory : public FrontendActionFactory { public: - clang::FrontendAction *create() override { return new T; } + FrontendAction *create() override { return new T; } }; return std::unique_ptr<FrontendActionFactory>( @@ -374,36 +400,37 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( public: explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) - : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} + : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} - clang::FrontendAction *create() override { + FrontendAction *create() override { return new ConsumerFactoryAdaptor(ConsumerFactory, Callbacks); } private: - class ConsumerFactoryAdaptor : public clang::ASTFrontendAction { + class ConsumerFactoryAdaptor : public ASTFrontendAction { public: ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, SourceFileCallbacks *Callbacks) - : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} + : ConsumerFactory(ConsumerFactory), Callbacks(Callbacks) {} - std::unique_ptr<clang::ASTConsumer> - CreateASTConsumer(clang::CompilerInstance &, StringRef) override { + std::unique_ptr<ASTConsumer> + CreateASTConsumer(CompilerInstance &, StringRef) override { return ConsumerFactory->newASTConsumer(); } protected: bool BeginSourceFileAction(CompilerInstance &CI) override { - if (!clang::ASTFrontendAction::BeginSourceFileAction(CI)) + if (!ASTFrontendAction::BeginSourceFileAction(CI)) return false; if (Callbacks) return Callbacks->handleBeginSource(CI); return true; } + void EndSourceFileAction() override { if (Callbacks) Callbacks->handleEndSource(); - clang::ASTFrontendAction::EndSourceFileAction(); + ASTFrontendAction::EndSourceFileAction(); } private: @@ -418,7 +445,7 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( new FrontendActionFactoryAdapter(ConsumerFactory, Callbacks)); } -/// \brief Returns the absolute path of \c File, by prepending it with +/// Returns the absolute path of \c File, by prepending it with /// the current directory if \c File is not absolute. /// /// Otherwise returns \c File. @@ -432,7 +459,7 @@ inline std::unique_ptr<FrontendActionFactory> newFrontendActionFactory( /// \param File Either an absolute or relative path. std::string getAbsolutePath(StringRef File); -/// \brief Changes CommandLine to contain implicit flags that would have been +/// Changes CommandLine to contain implicit flags that would have been /// defined had the compiler driver been invoked through the path InvokedAs. /// /// For example, when called with \c InvokedAs set to `i686-linux-android-g++`, @@ -455,12 +482,12 @@ std::string getAbsolutePath(StringRef File); void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine, StringRef InvokedAs); -/// \brief Creates a \c CompilerInvocation. -clang::CompilerInvocation *newInvocation( - clang::DiagnosticsEngine *Diagnostics, - const llvm::opt::ArgStringList &CC1Args); +/// Creates a \c CompilerInvocation. +CompilerInvocation *newInvocation(DiagnosticsEngine *Diagnostics, + const llvm::opt::ArgStringList &CC1Args); + +} // namespace tooling -} // end namespace tooling -} // end namespace clang +} // namespace clang #endif // LLVM_CLANG_TOOLING_TOOLING_H diff --git a/include/clang/module.modulemap b/include/clang/module.modulemap index 4097ad2dc7164..8d525c5ffbacd 100644 --- a/include/clang/module.modulemap +++ b/include/clang/module.modulemap @@ -42,6 +42,7 @@ module Clang_Basic { textual header "Basic/BuiltinsX86_64.def" textual header "Basic/BuiltinsXCore.def" textual header "Basic/DiagnosticOptions.def" + textual header "Basic/Features.def" textual header "Basic/LangOptions.def" textual header "Basic/OpenCLExtensions.def" textual header "Basic/OpenCLImageTypes.def" @@ -153,3 +154,8 @@ module Clang_ToolingCore { requires cplusplus umbrella "Tooling/Core" module * { export * } } + +module Clang_ToolingInclusions { + requires cplusplus + umbrella "Tooling/Inclusions" module * { export * } +} |